/**
 * 多平台登录服务 - 抽象基类
 * @module services/login/BaseLoginService
 * 
 * 登录流程：
 * 1. 打开登录页面，等待用户扫码
 * 2. 检测登录成功（URL检测 + AI静默检测）
 * 3. 收集完整账号信息（包括跳转作品页获取作品数）
 * 4. 所有信息获取完成后，才发送成功事件，前端显示保存按钮
 */

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';
import type {
  PlatformLoginConfig,
  LoginSession,
  LoginSessionStatus,
  AccountInfo,
  LoginResultEvent,
} from './types.js';

/**
 * API 拦截配置
 */
export interface ApiInterceptConfig {
  /** URL 匹配模式 */
  urlPattern: string | RegExp;
  /** 数据存储的 key */
  dataKey: string;
  /** 可选的数据处理函数 */
  handler?: (response: any) => any;
}

/**
 * 登录服务抽象基类
 */
export abstract class BaseLoginService extends EventEmitter {
  protected readonly config: PlatformLoginConfig;
  protected sessions: Map<string, LoginSession> = new Map();

  protected readonly LOGIN_TIMEOUT = 5 * 60 * 1000; // 5分钟
  protected readonly CHECK_INTERVAL = 1000; // URL检测间隔
  protected readonly AI_CHECK_INTERVAL = 5000; // AI检测间隔

  constructor(config: PlatformLoginConfig) {
    super();
    this.config = config;
  }

  get platform(): PlatformType {
    return this.config.platform;
  }

  get displayName(): string {
    return this.config.displayName;
  }

  // ==================== 核心登录流程 ====================

  /**
   * 开始登录会话
   */
  async startLoginSession(userId?: number): Promise<{ sessionId: string; message: string }> {
    const sessionId = `login_${this.config.platform}_${Date.now()}`;

    try {
      // 1. 启动浏览器
      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();

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

      this.sessions.set(sessionId, session);

      // 3. 设置 API 拦截（在导航前设置）
      this.setupApiIntercept(session);

      // 4. 打开登录页面
      logger.info(`[${this.displayName}] 打开登录页面: ${this.config.loginUrl}`);
      await page.goto(this.config.loginUrl, { waitUntil: 'domcontentloaded' });

      // 5. 启动登录状态监控（静默监控，不发送事件给前端）
      this.startLoginMonitor(sessionId);

      // 6. 设置超时
      this.setupTimeout(sessionId);

      logger.info(`[${this.displayName}] 登录会话已启动: ${sessionId}`);

      return {
        sessionId,
        message: `已打开${this.displayName}登录页面，请扫码登录`,
      };
    } catch (error) {
      logger.error(`[${this.displayName}] 启动登录失败:`, error);
      throw error;
    }
  }

  // ==================== API 拦截 ====================

  /**
   * 获取需要拦截的 API 配置（子类重写）
   */
  protected getApiInterceptConfigs(): ApiInterceptConfig[] {
    return [];
  }

  /**
   * 设置 API 拦截
   */
  protected setupApiIntercept(session: LoginSession): void {
    const configs = this.getApiInterceptConfigs();
    if (configs.length === 0) return;

    session.page.on('response', async (response) => {
      const url = response.url();

      for (const config of configs) {
        const matched = typeof config.urlPattern === 'string'
          ? url.includes(config.urlPattern)
          : config.urlPattern.test(url);

        if (matched) {
          try {
            const contentType = response.headers()['content-type'] || '';
            if (contentType.includes('application/json')) {
              const data = await response.json();
              const processedData = config.handler ? config.handler(data) : data;

              if (!session.apiData) session.apiData = {};
              session.apiData[config.dataKey] = processedData;

              logger.info(`[${this.displayName}] API 拦截成功: ${config.dataKey}`);
            }
          } catch (error) {
            logger.warn(`[${this.displayName}] API 数据处理失败: ${url}`);
          }
        }
      }
    });

    logger.info(`[${this.displayName}] 已设置 ${configs.length} 个 API 拦截`);
  }

  // ==================== 登录状态监控（静默） ====================

