import type { Browser, BrowserContext, Page } from 'playwright';
import type {
  PlatformType,
  QRCodeInfo,
  LoginStatusResult,
  ProxyConfig,
} from '@media-manager/shared';
import { BrowserManager } from '../browser.js';
import { logger } from '../../utils/logger.js';
import { aiService, type PublishStatusAnalysis, type PageOperationGuide } from '../../ai/index.js';

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

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

export interface PublishParams {
  videoPath: string;
  title: string;
  description?: string;
  coverPath?: string;
  tags?: string[];
  scheduledTime?: string | Date;  // 定时发布时间
  location?: string;  // 位置信息
  extra?: Record<string, unknown>;
}

export interface PublishResult {
  success: boolean;
  videoUrl?: string;
  platformVideoId?: string;
  errorMessage?: string;
}

export interface DateRange {
  startDate: string;
  endDate: string;
}

export interface AnalyticsData {
  fansCount: number;
  fansIncrease: number;
  viewsCount: number;
  likesCount: number;
  commentsCount: number;
  sharesCount: number;
  income?: number;
}

export interface CommentData {
  commentId: string;
  authorId: string;
  authorName: string;
  authorAvatar: string;
  content: string;
  likeCount: number;
  commentTime: string;
  parentCommentId?: string;
}

export interface InitBrowserOptions {
  proxyConfig?: ProxyConfig;
  headless?: boolean;  // 是否使用无头模式
}

/**
 * 平台适配器基类
 */
export abstract class BasePlatformAdapter {
  abstract readonly platform: PlatformType;
  abstract readonly loginUrl: string;
  
  protected browser: Browser | null = null;
  protected context: BrowserContext | null = null;
  protected page: Page | null = null;
  protected isHeadless: boolean = false;  // 记录当前是否为无头模式
  
  /**
   * 初始化浏览器
   * @param options.proxyConfig 代理配置
   * @param options.headless 是否使用无头模式（后台运行），默认 false
   */
  async initBrowser(options?: InitBrowserOptions | ProxyConfig): Promise<void> {
    // 如果已有浏览器上下文，先关闭
    if (this.context) {
      await this.closeBrowser();
    }
    
    // 兼容旧的调用方式（直接传 proxyConfig）
    let proxyConfig: ProxyConfig | undefined;
    let headless = false;
    
    if (options && 'headless' in options) {
      proxyConfig = options.proxyConfig;
      headless = options.headless ?? false;
    } else {
      proxyConfig = options as ProxyConfig | undefined;
    }
    
    this.isHeadless = headless;
    this.browser = await BrowserManager.getBrowser({ headless });
    
    const contextOptions: Record<string, unknown> = {
      viewport: { width: 1920, height: 1080 },
      locale: 'zh-CN',
      timezoneId: 'Asia/Shanghai',
    };
    
    if (proxyConfig?.enabled) {
      contextOptions.proxy = {
        server: `${proxyConfig.type}://${proxyConfig.host}:${proxyConfig.port}`,
        username: proxyConfig.username,
        password: proxyConfig.password,
      };
    }
    
    this.context = await this.browser.newContext(contextOptions);
    this.page = await this.context.newPage();
  }
  
  /**
   * 关闭浏览器
   * 对于 headful 模式，会关闭整个浏览器窗口
   */
  async closeBrowser(): Promise<void> {
    if (this.page) {
      await this.page.close();
      this.page = null;
    }
    if (this.context) {
      await this.context.close();
      this.context = null;
    }
    // 关闭对应的浏览器实例（特别是 headful 模式的浏览器窗口）
    if (!this.isHeadless) {
      await BrowserManager.closeBrowser({ headless: false });
    }
    this.browser = null;
  }
  
