/**
 * @deprecated 此服务已弃用，请使用新的登录服务架构
 * 
 * 新的登录服务已按平台拆分，请使用以下方式：
 * 
 * @example
 * ```typescript
 * // 使用统一的登录服务管理器
 * import { loginServiceManager } from './login';
 * 
 * // 启动登录会话
 * const { sessionId } = await loginServiceManager.startLoginSession('douyin', userId);
 * 
 * // 监听登录结果
 * loginServiceManager.on('loginResult', (event) => {
 *   console.log('登录结果:', event);
 * });
 * ```
 * 
 * 各平台独立服务：
 * - DouyinLoginService - 抖音登录
 * - XiaohongshuLoginService - 小红书登录
 * - WeixinVideoLoginService - 视频号登录
 * - BaijiahaoLoginService - 百家号登录
 * 
 * @see {@link ./login/LoginServiceManager.ts} 新的登录服务管理器
 * @see {@link ./login/BaseLoginService.ts} 登录服务基类
 */

/// <reference lib="dom" />
import { chromium, type Browser, type BrowserContext, type Page } from 'playwright';
import { EventEmitter } from 'events';
import { logger } from '../utils/logger.js';
import { CookieManager } from '../automation/cookie.js';
import { AILoginAssistant, type AILoginMonitorResult } from './AILoginAssistant.js';
import { aiService } from '../ai/index.js';
import type { PlatformType } from '@media-manager/shared';

// CookieManager 使用静态方法

// 平台配置
const PLATFORM_CONFIG: Record<string, {
  loginUrl: string;
  successIndicators: string[]; // 登录成功后URL包含的关键词
  cookieDomain: string;
  loginCookies?: string[]; // 登录成功后应该存在的Cookie名称
}> = {
  douyin: {
    loginUrl: 'https://creator.douyin.com/',
    successIndicators: ['/creator-micro/home', '/creator/home', 'creator.douyin.com/creator-micro'],
    cookieDomain: '.douyin.com',
    loginCookies: ['sessionid', 'sessionid_ss', 'passport_csrf_token'],
  },
  kuaishou: {
    loginUrl: 'https://cp.kuaishou.com/',
    successIndicators: ['/article/publish', '/profile'],
    cookieDomain: '.kuaishou.com',
  },
  bilibili: {
    loginUrl: 'https://member.bilibili.com/platform/home',
    successIndicators: ['/platform/home', '/platform/upload'],
    cookieDomain: '.bilibili.com',
  },
  xiaohongshu: {
    loginUrl: 'https://creator.xiaohongshu.com/',
    successIndicators: ['/creator/home', '/publish'],
    cookieDomain: '.xiaohongshu.com',
  },
  weixin: {
    loginUrl: 'https://channels.weixin.qq.com/platform',
    successIndicators: ['/platform/post', '/platform/home'],
    cookieDomain: '.qq.com',
  },
  toutiao: {
    loginUrl: 'https://mp.toutiao.com/',
    successIndicators: ['/profile_v4/index', '/profile'],
    cookieDomain: '.toutiao.com',
  },
  baijiahao: {
    loginUrl: 'https://baijiahao.baidu.com/',
    successIndicators: ['/builder/rc/home', '/builder'],
    cookieDomain: '.baidu.com',
  },
  penguin: {
    loginUrl: 'https://om.qq.com/',
    successIndicators: ['/userAuth/index', '/material'],
    cookieDomain: '.qq.com',
  },
  dayuhao: {
    loginUrl: 'https://mp.dayu.com/',
    successIndicators: ['/dashboard', '/home'],
    cookieDomain: '.dayu.com',
  },
};

interface WorkItem {
  videoId?: string;
  title: string;
  coverUrl: string;
  duration: string;
  publishTime: string;
  status: string;
  playCount: number;
  likeCount: number;
  commentCount: number;
  shareCount: number;
}

interface AccountInfo {
  accountId: string;
  accountName: string;
  avatarUrl: string;
  fansCount: number;
  worksCount: number;
  worksList?: WorkItem[];
}

interface LoginSession {
  id: string;
  userId?: number;
  platform: PlatformType;
  browser: Browser;
  context: BrowserContext;
  page: Page;
  status: 'pending' | 'fetching' | 'success' | 'failed' | 'timeout' | 'cancelled';
  cookies?: string;
  accountInfo?: AccountInfo;
  error?: string;
  createdAt: Date;
  aiAssistant?: AILoginAssistant;
  lastAIAnalysis?: AILoginMonitorResult;
}

/**
 * @deprecated 请使用 loginServiceManager 代替
 * @see {@link ./login/LoginServiceManager.ts}
 */
class BrowserLoginService extends EventEmitter {
  private sessions: Map<string, LoginSession> = new Map();

  /**
   * 开始浏览器登录会话
   * @param platform 平台类型
   * @param userId 可选的用户ID，用于通过 WebSocket 推送状态
   */
  async startLoginSession(platform: PlatformType, userId?: number): Promise<{ sessionId: string; message: string }> {
    const config = PLATFORM_CONFIG[platform];
    if (!config) {
      throw new Error(`不支持的平台: ${platform}`);
    }

    const sessionId = `login_${platform}_${Date.now()}`;

    try {
      // 启动可见浏览器（非无头模式）
      const browser = await chromium.launch({
        headless: false,
        args: [
          '--disable-blink-features=AutomationControlled',
          '--window-size=1300,900',
        ],
      });

      const context = await browser.newContext({
        viewport: null, // 使用窗口实际大小
        locale: 'zh-CN',
        timezoneId: 'Asia/Shanghai',
        userAgent: 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36',
      });

      const page = await context.newPage();

      // 创建会话
      const session: LoginSession = {
        id: sessionId,
        userId,
        platform,
        browser,
        context,
        page,
        status: 'pending',
        createdAt: new Date(),
      };

      this.sessions.set(sessionId, session);

      // 导航到登录页
      await page.goto(config.loginUrl, { waitUntil: 'domcontentloaded' });

      // 创建 AI 登录助手（如果 AI 服务可用）
      if (aiService.isAvailable()) {
        session.aiAssistant = new AILoginAssistant(page, platform, sessionId);
        logger.info(`[BrowserLogin] AI assistant created for session: ${sessionId}`);
      }

      // 开始监控登录状态（同时使用传统方法和 AI 方法）
      this.monitorLoginStatus(sessionId, config);

      // 如果 AI 可用，启动 AI 监控
      if (session.aiAssistant) {
        this.startAIMonitoring(sessionId);
      }

      // 设置超时（5分钟）
      setTimeout(() => {
        this.handleTimeout(sessionId);
      }, 5 * 60 * 1000);

      logger.info(`Browser login session started: ${sessionId} for platform: ${platform}`);

      return {
        sessionId,
        message: `已打开 ${platform} 登录页面，请在浏览器中完成登录${aiService.isAvailable() ? '（AI 辅助已启用）' : ''}`,
      };
    } catch (error) {
      logger.error(`Failed to start login session for ${platform}:`, error);
      throw error;
    }
  }