  /**
   * 启动登录监控（静默，不发送事件给前端）
   */
  protected startLoginMonitor(sessionId: string): void {
    // URL 监控
    this.startUrlMonitor(sessionId);

    // AI 静默监控（如果可用）- 只用于检测登录状态，不发送分析结果
    const session = this.sessions.get(sessionId);
    if (session && aiService.isAvailable()) {
      this.startAiMonitor(sessionId);
    }
  }

  /**
   * URL 监控 - 检测是否跳转到成功页面
   */
  protected startUrlMonitor(sessionId: string): void {
    const checkInterval = setInterval(async () => {
      const session = this.sessions.get(sessionId);

      // 会话不存在或已处理，停止监控
      if (!session || session.status !== 'pending') {
        clearInterval(checkInterval);
        return;
      }

      try {
        const currentUrl = session.page.url();

        // 检测是否跳转到成功页面
        const isSuccess = this.config.successIndicators.some(indicator =>
          currentUrl.includes(indicator)
        );

        if (isSuccess) {
          logger.info(`[${this.displayName}] URL 检测到登录成功: ${currentUrl}`);
          clearInterval(checkInterval);
          await this.handleLoginSuccess(sessionId);
        }
      } catch (error) {
        // 浏览器可能已关闭
        clearInterval(checkInterval);
        this.handleBrowserClosed(sessionId);
      }
    }, this.CHECK_INTERVAL);
  }

