/**
 * 通用自动化执行工具
 * 根据YAML配置自动化执行任意网站的操作流程
 * 
 * 用法：
 *   npm run run -- windsurf     # 执行Windsurf自动化
 *   npm run run -- stripe       # 执行Stripe自动化
 *   npm run run -- <网站名>      # 执行任意网站自动化
 * 
 * 配置文件位置：configs/sites/<网站名>.yaml
 */

import * as fs from 'fs';
import * as path from 'path';
import * as yaml from 'js-yaml';
import { AdsPowerProvider } from '../src/providers/adspower/AdsPowerProvider';
import { WorkflowEngine } from '../src/workflow/WorkflowEngine';
import { ISiteAdapter, EmptyAdapter } from '../src/adapters/ISiteAdapter';

interface WorkflowConfig {
  site: string;
  workflow: any[];
  errorHandling?: any;
  variables?: any;
  url?: string;
  siteConfig?: {
    url?: string;
    name?: string;
    [key: string]: any;
  };
}

class AutomationRunner {
  private siteName: string;
  private configPath: string;
  private adapterPath: string;
  private adapter: ISiteAdapter | null = null;

  constructor(siteName: string) {
    this.siteName = siteName;
    this.configPath = path.join(__dirname, '../configs/sites', `${siteName}.yaml`);
    this.adapterPath = path.join(__dirname, '../configs/sites', `${siteName}-adapter.ts`);
  }

  async run() {
    console.log('🚀 Browser Automation Executor\n');
    console.log(`Site: ${this.siteName}`);
    console.log(`Config: ${this.configPath}\n`);

    // 1. 检查配置文件
    if (!fs.existsSync(this.configPath)) {
      console.error(`❌ Config file not found: ${this.configPath}`);
      console.log('\n💡 Available configs:');
      this.listAvailableConfigs();
      process.exit(1);
    }

    // 2. 加载配置
    const config = this.loadConfig();
    console.log(`✅ Loaded workflow with ${config.workflow.length} steps\n`);

    // 2.5. 加载Adapter（如果存在）
    await this.loadAdapter();

    // 3. 初始化Provider
    const provider = await this.initializeProvider();

    try {
      // 4. 启动浏览器
      const result = await provider.launch();
      console.log('✅ Browser launched successfully\n');

      // 5. 准备Context
      const context = this.buildContext(result, config);

      // 5.5. 初始化Adapter
      if (this.adapter) {
        await this.adapter.initialize(context);
        if (this.adapter.beforeWorkflow) {
          await this.adapter.beforeWorkflow(context);
        }
      }

      // 6. 创建并执行WorkflowEngine
      const engine = new WorkflowEngine(
        config.workflow,
        context,
        provider.getActionFactory()
      );

      console.log('▶️  Starting workflow execution...\n');
      const workflowResult = await engine.execute();

      // 7. 显示结果
      this.displayResults(workflowResult, config.workflow.length);

      // 7.5. Adapter后处理
      if (this.adapter && this.adapter.afterWorkflow) {
        await this.adapter.afterWorkflow(context, workflowResult);
      }

      // 8. 等待查看
      console.log('⏸️  Waiting 5 seconds before closing...');
      await new Promise(resolve => setTimeout(resolve, 5000));

    } catch (error: any) {
      console.error('\n❌ Fatal error:', error.message);
      console.error(error.stack);
    } finally {
      await this.cleanup(provider);
    }
  }

  private loadConfig(): WorkflowConfig {
    const content = fs.readFileSync(this.configPath, 'utf8');
    return yaml.load(content) as WorkflowConfig;
  }

  /**
   * 动态加载网站适配器
   */
  private async loadAdapter(): Promise<void> {
    // 检查是否存在adapter文件（支持.ts和.js）
    const tsPath = this.adapterPath;
    const jsPath = this.adapterPath.replace('.ts', '.js');
    
    let adapterPath: string | null = null;
    if (fs.existsSync(tsPath)) {
      adapterPath = tsPath;
    } else if (fs.existsSync(jsPath)) {
      adapterPath = jsPath;
    }

    if (!adapterPath) {
      console.log(`⚠️  No adapter found for ${this.siteName}, using empty adapter`);
      this.adapter = new EmptyAdapter();
      return;
    }

    try {
      console.log(`🔌 Loading adapter: ${path.basename(adapterPath)}`);
      
      // 动态导入adapter
      const adapterModule = await import(adapterPath);
      const AdapterClass = adapterModule.default;
      
      if (!AdapterClass) {
        throw new Error('Adapter must have a default export');
      }

      this.adapter = new AdapterClass();
      console.log(`✅ Adapter loaded: ${this.adapter!.name}\n`);
      
    } catch (error: any) {
      console.error(`❌ Failed to load adapter: ${error.message}`);
      console.log('Using empty adapter as fallback\n');
      this.adapter = new EmptyAdapter();
    }
  }