  /**
   * 监控登录状态
   */
  private async monitorLoginStatus(
    sessionId: string,
    config: typeof PLATFORM_CONFIG[string]
  ): Promise<void> {
    const session = this.sessions.get(sessionId);
    if (!session || !session.page) return;

    // 先等待页面初始加载
    await session.page.waitForTimeout(2000);

    const initialUrl = session.page.url();
    logger.info(`Initial URL for ${sessionId}: ${initialUrl}`);

    const checkInterval = setInterval(async () => {
      try {
        const currentSession = this.sessions.get(sessionId);
        if (!currentSession || currentSession.status !== 'pending') {
          clearInterval(checkInterval);
          return;
        }

        const url = currentSession.page.url();

        // 检查是否仍在登录页面
        const onLoginPage = url.includes('login') || url.includes('passport') || url.includes('sso');
        if (onLoginPage) {
          return; // 仍在登录页面，继续等待
        }

        // 检查URL是否包含登录成功标识
        const urlMatched = config.successIndicators.some(indicator =>
          url.includes(indicator)
        );

        // URL匹配成功标识后，还需要检查是否有二次校验弹框
        if (urlMatched) {
          // 检查是否有二次校验弹框（抖音等平台可能需要短信验证或刷脸验证）
          const hasSecondaryVerification = await this.checkSecondaryVerification(currentSession.page, currentSession.platform);

          if (hasSecondaryVerification) {
            logger.info(`Secondary verification detected for ${sessionId}, waiting for user to complete...`);
            // 继续等待，不判断为登录成功
            return;
          }

          logger.info(`Login success detected for ${sessionId}, URL: ${url}`);
          clearInterval(checkInterval);

          // 对于视频号，必须先导航到首页获取视频号ID（iframe页面没有）
          const isWeixinVideo = currentSession.platform === 'weixin' || currentSession.platform === 'weixin_video';
          if (isWeixinVideo && (url.includes('iframe') || !url.includes('/platform/home'))) {
            logger.info(`[BrowserLogin] Weixin video URL detection: navigating to home page first...`);
            const homeUrl = 'https://channels.weixin.qq.com/platform/home';

            for (let navAttempt = 1; navAttempt <= 3; navAttempt++) {
              try {
                logger.info(`[BrowserLogin] URL Monitor: Navigation attempt ${navAttempt}/3`);
                await currentSession.page.goto(homeUrl, {
                  waitUntil: 'domcontentloaded',
                  timeout: 30000
                });

                const newUrl = currentSession.page.url();
                logger.info(`[BrowserLogin] URL Monitor: After navigation, URL: ${newUrl}`);

                if (newUrl.includes('/platform/home') || newUrl.includes('/platform')) {
                  // 等待页面加载
                  await currentSession.page.waitForLoadState('networkidle', { timeout: 15000 }).catch(() => { });
                  await currentSession.page.waitForTimeout(3000);

                  // 等待视频号ID元素
                  try {
                    await Promise.race([
                      currentSession.page.waitForSelector('#finder-uid-copy', { timeout: 10000 }),
                      currentSession.page.waitForSelector('.finder-uniq-id', { timeout: 10000 }),
                    ]);
                    logger.info(`[BrowserLogin] URL Monitor: Account elements found`);
                    break;
                  } catch {
                    logger.warn(`[BrowserLogin] URL Monitor: Account elements not found on attempt ${navAttempt}`);
                  }
                }
              } catch (e) {
                logger.error(`[BrowserLogin] URL Monitor: Navigation attempt ${navAttempt} failed:`, e);
              }

              if (navAttempt < 3) {
                await currentSession.page.waitForTimeout(2000);
              }
            }
          }

          await this.handleLoginSuccess(sessionId);
        }
      } catch (error) {
        // 页面可能已关闭
        clearInterval(checkInterval);
        const currentSession = this.sessions.get(sessionId);
        if (currentSession && currentSession.status === 'pending') {
          currentSession.status = 'failed';
          currentSession.error = '浏览器已关闭';
          this.emit('loginResult', { sessionId, userId: currentSession.userId, status: 'failed', error: '浏览器已关闭' });
        }
      }
    }, 1000); // 检查间隔改为1秒，更快响应
  }