  /**
   * 设置 Cookie
   * 支持两种格式：
   * 1. JSON 数组格式：[{name, value, domain, path}]
   * 2. 字符串格式：name=value; name2=value2;
   */
  async setCookies(cookies: string): Promise<void> {
    if (!this.context) {
      throw new Error('Browser context not initialized');
    }
    
    try {
      let cookieList: Array<{ name: string; value: string; domain?: string; path?: string }>;
      
      // 尝试解析为 JSON
      try {
        cookieList = JSON.parse(cookies);
      } catch {
        // JSON 解析失败，尝试解析为 name=value 格式的字符串
        cookieList = this.parseCookieString(cookies);
      }
      
      // 确保每个 cookie 都有必要的字段
      const formattedCookies = cookieList.map(c => ({
        name: c.name,
        value: c.value,
        domain: c.domain || this.getCookieDomain(),
        path: c.path || '/',
      }));
      
      await this.context.addCookies(formattedCookies);
      logger.info(`Set ${formattedCookies.length} cookies`);
    } catch (error) {
      logger.error('Failed to set cookies:', error);
      throw error;
    }
  }
  
  /**
   * 解析 name=value; 格式的 cookie 字符串
   */
  private parseCookieString(cookieStr: string): Array<{ name: string; value: string; domain?: string; path?: string }> {
    const cookies: Array<{ name: string; value: string; domain?: string; path?: string }> = [];
    const pairs = cookieStr.split(';').map(s => s.trim()).filter(s => s);
    
    for (const pair of pairs) {
      const eqIndex = pair.indexOf('=');
      if (eqIndex > 0) {
        const name = pair.substring(0, eqIndex).trim();
        const value = pair.substring(eqIndex + 1).trim();
        if (name && !['path', 'domain', 'expires', 'max-age', 'secure', 'httponly', 'samesite'].includes(name.toLowerCase())) {
          cookies.push({ name, value });
        }
      }
    }
    
    return cookies;
  }
  
  /**
   * 获取平台对应的 cookie domain
   */
  protected getCookieDomain(): string {
    return '.douyin.com'; // 子类可以覆盖
  }
  
  /**
   * 获取 Cookie
   */
  async getCookies(): Promise<string> {
    if (!this.context) {
      throw new Error('Browser context not initialized');
    }
    
    const cookies = await this.context.cookies();
    return JSON.stringify(cookies);
  }
  
  /**
   * 等待元素
   */
  protected async waitForSelector(selector: string, timeout: number = 10000): Promise<void> {
    if (!this.page) throw new Error('Page not initialized');
    await this.page.waitForSelector(selector, { timeout });
  }
  
  /**
   * 点击元素
   */
  protected async click(selector: string): Promise<void> {
    if (!this.page) throw new Error('Page not initialized');
    await this.page.click(selector);
  }
  
  /**
   * 输入文本
   */
  protected async type(selector: string, text: string): Promise<void> {
    if (!this.page) throw new Error('Page not initialized');
    await this.page.fill(selector, text);
  }
  
  /**
   * 截图
   */
  protected async screenshot(path: string): Promise<void> {
    if (!this.page) throw new Error('Page not initialized');
    await this.page.screenshot({ path });
  }

  /**
   * 截图并返回 Base64 格式
   */
  protected async screenshotBase64(): Promise<string> {
    if (!this.page) throw new Error('Page not initialized');
    const buffer = await this.page.screenshot({ type: 'jpeg', quality: 80 });
    return buffer.toString('base64');
  }

  /**
   * 获取页面 HTML
   */
  protected async getPageHtml(): Promise<string> {
    if (!this.page) throw new Error('Page not initialized');
    return await this.page.content();
  }

  // ==================== AI 辅助发布方法 ====================

  /**
   * AI 分析发布页面状态
   * @returns 发布状态分析结果
   */
  protected async aiAnalyzePublishStatus(): Promise<PublishStatusAnalysis | null> {
    if (!aiService.isAvailable()) {
      logger.debug('[AI Publish] AI service not available');
      return null;
    }

    try {
      const screenshot = await this.screenshotBase64();
      const result = await aiService.analyzePublishStatus(screenshot, this.platform);
      logger.info(`[AI Publish] Status analysis: ${result.status}, confidence: ${result.confidence}%`);
      return result;
    } catch (error) {
      logger.error('[AI Publish] Failed to analyze status:', error);
      return null;
    }
  }