  private async initializeProvider(): Promise<AdsPowerProvider> {
    console.log('🌐 Initializing AdsPower Provider...');
    
    return new AdsPowerProvider({
      profileId: process.env.ADSPOWER_USER_ID,
      siteName: this.siteName.charAt(0).toUpperCase() + this.siteName.slice(1)
    });
  }

  private buildContext(launchResult: any, config: WorkflowConfig): any {
    // 创建空context - Adapter负责填充数据
    return {
      page: launchResult.page,
      browser: launchResult.browser,
      logger: console,
      data: {
        account: {},  // Adapter会在beforeWorkflow中填充
        ...config.variables
      },
      siteConfig: config.siteConfig || {
        url: config.url || '',
        name: config.site || this.siteName
      },
      config: config,
      siteName: this.siteName,
      // 注入adapter的handlers
      adapter: this.adapter ? this.adapter.getHandlers() : {}
    };
  }

  private displayResults(result: any, totalSteps: number): void {
    console.log('\n' + '='.repeat(60));
    console.log('📊 Workflow Execution Summary');
    console.log('='.repeat(60));
    console.log(`Site: ${this.siteName}`);
    console.log(`Status: ${result.success ? '✅ SUCCESS' : '❌ FAILED'}`);
    console.log(`Steps Completed: ${result.steps}/${totalSteps}`);
    console.log(`Duration: ${(result.duration / 1000).toFixed(2)}s`);
    console.log(`Errors: ${result.errors.length}`);
    
    if (result.errors.length > 0) {
      console.log('\n❌ Errors:');
      result.errors.forEach((err: any, i: number) => {
        console.log(`  ${i + 1}. Step ${err.step} (${err.name}): ${err.error}`);
      });
    }
    console.log('='.repeat(60) + '\n');
  }

  private async cleanup(provider: AdsPowerProvider): Promise<void> {
    try {
      console.log('\n🔒 Closing browser...');
      await provider.close();
      console.log('✅ Browser closed successfully');
      
      // 清理adapter资源
      if (this.adapter && this.adapter.cleanup) {
        await this.adapter.cleanup();
      }
    } catch (e: any) {
      console.error('⚠️  Error closing browser:', e.message);
    }
  }

  private listAvailableConfigs(): void {
    const configsDir = path.join(__dirname, '../configs/sites');
    
    if (!fs.existsSync(configsDir)) {
      console.log('  (No configs directory found)');
      return;
    }

    const files = fs.readdirSync(configsDir)
      .filter(f => f.endsWith('.yaml') || f.endsWith('.yml'))
      .map(f => f.replace(/\.(yaml|yml)$/, ''));

    if (files.length === 0) {
      console.log('  (No config files found)');
    } else {
      files.forEach(name => console.log(`  - ${name}`));
    }
  }
}

// 主程序
async function main() {
  const args = process.argv.slice(2);
  
  // 参数格式：node cli/run.js <browser-provider> <browser-params> <site>
  // 示例：node cli/run.js adspower k1728p8l windsurf
  
  if (args.length < 3) {
    console.error('❌ Usage: node cli/run.js <browser-provider> <browser-params> <site>');
    console.error('\nArguments:');
    console.error('  browser-provider  浏览器提供商 (adspower, playwright, etc)');
    console.error('  browser-params    浏览器参数 (AdsPower的profileId, 或 - 表示默认)');
    console.error('  site              网站名称 (windsurf, stripe, etc)\n');
    console.error('Examples:');
    console.error('  node cli/run.js adspower k1728p8l windsurf');
    console.error('  node cli/run.js playwright - windsurf');
    console.error('  node cli/run.js adspower j9abc123 stripe\n');
    process.exit(1);
  }

  const browserProvider = args[0];
  const browserParams = args[1];
  const siteName = args[2];

  console.log('🚀 Browser Automation Executor\n');
  console.log(`Browser: ${browserProvider}`);
  console.log(`Params: ${browserParams}`);
  console.log(`Site: ${siteName}\n`);

  // 设置浏览器参数
  if (browserProvider === 'adspower') {
    if (browserParams !== '-') {
      process.env.ADSPOWER_USER_ID = browserParams;
      console.log(`📍 AdsPower Profile: ${browserParams}`);
    }
  }

  const runner = new AutomationRunner(siteName);

  try {
    await runner.run();
    console.log('\n✅ Automation completed successfully!');
    process.exit(0);
  } catch (error: any) {
    console.error('\n❌ Automation failed:', error.message);
    console.error(error.stack);
    process.exit(1);
  }
}

main();