  /**
   * 启动 AI 登录状态监控
   */
  private startAIMonitoring(sessionId: string): void {
    const session = this.sessions.get(sessionId);
    if (!session || !session.aiAssistant) return;

    logger.info(`[BrowserLogin] Starting AI monitoring for session: ${sessionId}`);

    session.aiAssistant.startMonitoring(
      async (result: AILoginMonitorResult) => {
        const currentSession = this.sessions.get(sessionId);
        if (!currentSession || currentSession.status !== 'pending') {
          currentSession?.aiAssistant?.stopMonitoring();
          return;
        }

        // 保存最新的 AI 分析结果
        currentSession.lastAIAnalysis = result;

        // 发送 AI 分析状态更新（包含 userId 以便 WebSocket 推送）
        this.emit('aiAnalysis', {
          sessionId,
          userId: currentSession.userId,
          ...result,
        });

        logger.info(`[BrowserLogin] AI analysis for ${sessionId}:`, {
          status: result.status,
          isLoggedIn: result.analysis.isLoggedIn,
          hasVerification: result.analysis.hasVerification,
          pageDescription: result.analysis.pageDescription?.substring(0, 80),
        });

        // 如果 AI 检测到登录成功
        if (result.status === 'logged_in' && result.analysis.isLoggedIn) {
          logger.info(`[BrowserLogin] AI detected login success for session: ${sessionId}`);
          // 停止 AI 监控
          currentSession.aiAssistant?.stopMonitoring();

          // 对于视频号，必须导航到首页才能获取视频号ID
          const isWeixinVideo = currentSession.platform === 'weixin' || currentSession.platform === 'weixin_video';
          if (isWeixinVideo) {
            const currentUrl = currentSession.page.url();
            logger.info(`[BrowserLogin] ========== Weixin Video Navigation Start ==========`);
            logger.info(`[BrowserLogin] Current URL: ${currentUrl}`);

            // 视频号必须导航到首页获取ID（iframe页面没有视频号ID）
            const homeUrl = 'https://channels.weixin.qq.com/platform/home';
            let navigationSuccess = false;

            for (let navAttempt = 1; navAttempt <= 3; navAttempt++) {
              logger.info(`[BrowserLogin] Navigation attempt ${navAttempt}/3 to ${homeUrl}`);
              try {
                await currentSession.page.goto(homeUrl, {
                  waitUntil: 'domcontentloaded',
                  timeout: 30000
                });

                const newUrl = currentSession.page.url();
                logger.info(`[BrowserLogin] After navigation, URL: ${newUrl}`);

                // 验证是否真的到了首页
                if (newUrl.includes('/platform/home') || newUrl.includes('/platform')) {
                  logger.info(`[BrowserLogin] Successfully navigated to home page`);

                  // 等待页面加载完成
                  await currentSession.page.waitForLoadState('networkidle', { timeout: 15000 }).catch(() => { });
                  await currentSession.page.waitForTimeout(3000);

                  // 等待视频号ID元素出现
                  try {
                    await Promise.race([
                      currentSession.page.waitForSelector('#finder-uid-copy', { timeout: 10000 }),
                      currentSession.page.waitForSelector('.finder-uniq-id', { timeout: 10000 }),
                    ]);
                    logger.info(`[BrowserLogin] Account info elements found on home page`);
                    navigationSuccess = true;
                    break;
                  } catch {
                    logger.warn(`[BrowserLogin] Account info elements not found on attempt ${navAttempt}`);
                  }
                } else {
                  logger.warn(`[BrowserLogin] Navigation redirected to ${newUrl}, not home page`);
                }
              } catch (e) {
                logger.error(`[BrowserLogin] Navigation attempt ${navAttempt} failed:`, e);
              }

              // 如果不是最后一次尝试，等待一下再重试
              if (navAttempt < 3) {
                await currentSession.page.waitForTimeout(2000);
              }
            }

            if (!navigationSuccess) {
              logger.error(`[BrowserLogin] All navigation attempts failed!`);
            }

            logger.info(`[BrowserLogin] Final URL before handleLoginSuccess: ${currentSession.page.url()}`);
            logger.info(`[BrowserLogin] ========== Weixin Video Navigation End ==========`);
          }

          // 触发登录成功处理
          await this.handleLoginSuccess(sessionId);
        }

        // 如果检测到验证码
        if (result.status === 'verification_needed') {
          logger.info(`[BrowserLogin] AI detected verification for session: ${sessionId}`, {
            type: result.analysis.verificationType,
            description: result.analysis.verificationDescription,
          });
          // 通知前端显示验证码提示
          this.emit('verificationNeeded', {
            sessionId,
            userId: currentSession.userId,
            verificationType: result.analysis.verificationType,
            description: result.analysis.verificationDescription,
            suggestedAction: result.analysis.suggestedAction,
          });
        }
      },
      3000 // API 返回后等待 3 秒再进行下一次分析
    );
  }

  /**
   * 检查是否存在二次校验弹框
   * 不同平台可能有不同的二次校验方式：短信验证码、刷脸验证等
   */
  private async checkSecondaryVerification(page: Page, platform: PlatformType): Promise<boolean> {
    try {
      // 抖音平台的二次校验检测
      if (platform === 'douyin') {
        // 1. 检查"身份验证"弹框
        const verifyTitle = page.getByText('身份验证', { exact: false });
        if (await verifyTitle.count() > 0 && await verifyTitle.first().isVisible().catch(() => false)) {
          logger.info('[BrowserLogin] Found "身份验证" dialog');
          return true;
        }

        // 2. 检查"接收短信验证码"选项
        const smsOption = page.getByText('接收短信验证码', { exact: false });
        if (await smsOption.count() > 0 && await smsOption.first().isVisible().catch(() => false)) {
          logger.info('[BrowserLogin] Found "接收短信验证码" option');
          return true;
        }

        // 3. 检查"手机刷脸验证"选项
        const faceOption = page.getByText('手机刷脸验证', { exact: false });
        if (await faceOption.count() > 0 && await faceOption.first().isVisible().catch(() => false)) {
          logger.info('[BrowserLogin] Found "手机刷脸验证" option');
          return true;
        }

        // 4. 检查"发送短信验证"选项
        const sendSmsOption = page.getByText('发送短信验证', { exact: false });
        if (await sendSmsOption.count() > 0 && await sendSmsOption.first().isVisible().catch(() => false)) {
          logger.info('[BrowserLogin] Found "发送短信验证" option');
          return true;
        }

        // 5. 检查"为保障账号安全"提示文本
        const securityHint = page.getByText('为保障账号安全', { exact: false });
        if (await securityHint.count() > 0 && await securityHint.first().isVisible().catch(() => false)) {
          logger.info('[BrowserLogin] Found security verification hint');
          return true;
        }

        // 6. 检查页面内容
        const pageContent = await page.content().catch(() => '');
        if ((pageContent.includes('身份验证') || pageContent.includes('为保障账号安全')) &&
          (pageContent.includes('接收短信验证码') || pageContent.includes('手机刷脸验证') || pageContent.includes('发送短信验证'))) {
          logger.info('[BrowserLogin] Found secondary verification in page content');
          return true;
        }
      }

      // 其他平台的二次校验检测可以在这里添加
      // 通用检测：检查常见的验证弹框
      const commonVerifySelectors = [
        '[class*="verify-modal"]',
        '[class*="identity-verify"]',
        '[class*="second-verify"]',
        '[class*="security-verify"]',
        '[class*="sms-verify"]',
      ];

      for (const selector of commonVerifySelectors) {
        const element = page.locator(selector).first();
        if (await element.count() > 0 && await element.isVisible().catch(() => false)) {
          logger.info(`[BrowserLogin] Found verification modal: ${selector}`);
          return true;
        }
      }

      return false;
    } catch (error) {
      logger.error('[BrowserLogin] Error checking secondary verification:', error);
      return false;
    }
  }