  /**
   * AI 获取发布操作指导
   * @param currentStatus 当前状态描述
   * @returns 操作指导
   */
  protected async aiGetPublishOperationGuide(currentStatus: string): Promise<PageOperationGuide | null> {
    if (!aiService.isAvailable()) {
      logger.debug('[AI Publish] AI service not available');
      return null;
    }

    try {
      const html = await this.getPageHtml();
      const result = await aiService.analyzePublishPageHtml(html, this.platform, currentStatus);
      logger.info(`[AI Publish] Operation guide: hasAction=${result.hasAction}, action=${result.actionType}`);
      return result;
    } catch (error) {
      logger.error('[AI Publish] Failed to get operation guide:', error);
      return null;
    }
  }

  /**
   * 将AI返回的选择器转换为Playwright兼容的格式
   * @param selector 原始选择器
   * @returns 转换后的选择器
   */
  private convertToPlaywrightSelector(selector: string): string {
    let converted = selector;
    
    // 将 :contains('text') 或 :contains("text") 转换为 :has-text("text")
    converted = converted.replace(/:contains\(['"]([^'"]+)['"]\)/g, ':has-text("$1")');
    converted = converted.replace(/:contains\(([^)]+)\)/g, ':has-text("$1")');
    
    // 移除不支持的伪类选择器
    // 如果选择器包含不支持的语法，尝试简化
    if (converted.includes(':contains')) {
      // 如果还有 :contains，提取文本用于 text= 选择器
      const match = converted.match(/:contains\(['"]?([^'")\]]+)['"]?\)/);
      if (match) {
        return `text="${match[1]}"`;
      }
    }
    