  /**
   * AI 静默监控 - 只用于检测登录状态，不发送分析结果给前端
   */
  protected startAiMonitor(sessionId: string): void {
    const session = this.sessions.get(sessionId);
    if (!session) return;

    // 创建 AI 助手
    session.aiAssistant = new AILoginAssistant(session.page, session.platform, session.id);

    logger.info(`[${this.displayName}] 启动 AI 静默监控`);

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

        // 【重要】不发送 aiAnalysis 事件给前端，AI 只在后台静默检测

        // AI 检测到登录成功
        if (result.status === 'logged_in' && result.analysis.isLoggedIn) {
          logger.info(`[${this.displayName}] AI 检测到登录成功`);
          currentSession.aiAssistant?.stopMonitoring();
          await this.handleLoginSuccess(sessionId);
        }

        // AI 检测到需要验证（只记录日志，不通知前端）
        if (result.status === 'verification_needed') {
          logger.info(`[${this.displayName}] AI 检测到需要验证: ${result.analysis.verificationType}`);
        }
      },
      this.AI_CHECK_INTERVAL
    );
  }

  // ==================== 登录成功处理 ====================

  /**
   * 处理登录成功
   * 【重要】先收集完所有账号信息，再发送成功事件
   */
  protected async handleLoginSuccess(sessionId: string): Promise<void> {
    const session = this.sessions.get(sessionId);
    if (!session || session.status !== 'pending') return;

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

      // 更新状态为正在获取信息（但不发送事件给前端）
      session.status = 'fetching';
      logger.info(`[${this.displayName}] 登录成功，开始收集账号信息...`);

      // 等待页面稳定
      await this.waitPageStable(session.page);

      // 【核心】收集完整账号信息（各平台实现，包括跳转作品页获取作品数）
      const accountInfo = await this.collectAccountInfo(session);

      if (!accountInfo || !accountInfo.accountId) {
        throw new Error('无法获取账号ID');
      }

      // 获取并加密 Cookie
      const cookies = await session.context.cookies();
      const encryptedCookies = CookieManager.encrypt(JSON.stringify(cookies));

      // 更新会话
      session.status = 'success';
      session.cookies = encryptedCookies;
      session.accountInfo = accountInfo;

      logger.info(`[${this.displayName}] 所有账号信息收集完成:`, {
        accountId: accountInfo.accountId,
        accountName: accountInfo.accountName,
        fansCount: accountInfo.fansCount,
        worksCount: accountInfo.worksCount,
      });

      // 【重要】只有在这里才发送成功事件，前端才显示保存按钮
      this.emit('loginResult', {
        sessionId,
        userId: session.userId,
        status: 'success',
        cookies: encryptedCookies,
        accountInfo,
        rawCookies: cookies,
      });

      // 注意：不关闭浏览器，让用户确认保存后再关闭
      // await this.closeSession(sessionId);

    } catch (error) {
      logger.error(`[${this.displayName}] 收集账号信息失败:`, error);
      session.status = 'failed';
      session.error = String(error);

      this.emit('loginResult', {
        sessionId,
        userId: session.userId,
        status: 'failed',
        error: String(error),
      });

      await this.closeSession(sessionId);
    }
  }

  /**
   * 等待页面稳定
   */
  protected async waitPageStable(page: Page): Promise<void> {
    try {
      await page.waitForLoadState('networkidle', { timeout: 10000 });
    } catch {
      // 超时继续
    }
    await page.waitForTimeout(2000);
  }

  /**
   * 收集账号信息（子类必须实现）
   * 
   * 要求：
   * 1. 获取基本信息（头像、昵称、账号ID、粉丝数等）
   * 2. 跳转到作品管理页获取作品数
   * 3. 返回完整的账号信息
   */
  protected abstract collectAccountInfo(session: LoginSession): Promise<AccountInfo | null>;

  /**
   * 等待 API 数据
   */
  protected async waitForApiData(session: LoginSession, dataKey: string, timeout = 10000): Promise<any> {
    const start = Date.now();
    while (Date.now() - start < timeout) {
      if (session.apiData?.[dataKey]) {
        return session.apiData[dataKey];
      }
      await session.page.waitForTimeout(500);
    }
    return null;
  }

  /**
   * 导航并等待 API 数据
   */
  protected async navigateAndWaitForApi(
    session: LoginSession,
    url: string,
    dataKey: string,
    timeout = 15000
  ): Promise<any> {
    // 清除旧数据
    if (session.apiData) {
      delete session.apiData[dataKey];
    }

    await session.page.goto(url, { waitUntil: 'domcontentloaded', timeout: 30000 });
    return this.waitForApiData(session, dataKey, timeout);
  }

  // ==================== 工具方法 ====================

  /**
   * 解析数字字符串（支持 万、亿、w）
   */
  protected parseNumber(str?: string | number): number {
    if (typeof str === 'number') return str;
    if (!str) return 0;

    const text = String(str);
    const match = text.match(/(\d+(?:\.\d+)?)\s*(万|亿|w)?/i);
    if (!match) return 0;

    let num = parseFloat(match[1]);
    if (match[2]) {
      if (match[2] === '万' || match[2].toLowerCase() === 'w') num *= 10000;
      if (match[2] === '亿') num *= 100000000;
    }
    return Math.floor(num);
  }

  // ==================== 会话管理 ====================

  /**
   * 设置超时
   */
  protected setupTimeout(sessionId: string): void {
    setTimeout(() => {
      const session = this.sessions.get(sessionId);
      if (session && session.status === 'pending') {
        session.status = 'timeout';
        session.error = '登录超时';

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

        this.closeSession(sessionId);
      }
    }, this.LOGIN_TIMEOUT);
  }

  /**
   * 处理浏览器关闭
   */
  protected handleBrowserClosed(sessionId: string): void {
    const session = this.sessions.get(sessionId);
    if (session && session.status === 'pending') {
      session.status = 'failed';
      session.error = '浏览器已关闭';

      this.emit('loginResult', {
        sessionId,
        userId: session.userId,
        status: 'failed',
        error: '浏览器已关闭',
      });
    }
  }

  /**
   * 获取会话状态
   */
  getSessionStatus(sessionId: string): {
    status: LoginSessionStatus;
    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 {
    return this.sessions.get(sessionId)?.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(`[${this.displayName}] 会话已取消: ${sessionId}`);
  }

  /**
   * 关闭会话（用户确认保存后调用）
   */
  async closeSession(sessionId: string): Promise<void> {
    const session = this.sessions.get(sessionId);
    if (!session) return;

    try {
      session.aiAssistant?.stopMonitoring();
      await session.aiAssistant?.destroy().catch(() => {});
      await session.page?.close().catch(() => {});
      await session.context?.close().catch(() => {});
      await session.browser?.close().catch(() => {});
    } catch (error) {
      logger.error(`[${this.displayName}] 关闭会话失败:`, error);
    }

    // 延迟删除会话（方便查询状态）
    setTimeout(() => this.sessions.delete(sessionId), 60000);
  }

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