  /**
   * 处理登录成功
   * 直接从当前登录成功的页面提取账号信息，不再刷新页面
   */
  private async handleLoginSuccess(sessionId: string): Promise<void> {
    const session = this.sessions.get(sessionId);
    if (!session) return;

    // 防止重复处理（AI 检测和 URL 检测可能同时触发）
    if (session.status !== 'pending') {
      logger.info(`[BrowserLogin] Session ${sessionId} already processed, status: ${session.status}`);
      return;
    }

    try {
      // 停止 AI 监控
      session.aiAssistant?.stopMonitoring();

      // 等待页面完全稳定
      logger.info(`[BrowserLogin] Waiting for page to stabilize for session: ${sessionId}`);

      // 等待网络请求完成
      try {
        await session.page.waitForLoadState('networkidle', { timeout: 10000 });
      } catch {
        // 超时也继续
      }

      // 对于视频号，等待用户信息元素出现（最多等待10秒）
      if (session.platform === 'weixin' || session.platform === 'weixin_video') {
        logger.info(`[BrowserLogin] Waiting for Weixin video account info elements...`);
        try {
          // 等待视频号ID元素或昵称元素出现
          await Promise.race([
            session.page.waitForSelector('.finder-uniq-id', { timeout: 10000 }),
            session.page.waitForSelector('#finder-uid-copy', { timeout: 10000 }),
            session.page.waitForSelector('.finder-nickname', { timeout: 10000 }),
            session.page.waitForSelector('h2.finder-nickname', { timeout: 10000 }),
          ]);
          logger.info(`[BrowserLogin] Weixin video account info elements found`);
        } catch {
          logger.warn(`[BrowserLogin] Weixin video account info elements not found within timeout`);
        }
        // 额外等待确保数据渲染完成
        await session.page.waitForTimeout(1000);
      } else {
        // 其他平台等待2秒
        await session.page.waitForTimeout(2000);
      }

      logger.info(`[BrowserLogin] Processing login success for session: ${sessionId}`);

      // 获取所有 Cookie
      const cookies = await session.context.cookies();
      const cookieString = JSON.stringify(cookies);

      // 更新状态为"正在获取账号信息"
      session.status = 'fetching';
      this.emit('loginResult', {
        sessionId,
        userId: session.userId,
        status: 'fetching',
        message: '登录成功，正在获取账号信息...',
      });

      // 获取账号信息 - 分别收集各个字段，最后合并
      const isWeixinVideo = session.platform === 'weixin' || session.platform === 'weixin_video';

      // 初始化各字段
      let finalAccountId = '';
      let finalAccountName = '';
      let finalAvatarUrl = '';
      let finalFansCount = 0;
      let finalWorksCount = 0;

      logger.info(`[BrowserLogin] Starting to extract account info for session: ${sessionId}`);
      logger.info(`[BrowserLogin] Current page URL: ${session.page.url()}`);

      if (isWeixinVideo) {
        // ========== 视频号专用提取逻辑 ==========

        // 1. 获取页面 HTML 并用正则提取视频号ID
        try {
          const html = await session.page.content();
          logger.info(`[BrowserLogin] Got page HTML, length: ${html.length}`);

          // 正则提取视频号ID
          const idPatterns = [
            /data-clipboard-text="([a-zA-Z0-9]{10,})"/,
            /class="[^"]*finder-uniq-id[^"]*"[^>]*>([a-zA-Z0-9]{10,})</,
            />([a-zA-Z0-9]{15,16})</,  // 视频号ID通常是15-16位字母数字
            /视频号ID[：:]\s*([a-zA-Z0-9]{10,})/,
          ];

          for (const pattern of idPatterns) {
            const match = html.match(pattern);
            if (match && match[1] && /^[a-zA-Z]/.test(match[1])) { // 视频号ID通常以字母开头
              finalAccountId = match[1];
              logger.info(`[BrowserLogin] ✓ Found accountId from HTML regex: ${finalAccountId}`);
              break;
            }
          }
        } catch (e) {
          logger.warn(`[BrowserLogin] HTML extraction error:`, e);
        }

        // 2. 从页面元素直接提取头像和其他信息
        try {
          const pageData = await session.page.evaluate(() => {
            const result: {
              accountId?: string;
              accountName?: string;
              avatarUrl?: string;
              fansCount?: number;
              worksCount?: number;
            } = {};

            // 提取视频号ID
            const idEl = document.querySelector('#finder-uid-copy') || document.querySelector('.finder-uniq-id');
            if (idEl) {
              const clipboardText = idEl.getAttribute('data-clipboard-text');
              if (clipboardText && /^[a-zA-Z][a-zA-Z0-9]{9,}$/.test(clipboardText)) {
                result.accountId = clipboardText;
              } else {
                const text = idEl.textContent?.trim();
                if (text && /^[a-zA-Z][a-zA-Z0-9]{9,}$/.test(text)) {
                  result.accountId = text;
                }
              }
            }

            // 提取账号名称
            const nameEl = document.querySelector('h2.finder-nickname') ||
              document.querySelector('.finder-nickname') ||
              document.querySelector('.nickname');
            if (nameEl) {
              const text = nameEl.textContent?.trim();
              if (text && text.length >= 2 && text.length <= 30) {
                result.accountName = text;
              }
            }

            // 提取头像 - 多种选择器
            const avatarSelectors = [
              'img.avatar',
              'img[alt*="头像"]',
              'img[alt*="avatar"]',
              '.avatar img',
              'img[src*="qlogo"]',
              'img[src*="finderhead"]',
              '.finder-info-container img',
              '.user-info img',
            ];
            for (const sel of avatarSelectors) {
              const img = document.querySelector(sel) as HTMLImageElement;
              if (img?.src && img.src.startsWith('http')) {
                result.avatarUrl = img.src;
                break;
              }
            }

            // 提取粉丝数和作品数
            const infoText = document.body.innerText;
            const fansMatch = infoText.match(/关注者\s*(\d+)/) || infoText.match(/粉丝\s*(\d+)/);
            if (fansMatch) result.fansCount = parseInt(fansMatch[1], 10);

            const worksMatch = infoText.match(/视频\s*(\d+)/) || infoText.match(/作品\s*(\d+)/);
            if (worksMatch) result.worksCount = parseInt(worksMatch[1], 10);

            return result;
          });

          logger.info(`[BrowserLogin] Page element extraction result:`, pageData);

          // 合并数据（只覆盖空值）
          if (pageData.accountId && !finalAccountId) finalAccountId = pageData.accountId;
          if (pageData.accountName) finalAccountName = pageData.accountName;
          if (pageData.avatarUrl) finalAvatarUrl = pageData.avatarUrl;
          if (pageData.fansCount) finalFansCount = pageData.fansCount;
          if (pageData.worksCount) finalWorksCount = pageData.worksCount;

        } catch (e) {
          logger.warn(`[BrowserLogin] Page element extraction error:`, e);
        }

        // 3. 如果还没有ID或名称，使用AI补充
        if ((!finalAccountId || !finalAccountName) && aiService.isAvailable()) {
          try {
            const screenshotBuffer = await session.page.screenshot({ type: 'jpeg', quality: 80 });
            const screenshotBase64 = screenshotBuffer.toString('base64');
            const html = await session.page.content();

            const aiResult = await aiService.extractAccountInfoWithHtml(screenshotBase64, html, 'weixin_video');
            logger.info(`[BrowserLogin] AI extraction result:`, aiResult);

            if (aiResult.found) {
              if (aiResult.accountId && !finalAccountId) finalAccountId = aiResult.accountId;
              if (aiResult.accountName && !finalAccountName) finalAccountName = aiResult.accountName;
              if (!finalFansCount && aiResult.fansCount) finalFansCount = this.parseNumberString(aiResult.fansCount);
              if (!finalWorksCount && aiResult.worksCount) finalWorksCount = this.parseNumberString(aiResult.worksCount);
            }
          } catch (e) {
            logger.warn(`[BrowserLogin] AI extraction error:`, e);
          }
        }

        // 4. 添加前缀
        if (finalAccountId && !finalAccountId.startsWith('weixin_video_')) {
          finalAccountId = `weixin_video_${finalAccountId}`;
        }

      } else {
        // ========== 其他平台提取逻辑 ==========
        const pageInfo = await this.extractAccountInfoFromCurrentPage(session.page, session.platform);

        if (pageInfo) {
          finalAccountId = pageInfo.accountId;
          finalAccountName = pageInfo.accountName;
          finalAvatarUrl = pageInfo.avatarUrl;
          finalFansCount = pageInfo.fansCount;
          finalWorksCount = pageInfo.worksCount;
        }

        // 如果页面提取失败，用AI补充
        if ((!finalAccountId || !finalAccountName) && session.aiAssistant && aiService.isAvailable()) {
          const aiResult = await session.aiAssistant.getAccountInfoWithAI(3);
          if (aiResult.success && aiResult.accountInfo) {
            if (aiResult.accountInfo.accountId && !finalAccountId) {
              finalAccountId = aiResult.accountInfo.accountId;
              if (!finalAccountId.startsWith(`${session.platform}_`)) {
                finalAccountId = `${session.platform}_${finalAccountId}`;
              }
            }
            if (aiResult.accountInfo.accountName && !finalAccountName) {
              finalAccountName = aiResult.accountInfo.accountName;
            }
            if (!finalFansCount && aiResult.accountInfo.fansCount) {
              finalFansCount = this.parseNumberString(aiResult.accountInfo.fansCount);
            }
            if (!finalWorksCount && aiResult.accountInfo.worksCount) {
              finalWorksCount = this.parseNumberString(aiResult.accountInfo.worksCount);
            }
          }
        }
      }

      // 最终结果
      logger.info(`[BrowserLogin] Final extracted data:`, {
        accountId: finalAccountId,
        accountName: finalAccountName,
        avatarUrl: finalAvatarUrl ? 'yes' : 'no',
        fansCount: finalFansCount,
        worksCount: finalWorksCount,
      });

      // 检查是否获取到了真正的账号ID（不是时间戳）
      const isValidAccountId = (id: string): boolean => {
        if (!id) return false;
        // 检查是否是时间戳格式（纯数字或以平台前缀+数字结尾）
        const timestampPattern = /^(weixin_video_|douyin_|xiaohongshu_|kuaishou_|bilibili_|baijiahao_|weixin_)?\d{10,}$/;
        return !timestampPattern.test(id);
      };

      // 如果没有获取到有效的账号ID，尝试重新获取（最多3次）
      let retryCount = 0;
      const maxRetries = 3;

      while (!isValidAccountId(finalAccountId) && retryCount < maxRetries) {
        retryCount++;
        logger.warn(`[BrowserLogin] No valid accountId found, retry ${retryCount}/${maxRetries}...`);

        // 等待一段时间再重试
        await session.page.waitForTimeout(2000);

        // 对于视频号，确保在首页
        if (isWeixinVideo) {
          const currentUrl = session.page.url();
          if (!currentUrl.includes('/platform/home') || currentUrl.includes('iframe')) {
            logger.info(`[BrowserLogin] Navigating to home page for retry...`);
            try {
              await session.page.goto('https://channels.weixin.qq.com/platform/home', {
                waitUntil: 'networkidle',
                timeout: 15000
              });
              await session.page.waitForTimeout(2000);
            } catch (e) {
              logger.warn(`[BrowserLogin] Navigation failed:`, e);
            }
          }
        }

        // 重新从页面提取
        try {
          const html = await session.page.content();

          // 尝试正则提取
          const idPatterns: { pattern: RegExp; platform: string }[] = [
            { pattern: /data-clipboard-text="([a-zA-Z][a-zA-Z0-9]{9,})"/, platform: 'weixin_video' },
            { pattern: /finder-uniq-id[^>]*>([a-zA-Z][a-zA-Z0-9]{9,})</, platform: 'weixin_video' },
            { pattern: /视频号ID[：:]\s*([a-zA-Z][a-zA-Z0-9]{9,})/, platform: 'weixin_video' },
            { pattern: /抖音号[：:]\s*([a-zA-Z0-9_]+)/, platform: 'douyin' },
            { pattern: /小红书号[：:]\s*([a-zA-Z0-9]+)/, platform: 'xiaohongshu' },
            { pattern: /百家号ID[：:]\s*(\d+)/, platform: 'baijiahao' },
          ];

          for (const { pattern, platform } of idPatterns) {
            if (session.platform === platform ||
              (session.platform === 'weixin' && platform === 'weixin_video')) {
              const match = html.match(pattern);
              if (match && match[1]) {
                finalAccountId = match[1];
                logger.info(`[BrowserLogin] Found accountId on retry ${retryCount}: ${finalAccountId}`);
                break;
              }
            }
          }

          // 也从页面元素提取
          if (!isValidAccountId(finalAccountId)) {
            const pageData = await session.page.evaluate(() => {
              // 视频号
              const finderIdEl = document.querySelector('#finder-uid-copy') || document.querySelector('.finder-uniq-id');
              if (finderIdEl) {
                const clipboardText = finderIdEl.getAttribute('data-clipboard-text');
                if (clipboardText && /^[a-zA-Z]/.test(clipboardText)) return clipboardText;
                const text = finderIdEl.textContent?.trim();
                if (text && /^[a-zA-Z]/.test(text)) return text;
              }
              return null;
            });

            if (pageData) {
              finalAccountId = pageData;
              logger.info(`[BrowserLogin] Found accountId from page on retry ${retryCount}: ${finalAccountId}`);
            }
          }
        } catch (e) {
          logger.warn(`[BrowserLogin] Retry ${retryCount} failed:`, e);
        }
      }

      // 最终检查 - 如果没有获取到有效ID，报错不允许保存
      if (!isValidAccountId(finalAccountId)) {
        logger.error(`[BrowserLogin] FAILED to get valid accountId after ${maxRetries} retries`);

        // 发送失败消息，提示用户重试
        session.status = 'failed';
        session.error = '无法获取账号ID，请重新登录。请确保登录后页面跳转到首页。';
        this.emit('loginResult', {
          sessionId,
          userId: session.userId,
          status: 'failed',
          error: '无法获取账号ID（视频号ID/抖音号/小红书号等），请重新登录'
        });

        // 关闭浏览器
        await this.closeSession(sessionId);
        return;
      }

      // 添加平台前缀
      const expectedPrefix = isWeixinVideo ? 'weixin_video_' : `${session.platform}_`;
      if (!finalAccountId.startsWith(expectedPrefix)) {
        finalAccountId = `${expectedPrefix}${finalAccountId}`;
      }

      // 构建最终的 accountInfo
      let accountInfo: AccountInfo = {
        accountId: finalAccountId,
        accountName: finalAccountName || `${session.platform}账号`,
        avatarUrl: finalAvatarUrl,
        fansCount: finalFansCount,
        worksCount: finalWorksCount,
      };

      // 如果还没有头像，再次尝试从页面提取
      if (!accountInfo.avatarUrl) {
        try {
          const avatarUrl = await session.page.evaluate(() => {
            const selectors = [
              'img.avatar',
              'img[alt*="头像"]',
              '.avatar img',
              'img[src*="qlogo"]',
              'img[src*="finderhead"]',
              'img[src*="avatar"]',
              '.user-avatar img',
              '.profile-avatar img',
              '.finder-info-container img',
            ];
            for (const selector of selectors) {
              const img = document.querySelector(selector) as HTMLImageElement;
              if (img?.src && img.src.startsWith('http')) {
                return img.src;
              }
            }
            // 也尝试找背景图片形式的头像
            const avatarDivs = document.querySelectorAll('[class*="avatar"]');
            for (const div of avatarDivs) {
              const style = window.getComputedStyle(div);
              const bgImage = style.backgroundImage;
              if (bgImage && bgImage.startsWith('url(')) {
                const url = bgImage.slice(5, -2);
                if (url.startsWith('http')) {
                  return url;
                }
              }
            }
            return null;
          });

          if (avatarUrl) {
            accountInfo.avatarUrl = avatarUrl;
            logger.info(`[BrowserLogin] Extracted avatar URL: ${avatarUrl}`);
          }
        } catch (error) {
          logger.warn(`[BrowserLogin] Failed to extract avatar:`, error);
        }
      }

      // 最终再次确保 accountId 有正确的前缀
      if (isWeixinVideo && !accountInfo.accountId.startsWith('weixin_video_')) {
        accountInfo.accountId = `weixin_video_${accountInfo.accountId}`;
      } else if (!isWeixinVideo && !accountInfo.accountId.startsWith(`${session.platform}_`)) {
        accountInfo.accountId = `${session.platform}_${accountInfo.accountId}`;
      }

      // 如果还没有头像，从首页专门提取
      if (!accountInfo.avatarUrl && isWeixinVideo) {
        logger.info(`[BrowserLogin] Trying to extract avatar from home page...`);
        try {
          // 确保在首页
          const currentUrl = session.page.url();
          if (!currentUrl.includes('/platform/home')) {
            await session.page.goto('https://channels.weixin.qq.com/platform/home', {
              waitUntil: 'networkidle',
              timeout: 10000
            });
            await session.page.waitForTimeout(2000);
          }

          const avatarUrl = await session.page.evaluate(() => {
            // 视频号首页的头像选择器
            const selectors = [
              'img.avatar',
              '.finder-info img',
              '.finder-info-container img',
              'img[src*="wx.qlogo.cn"]',
              'img[src*="qlogo"]',
              'img[src*="finderhead"]',
              'img[alt*="头像"]',
              'img[alt*="avatar"]',
            ];

            for (const sel of selectors) {
              const imgs = document.querySelectorAll(sel);
              for (const img of imgs) {
                const src = (img as HTMLImageElement).src;
                if (src && src.startsWith('http') && (src.includes('qlogo') || src.includes('finderhead'))) {
                  return src;
                }
              }
            }

            // 尝试找任何看起来像头像的图片
            const allImgs = document.querySelectorAll('img');
            for (const img of allImgs) {
              const src = (img as HTMLImageElement).src;
              if (src && (src.includes('qlogo') || src.includes('finderhead') || src.includes('avatar'))) {
                return src;
              }
            }

            return null;
          });

          if (avatarUrl) {
            accountInfo.avatarUrl = avatarUrl;
            logger.info(`[BrowserLogin] Found avatar URL from home page: ${avatarUrl}`);
          } else {
            logger.warn(`[BrowserLogin] Could not find avatar URL`);
          }
        } catch (e) {
          logger.warn(`[BrowserLogin] Failed to extract avatar from home page:`, e);
        }
      }

      logger.info(`[BrowserLogin] Final account info:`, {
        accountId: accountInfo.accountId,
        accountName: accountInfo.accountName,
        avatarUrl: accountInfo.avatarUrl || 'none',
        fansCount: accountInfo.fansCount,
        worksCount: accountInfo.worksCount,
      });

      // 关闭浏览器
      await this.closeSession(sessionId);

      // 加密存储
      const encryptedCookies = CookieManager.encrypt(cookieString);

      session.status = 'success';
      session.cookies = encryptedCookies;
      session.accountInfo = accountInfo;

      logger.info(`[BrowserLogin] Login success for session: ${sessionId}, account: ${accountInfo.accountName}`);

      // 发送事件
      this.emit('loginResult', {
        sessionId,
        userId: session.userId,
        status: 'success',
        cookies: encryptedCookies,
        accountInfo,
        rawCookies: cookies,
      });
    } catch (error) {
      logger.error(`[BrowserLogin] Error handling login success for ${sessionId}:`, error);
      session.status = 'failed';
      session.error = String(error);
      this.emit('loginResult', { sessionId, userId: session.userId, status: 'failed', error: String(error) });
    }
  }