    return converted;
  }

  /**
   * AI 辅助执行操作
   * @param guide 操作指导
   * @returns 是否执行成功
   */
  protected async aiExecuteOperation(guide: PageOperationGuide): Promise<boolean> {
    if (!this.page || !guide.hasAction) return false;

    try {
      switch (guide.actionType) {
        case 'click':
          if (guide.targetSelector) {
            // 转换选择器为Playwright兼容格式
            const selector = this.convertToPlaywrightSelector(guide.targetSelector);
            logger.info(`[AI Publish] Clicking: ${selector} (original: ${guide.targetSelector})`);
            
            try {
              await this.page.click(selector, { timeout: 10000 });
              return true;
            } catch (selectorError) {
              // 如果选择器失败，尝试使用位置点击
              if (guide.targetPosition) {
                logger.info(`[AI Publish] Selector failed, trying position click: ${guide.targetPosition.x}, ${guide.targetPosition.y}`);
                await this.page.mouse.click(guide.targetPosition.x, guide.targetPosition.y);
                return true;
              }
              
              // 尝试使用文本匹配
              if (guide.targetDescription) {
                const textSelector = `text="${guide.targetDescription}"`;
                logger.info(`[AI Publish] Trying text selector: ${textSelector}`);
                try {
                  await this.page.click(textSelector, { timeout: 5000 });
                  return true;
                } catch {
                  // 继续抛出原始错误
                }
              }
              
              throw selectorError;
            }
          }
          break;

        case 'input':
          if (guide.targetSelector && guide.inputText) {
            const selector = this.convertToPlaywrightSelector(guide.targetSelector);
            logger.info(`[AI Publish] Inputting to: ${selector}`);
            await this.page.fill(selector, guide.inputText);
            return true;
          }
          break;

        case 'wait':
          logger.info('[AI Publish] Waiting...');
          await this.page.waitForTimeout(3000);
          return true;

        case 'scroll':
          logger.info('[AI Publish] Scrolling...');
          await this.page.evaluate(() => window.scrollBy(0, 300));
          return true;
      }
    } catch (error) {
      logger.error(`[AI Publish] Failed to execute operation:`, error);
    }

    return false;
  }

  /**
   * AI 辅助发布监控循环
   * 监控发布过程，检测验证码和发布结果
   * @param options 配置选项
   * @returns 发布结果
   */
  protected async aiAssistedPublishMonitor(options: {
    maxAttempts?: number;
    checkInterval?: number;
    onCaptchaRequired?: (captchaInfo: {
      taskId: string;
      type: 'sms' | 'image';
      captchaDescription?: string;
      imageBase64?: string;
    }) => Promise<string>;
    onProgress?: (progress: number, message: string) => void;
  }): Promise<{ success: boolean; message: string; needManualIntervention?: boolean }> {
    const maxAttempts = options.maxAttempts || 30;
    const checkInterval = options.checkInterval || 3000;

    for (let attempt = 0; attempt < maxAttempts; attempt++) {
      // 等待页面稳定
      await this.page?.waitForTimeout(checkInterval);

      // AI 分析当前页面状态
      const status = await this.aiAnalyzePublishStatus();
      if (!status) {
        logger.warn('[AI Publish] AI analysis unavailable, continuing...');
        continue;
      }

      logger.info(`[AI Publish] Attempt ${attempt + 1}/${maxAttempts}: status=${status.status}`);

      switch (status.status) {
        case 'success':
          options.onProgress?.(100, '发布成功');
          return { success: true, message: status.pageDescription };

        case 'failed':
          options.onProgress?.(0, status.errorMessage || '发布失败');
          return { success: false, message: status.errorMessage || '发布失败' };

        case 'need_captcha':
          if (options.onCaptchaRequired) {
            options.onProgress?.(50, `检测到验证码: ${status.captchaDescription || '请输入验证码'}`);

            // 如果是图片验证码，截图发送
            let imageBase64: string | undefined;
            if (status.captchaType === 'image' || status.captchaType === 'slider') {
              imageBase64 = await this.screenshotBase64();
            }

            try {
              const captchaCode = await options.onCaptchaRequired({
                taskId: `captcha_${Date.now()}`,
                type: status.captchaType === 'sms' ? 'sms' : 'image',
                captchaDescription: status.captchaDescription,
                imageBase64,
              });

              // 用户输入了验证码，尝试 AI 指导输入
              if (captchaCode && status.nextAction?.targetSelector) {
                await this.page?.fill(status.nextAction.targetSelector, captchaCode);
                await this.page?.waitForTimeout(500);

                // 尝试点击确认按钮
                const guide = await this.aiGetPublishOperationGuide('已输入验证码，需要点击确认');
                if (guide?.hasAction && guide.actionType === 'click' && guide.targetSelector) {
                  await this.page?.click(guide.targetSelector);
                }
              }
            } catch (captchaError) {
              logger.error('[AI Publish] Captcha handling failed:', captchaError);
              return { success: false, message: '验证码处理失败', needManualIntervention: true };
            }
          } else {
            // 没有验证码处理回调，需要人工介入
            logger.warn('[AI Publish] Captcha required but no handler provided');
            return { success: false, message: '需要验证码', needManualIntervention: true };
          }
          break;

        case 'need_action':
          if (status.nextAction) {
            options.onProgress?.(Math.min(80, 50 + attempt * 2), status.pageDescription);

            // 尝试执行 AI 建议的操作
            const guide = await this.aiGetPublishOperationGuide(status.pageDescription);
            if (guide?.hasAction) {
              await this.aiExecuteOperation(guide);
            }
          }
          break;

        case 'uploading':
        case 'processing':
          options.onProgress?.(Math.min(90, 30 + attempt * 2), status.pageDescription);
          // 继续等待
          break;
      }
    }

    // 超过最大尝试次数
    logger.warn('[AI Publish] Max attempts reached');
    return { success: false, message: '发布超时，请检查发布状态' };
  }

  /**
   * AI 辅助处理 Python API 发布结果
   * 当 Python 返回截图时，使用 AI 分析发布状态
   * @param result Python API 返回的结果
   * @param onCaptchaRequired 验证码回调
   * @param onProgress 进度回调
   * @returns 处理后的发布结果
   */
  protected async aiProcessPythonPublishResult(
    result: {
      success?: boolean;
      screenshot_base64?: string;
      page_url?: string;
      video_id?: string;
      video_url?: string;
      need_captcha?: boolean;
      captcha_type?: string;
      status?: string;
      error?: string;
    },
    onCaptchaRequired?: (captchaInfo: {
      taskId: string;
      type: 'sms' | 'image';
      phone?: string;
      imageBase64?: string;
    }) => Promise<string>,
    onProgress?: (progress: number, message: string) => void
  ): Promise<PublishResult & { needCaptcha?: boolean; captchaType?: string }> {
    // 如果 Python 返回成功
    if (result.success) {
      onProgress?.(100, '发布成功');
      return {
        success: true,
        platformVideoId: result.video_id || `${this.platform}_${Date.now()}`,
        videoUrl: result.video_url || '',
      };
    }

    // 如果返回了截图，使用 AI 分析
    if (result.screenshot_base64 && aiService.isAvailable()) {
      logger.info(`[${this.platform} Python] Got screenshot, analyzing with AI...`);
      
      const aiStatus = await aiService.analyzePublishStatus(result.screenshot_base64, this.platform);
      logger.info(`[${this.platform} Python] AI analysis: status=${aiStatus.status}, confidence=${aiStatus.confidence}%`);

      // AI 判断发布成功
      if (aiStatus.status === 'success' && aiStatus.confidence >= 70) {
        onProgress?.(100, '发布成功');
        return {
          success: true,
          platformVideoId: result.video_id || `${this.platform}_${Date.now()}`,
          videoUrl: result.video_url || result.page_url || '',
        };
      }

      // AI 检测到需要验证码
      if (aiStatus.status === 'need_captcha') {
        logger.info(`[${this.platform} Python] AI detected captcha: ${aiStatus.captchaDescription}`);
        
        if (onCaptchaRequired) {
          onProgress?.(50, `AI 检测到验证码: ${aiStatus.captchaDescription || '请输入验证码'}`);
          
          try {
            const captchaCode = await onCaptchaRequired({
              taskId: `${this.platform}_captcha_${Date.now()}`,
              type: aiStatus.captchaType === 'sms' ? 'sms' : 'image',
              imageBase64: result.screenshot_base64,
            });
            
            // 验证码已获取，但 Python 发布已结束，需要通过 Playwright 继续
            logger.info(`[${this.platform} Python] Got captcha code, need to continue with Playwright`);
          } catch {
            logger.error(`[${this.platform} Python] Captcha handling failed`);
          }
        }

        return {
          success: false,
          needCaptcha: true,
          captchaType: aiStatus.captchaType || 'image',
          errorMessage: aiStatus.captchaDescription || '需要验证码',
        };
      }

      // AI 判断发布失败
      if (aiStatus.status === 'failed' && aiStatus.confidence >= 70) {
        return {
          success: false,
          errorMessage: aiStatus.errorMessage || 'AI 检测到发布失败',
        };
      }
    }

    // Python 返回需要验证码
    if (result.need_captcha || result.status === 'need_captcha') {
      logger.info(`[${this.platform} Python] Captcha required: type=${result.captcha_type}`);
      onProgress?.(0, `检测到需要验证码，切换到浏览器模式...`);
      return {
        success: false,
        needCaptcha: true,
        captchaType: result.captcha_type || 'image',
        errorMessage: result.error || '需要验证码',
      };
    }

    // 其他失败情况
    return {
      success: false,
      errorMessage: result.error || '发布失败',
    };
  }

  // ==================== 抽象方法 - 子类必须实现 ====================
  
  /**
   * 获取扫码登录二维码
   */
  abstract getQRCode(): Promise<QRCodeInfo>;
  
  /**
   * 检查扫码状态
   */
  abstract checkQRCodeStatus(qrcodeKey: string): Promise<LoginStatusResult>;
  
  /**
   * 检查登录状态
   */
  abstract checkLoginStatus(cookies: string): Promise<boolean>;
  
  /**
   * 获取账号信息
   */
  abstract getAccountInfo(cookies: string): Promise<AccountProfile>;
  
  /**
   * 发布视频
   */
  abstract publishVideo(cookies: string, params: PublishParams): Promise<PublishResult>;
  
  /**
   * 获取评论列表
   */
  abstract getComments(cookies: string, videoId: string): Promise<CommentData[]>;
  
  /**
   * 回复评论
   */
  abstract replyComment(cookies: string, commentId: string, content: string): Promise<boolean>;
  
  /**
   * 获取数据统计
   */
  abstract getAnalytics(cookies: string, dateRange: DateRange): Promise<AnalyticsData>;
}
