/**
 * 基础Adapter - 提供工具注册和管理功能
 */

import { ISiteAdapter } from './ISiteAdapter';
import { ITool } from '../tools/ITool';

/**
 * Adapter抽象基类
 */
export abstract class BaseAdapter implements ISiteAdapter {
  abstract readonly name: string;
  
  protected context: any;
  private tools = new Map<string, ITool>();
  private toolConfigs = new Map<string, any>();
  
  /**
   * 初始化流程 - 模板方法
   */
  async initialize(context: any): Promise<void> {
    this.context = context;
    
    console.log(`🔧 Initializing ${this.name} adapter...`);
    
    // 1. 子类注册工具
    this.registerTools();
    
    // 2. 验证必需工具
    this.validateRequiredTools();
    
    // 3. 初始化所有工具
    await this.initializeTools();
    
    console.log(`✅ ${this.name} adapter initialized\n`);
  }
  
  /**
   * 强制子类实现 - 注册需要的工具
   */
  protected abstract registerTools(): void;
  
  /**
   * 强制子类声明 - 必需的工具列表
   */
  protected abstract getRequiredTools(): string[];
  
  /**
   * 获取custom action handlers
   */
  abstract getHandlers(): Record<string, (...args: any[]) => Promise<any>>;
  
  /**
   * 注册工具（支持传入配置）
   */
  protected registerTool(tool: ITool, config?: any): void {
    if (this.tools.has(tool.name)) {
      throw new Error(`Tool already registered: ${tool.name}`);
    }
    this.tools.set(tool.name, tool);
    if (config) {
      this.toolConfigs.set(tool.name, config);
    }
    console.log(`  ✓ Registered: ${tool.name}`);
  }
  
  /**
   * 获取工具（类型安全）
   */
  protected getTool<T extends ITool>(name: string): T {
    const tool = this.tools.get(name);
    if (!tool) {
      throw new Error(
        `Tool not found: ${name}. Available tools: ${Array.from(this.tools.keys()).join(', ')}`
      );
    }
    return tool as T;
  }
  
  /**
   * 检查工具是否存在
   */
  protected hasTool(name: string): boolean {
    return this.tools.has(name);
  }
  
  /**
   * 验证必需工具
   */
  private validateRequiredTools(): void {
    const required = this.getRequiredTools();
    const missing: string[] = [];
    
    for (const toolName of required) {
      if (!this.tools.has(toolName)) {
        missing.push(toolName);
      }
    }
    
    if (missing.length > 0) {
      throw new Error(
        `Missing required tools: ${missing.join(', ')}. Please register them in registerTools().`
      );
    }
  }
  
  /**
   * 初始化所有工具
   */
  private async initializeTools(): Promise<void> {
    console.log(`\n  Initializing ${this.tools.size} tools...`);
    
    for (const [name, tool] of this.tools) {
      try {
        await tool.initialize(this.getToolConfig(name));
      } catch (error: any) {
        console.error(`  ❌ Tool ${name} initialization error:`, error);
        throw new Error(`Failed to initialize tool ${name}: ${error.message}\n${error.stack}`);
      }
    }
  }
  
  /**
   * 获取工具配置（子类可覆盖以提供动态配置）
   */
  protected getToolConfig(toolName: string): any {
    return this.toolConfigs.get(toolName);
  }
  
  /**
   * Workflow执行前（可选）
   */
  async beforeWorkflow?(context: any): Promise<void>;
  
  /**
   * Workflow执行后（可选）
   */
  async afterWorkflow?(context: any, result: any): Promise<void>;
  
  /**
   * 执行重试策略（通用方法，与旧框架一致）
   */
  protected async executeRetryStrategy(
    strategy: 'refresh' | 'restart' | 'wait', 
    retryCount: number,
    options: any = {}
  ): Promise<void> {
    const page = this.context?.page;
    
    if (!page) {
      console.warn('⚠️  No page available for retry strategy');
      return;
    }
    
    switch (strategy) {
      case 'refresh':
        console.log('策略: 刷新当前页面');
        await page.reload({ waitUntil: 'networkidle2', timeout: 30000 });
        await new Promise(resolve => setTimeout(resolve, 3000));
        break;
        
      case 'restart':
        // 重新开始流程（适用于刷新后回到初始状态的网站）
        console.warn('策略: 刷新会重置，执行自定义恢复');
        await page.reload({ waitUntil: 'networkidle2', timeout: 30000 });
        await new Promise(resolve => setTimeout(resolve, 3000));
        
        // 调用站点特定的恢复方法
        if (this.onRestart && typeof this.onRestart === 'function') {
          const restartSteps = await this.onRestart(options);
          
          // 如果返回步骤名称数组，则重新执行这些步骤
          if (Array.isArray(restartSteps) && restartSteps.length > 0) {
            console.log(`需要重新执行 ${restartSteps.length} 个步骤`);
            // TODO: 实现 rerunSteps 或通过引擎重新执行
          }
        } else {
          console.warn('未定义 onRestart 方法，跳过恢复步骤');
        }
        break;
        
      case 'wait':
        const waitTime = options.waitTime || 10000;
        console.log(`策略: 延长等待 ${waitTime}ms（第 ${retryCount} 次）`);
        await new Promise(resolve => setTimeout(resolve, waitTime));
        break;
        
      default:
        console.warn(`未知重试策略: ${strategy}，使用默认等待`);
        await new Promise(resolve => setTimeout(resolve, 5000));
    }
  }
  
  /**
   * 重启后的恢复钩子（子类可重写）
   * @returns 返回需要重新执行的步骤名称数组，或 void（自定义实现）
   */
  protected async onRestart?(options?: any): Promise<string[] | void>;
  
  /**
   * 清理所有工具
   */
  async cleanup(): Promise<void> {
    console.log(`\n🧹 Cleaning up ${this.name} adapter...`);
    
    for (const [name, tool] of this.tools) {
      if (tool.cleanup) {
        try {
          await tool.cleanup();
        } catch (error: any) {
          console.error(`  ⚠️  Failed to cleanup ${name}: ${error.message}`);
        }
      }
    }
    
    console.log(`✅ ${this.name} adapter cleaned up`);
  }
}