  /**
   * 直接从当前页面提取账号信息（不刷新页面）
   * 支持重试机制，最多重试3次
   */
  private async extractAccountInfoFromCurrentPage(page: Page, platform: PlatformType): Promise<AccountInfo | null> {
    const maxRetries = 3;

    for (let attempt = 1; attempt <= maxRetries; attempt++) {
      try {
        logger.info(`[BrowserLogin] Extracting account info attempt ${attempt}/${maxRetries} for platform: ${platform}`);
        logger.info(`[BrowserLogin] Current page URL: ${page.url()}`);

        const accountData = await page.evaluate((platformType: string) => {
          const result: {
            accountId?: string;
            accountName?: string;
            avatarUrl?: string;
            fansCount?: number;
            worksCount?: number;
            debug?: string;
          } = {};

          const debugInfo: string[] = [];

          try {
            // ===== 视频号平台的选择器 =====
            if (platformType === 'weixin' || platformType === 'weixin_video') {
              // 1. 获取视频号 ID - 多种方法

              // 方法1: 从 #finder-uid-copy 的 data-clipboard-text 属性获取
              const finderIdCopyEl = document.querySelector('#finder-uid-copy');
              if (finderIdCopyEl) {
                debugInfo.push(`Found #finder-uid-copy element`);
                const clipboardText = finderIdCopyEl.getAttribute('data-clipboard-text');
                if (clipboardText && clipboardText.length >= 10) {
                  result.accountId = clipboardText;
                  debugInfo.push(`Got accountId from data-clipboard-text: ${clipboardText}`);
                } else {
                  const text = finderIdCopyEl.textContent?.trim();
                  if (text && /^[a-zA-Z0-9_]+$/.test(text) && text.length >= 10) {
                    result.accountId = text;
                    debugInfo.push(`Got accountId from #finder-uid-copy text: ${text}`);
                  }
                }
              } else {
                debugInfo.push(`#finder-uid-copy not found`);
              }

              // 方法2: 从 .finder-uniq-id 获取
              if (!result.accountId) {
                const finderUniqIdEl = document.querySelector('.finder-uniq-id');
                if (finderUniqIdEl) {
                  debugInfo.push(`Found .finder-uniq-id element`);
                  const clipboardText = finderUniqIdEl.getAttribute('data-clipboard-text');
                  if (clipboardText && clipboardText.length >= 10) {
                    result.accountId = clipboardText;
                    debugInfo.push(`Got accountId from .finder-uniq-id data-clipboard-text: ${clipboardText}`);
                  } else {
                    const text = finderUniqIdEl.textContent?.trim();
                    if (text && /^[a-zA-Z0-9_]+$/.test(text) && text.length >= 10) {
                      result.accountId = text;
                      debugInfo.push(`Got accountId from .finder-uniq-id text: ${text}`);
                    }
                  }
                } else {
                  debugInfo.push(`.finder-uniq-id not found`);
                }
              }

              // 方法3: 从页面文本正则匹配
              if (!result.accountId) {
                const bodyText = document.body.innerText || '';
                const patterns = [
                  /视频号ID[：:\s]*([a-zA-Z0-9_]{10,})/,
                  /视频号[：:\s]*ID[：:\s]*([a-zA-Z0-9_]{10,})/,
                ];
                for (const pattern of patterns) {
                  const match = bodyText.match(pattern);
                  if (match && match[1]) {
                    result.accountId = match[1];
                    debugInfo.push(`Got accountId from page text regex: ${match[1]}`);
                    break;
                  }
                }
                if (!result.accountId) {
                  debugInfo.push(`No accountId found from page text regex`);
                }
              }

              // 2. 获取账号名称
              const nicknameSelectors = ['h2.finder-nickname', '.finder-nickname', '.nickname'];
              for (const selector of nicknameSelectors) {
                const el = document.querySelector(selector);
                if (el) {
                  const text = el.textContent?.trim();
                  if (text && text.length >= 2 && text.length <= 30) {
                    result.accountName = text;
                    debugInfo.push(`Got accountName from ${selector}: ${text}`);
                    break;
                  }
                }
              }
              if (!result.accountName) {
                debugInfo.push(`No accountName found from selectors`);
              }

              // 3. 获取头像 URL
              const avatarSelectors = [
                'img.avatar',
                'img[alt="视频号头像"]',
                '.finder-info-container img.avatar',
                'img[src*="wx.qlogo.cn/finderhead"]',
                'img[src*="wx.qlogo"]',
                '.avatar img',
                '[class*="avatar"] img',
              ];
              for (const selector of avatarSelectors) {
                const el = document.querySelector(selector) as HTMLImageElement;
                if (el?.src && el.src.startsWith('http')) {
                  result.avatarUrl = el.src;
                  debugInfo.push(`Got avatarUrl from ${selector}`);
                  break;
                }
              }
              if (!result.avatarUrl) {
                debugInfo.push(`No avatarUrl found from selectors`);
              }

              // 4. 获取视频数和关注者数
              const contentInfo = document.querySelector('.finder-content-info');
              if (contentInfo) {
                debugInfo.push(`Found .finder-content-info`);
                const infoDivs = contentInfo.querySelectorAll('div');
                infoDivs.forEach(div => {
                  const text = div.textContent || '';
                  const numEl = div.querySelector('.finder-info-num');
                  if (numEl) {
                    const num = parseInt(numEl.textContent?.trim() || '0', 10);
                    if (text.includes('视频') || text.includes('作品')) {
                      result.worksCount = num;
                      debugInfo.push(`Got worksCount: ${num}`);
                    } else if (text.includes('关注者') || text.includes('粉丝')) {
                      result.fansCount = num;
                      debugInfo.push(`Got fansCount: ${num}`);
                    }
                  }
                });
              } else {
                debugInfo.push(`.finder-content-info not found`);
              }

              // 备选：从页面文本匹配数字
              if (result.fansCount === undefined || result.worksCount === undefined) {
                const bodyText = document.body.innerText || '';
                if (result.fansCount === undefined) {
                  const fansMatch = bodyText.match(/关注者\s*(\d+)/) || bodyText.match(/粉丝\s*(\d+)/);
                  if (fansMatch) {
                    result.fansCount = parseInt(fansMatch[1], 10);
                    debugInfo.push(`Got fansCount from text: ${result.fansCount}`);
                  }
                }
                if (result.worksCount === undefined) {
                  const worksMatch = bodyText.match(/视频\s*(\d+)/) || bodyText.match(/作品\s*(\d+)/);
                  if (worksMatch) {
                    result.worksCount = parseInt(worksMatch[1], 10);
                    debugInfo.push(`Got worksCount from text: ${result.worksCount}`);
                  }
                }
              }
            }

            // ===== 其他平台的选择器（抖音、小红书等） =====
            // 通用选择器
            if (!result.accountName) {
              const nameSelectors = [
                '.user-name', '.nickname', '[class*="nickname"]', '[class*="userName"]',
                '.account-name', 'h2.name', '.name-text',
              ];
              for (const selector of nameSelectors) {
                const el = document.querySelector(selector);
                const text = el?.textContent?.trim();
                if (text && text.length >= 2 && text.length <= 30) {
                  result.accountName = text;
                  break;
                }
              }
            }

            if (!result.avatarUrl) {
              const avatarSelectors = [
                'img[class*="avatar"]', '[class*="avatar"] img', 'img.avatar',
              ];
              for (const selector of avatarSelectors) {
                const el = document.querySelector(selector) as HTMLImageElement;
                if (el?.src && el.src.startsWith('http')) {
                  result.avatarUrl = el.src;
                  break;
                }
              }
            }

            // 保存调试信息
            result.debug = debugInfo.join('; ');

          } catch (e) {
            // eslint-disable-next-line no-console
            console.error('[BrowserLogin] Extract error:', e);
          }

          return result;
        }, platform);

        // 输出调试信息
        if (accountData?.debug) {
          logger.info(`[BrowserLogin] Debug info: ${accountData.debug}`);
        }

        logger.info(`[BrowserLogin] Extracted from current page:`, {
          accountId: accountData?.accountId,
          accountName: accountData?.accountName,
          avatarUrl: accountData?.avatarUrl ? 'yes' : 'no',
          fansCount: accountData?.fansCount,
          worksCount: accountData?.worksCount,
        });

        if (accountData && (accountData.accountName || accountData.accountId)) {
          // 生成统一格式的 accountId：前缀 + 原始ID
          let finalAccountId: string;
          const rawId = accountData.accountId;

          if (rawId) {
            // 根据平台添加对应前缀
            if (platform === 'weixin' || platform === 'weixin_video') {
              // 视频号：weixin_video_ + 视频号ID
              finalAccountId = rawId.startsWith('weixin_video_') ? rawId : `weixin_video_${rawId}`;
            } else if (platform === 'douyin') {
              finalAccountId = rawId.startsWith('douyin_') ? rawId : `douyin_${rawId}`;
            } else if (platform === 'xiaohongshu') {
              finalAccountId = rawId.startsWith('xiaohongshu_') ? rawId : `xiaohongshu_${rawId}`;
            } else if (platform === 'kuaishou') {
              finalAccountId = rawId.startsWith('kuaishou_') ? rawId : `kuaishou_${rawId}`;
            } else if (platform === 'bilibili') {
              finalAccountId = rawId.startsWith('bilibili_') ? rawId : `bilibili_${rawId}`;
            } else {
              finalAccountId = rawId.startsWith(`${platform}_`) ? rawId : `${platform}_${rawId}`;
            }
          } else {
            // 没有获取到ID，使用时间戳
            const defaultPrefix = (platform === 'weixin' || platform === 'weixin_video') ? 'weixin_video' : platform;
            finalAccountId = `${defaultPrefix}_${Date.now()}`;
          }

          logger.info(`[BrowserLogin] Final accountId: ${finalAccountId}`);

          return {
            accountId: finalAccountId,
            accountName: accountData.accountName || `${platform}账号`,
            avatarUrl: accountData.avatarUrl || '',
            fansCount: accountData.fansCount || 0,
            worksCount: accountData.worksCount || 0,
          };
        }

        // 如果没有获取到信息，且还有重试机会，等待后重试
        if (attempt < maxRetries) {
          logger.info(`[BrowserLogin] No account info found, waiting 2s before retry...`);
          await page.waitForTimeout(2000);
        }

      } catch (error) {
        logger.error(`[BrowserLogin] Extract attempt ${attempt} failed:`, error);
        if (attempt < maxRetries) {
          await page.waitForTimeout(1000);
        }
      }
    }

    logger.warn(`[BrowserLogin] Failed to extract account info after ${maxRetries} attempts`);
    return null;
  }

  /**
   * 解析数字字符串（支持中文单位）
   */
  private parseNumberString(str?: string): number {
    if (!str) return 0;

    // 移除非数字字符（保留小数点）
    const cleaned = str.replace(/[^0-9.万亿w]/gi, '');
    const num = parseFloat(cleaned) || 0;

    // 处理中文单位
    if (str.includes('万') || str.toLowerCase().includes('w')) {
      return Math.floor(num * 10000);
    }
    if (str.includes('亿')) {
      return Math.floor(num * 100000000);
    }

    return Math.floor(num);
  }

  /**
   * 使用无头浏览器获取账号信息
   */
  private async fetchAccountInfoHeadless(
    platform: PlatformType,
    cookies: { name: string; value: string; domain: string; path: string }[]
  ): Promise<AccountInfo> {
    // 使用共享的无头浏览器服务
    const { headlessBrowserService } = await import('./HeadlessBrowserService.js');
    return headlessBrowserService.fetchAccountInfo(platform, cookies);
  }

  /**
   * 处理超时
   */
  private async handleTimeout(sessionId: string): Promise<void> {
    const session = this.sessions.get(sessionId);
    if (!session || session.status !== 'pending') return;

    session.status = 'timeout';
    session.error = '登录超时';

    logger.warn(`Login session timeout: ${sessionId}`);
    this.emit('loginResult', { sessionId, userId: session.userId, status: 'timeout', error: '登录超时' });

    await this.closeSession(sessionId);
  }

  /**
   * 获取会话状态
   */
  getSessionStatus(sessionId: string): {
    status: string;
    cookies?: string;
    accountInfo?: AccountInfo;
    error?: string;
    userId?: number;
  } | null {
    const session = this.sessions.get(sessionId);
    if (!session) return null;

    return {
      status: session.status,
      cookies: session.cookies,
      accountInfo: session.accountInfo,
      error: session.error,
      userId: session.userId,
    };
  }

  /**
   * 获取会话的用户ID
   */
  getSessionUserId(sessionId: string): number | undefined {
    const session = this.sessions.get(sessionId);
    return session?.userId;
  }

  /**
   * 取消登录会话
   */
  async cancelSession(sessionId: string): Promise<void> {
    const session = this.sessions.get(sessionId);
    if (!session) return;

    session.status = 'cancelled';
    await this.closeSession(sessionId);

    logger.info(`Login session cancelled: ${sessionId}`);
  }

  /**
   * 关闭会话
   */
  private async closeSession(sessionId: string): Promise<void> {
    const session = this.sessions.get(sessionId);
    if (!session) return;

    try {
      // 停止并销毁 AI 助手（异步清理截图）
      if (session.aiAssistant) {
        await session.aiAssistant.destroy();
        session.aiAssistant = undefined;
      }

      if (session.page) {
        await session.page.close().catch(() => { });
      }
      if (session.context) {
        await session.context.close().catch(() => { });
      }
      if (session.browser) {
        await session.browser.close().catch(() => { });
      }
    } catch (error) {
      logger.error(`Error closing session ${sessionId}:`, error);
    }

    // 保留会话信息一段时间供查询
    setTimeout(() => {
      this.sessions.delete(sessionId);
    }, 60000);
  }

  /**
   * 清理所有会话
   */
  async cleanup(): Promise<void> {
    for (const [sessionId] of this.sessions) {
      await this.closeSession(sessionId);
    }
    this.sessions.clear();
  }
}

// 导出单例
export const browserLoginService = new BrowserLoginService();
