import db from '../../config/database';
import { AdAutoService } from '../../domains/Marketing/AdAutoService';
import { AIService } from '../../services/AIService';
import { DynamicPricingService } from '../../services/DynamicPricingService';
import { PublishService } from '../../services/PublishService';
import { logger } from '../../utils/logger';
import { CrawlerWorker } from '../../workers/CrawlerWorker';
import { PipelineContext, PipelineDefinition, StepResult, StepStatus } from './PipelineTypes';
import { SelfHealingAgent } from './SelfHealingAgent';

/**
 * [CORE_AUTO_01] 自治流水线引擎 (Autonomous Pipeline Engine)
 * @description 核心逻辑：Pipeline-as-Code，支持任务间逻辑依赖与 AI 自主触发
 */
export class PipelineEngine {
  private static readonly INSTANCE_TABLE = 'cf_pipeline_instances';
  private static readonly STEP_TABLE = 'cf_pipeline_steps';

  /**
   * 启动流水线
   */
  static async start(definition: PipelineDefinition, context: PipelineContext): Promise<string> {
    const instanceId = `PIPE-${Date.now()}`;
    logger.info(`[Pipeline] Starting instance ${instanceId} for definition ${definition.id}`);

    // 1. 保存实例
    await db(this.INSTANCE_TABLE).insert({
      id: instanceId,
      definition_id: definition.id,
      tenant_id: context.tenantId,
      shop_id: context.shopId,
      trace_id: context.traceId,
      status: StepStatus.RUNNING,
      context_variables: JSON.stringify(context.variables),
      created_at: new Date(),
      updated_at: new Date()
    });

    // 2. 初始化步骤
    for (const step of definition.steps) {
      await db(this.STEP_TABLE).insert({
        id: `${instanceId}-${step.id}`,
        instance_id: instanceId,
        type: step.type,
        status: StepStatus.PENDING,
        config: JSON.stringify(step.config),
        depends_on: JSON.stringify(step.dependsOn || []),
        created_at: new Date(),
        updated_at: new Date()
      });
    }

    // 3. 执行第一个可用步骤
    this.runNextSteps(instanceId, context).catch(err => 
      logger.error(`[Pipeline] Error running next steps for ${instanceId}: ${err.message}`)
    );

    return instanceId;
  }

  /**
   * 执行下一步任务
   */
  private static async runNextSteps(instanceId: string, context: PipelineContext) {
    const allSteps = await db(this.STEP_TABLE).where({ instance_id: instanceId });
    const pendingSteps = allSteps.filter(s => s.status === StepStatus.PENDING);
    const completedStepIds = allSteps.filter(s => s.status === StepStatus.COMPLETED).map(s => s.id.split('-').pop());

    for (const step of pendingSteps) {
      const dependsOn = JSON.parse(step.depends_on || '[]');
      const canRun = dependsOn.every((depId: string) => completedStepIds.includes(depId));

      if (canRun) {
        await this.executeStep(instanceId, step, context);
      }
    }
  }

  /**
   * 执行单个步骤 (含 AI 自愈逻辑)
   */
  private static async executeStep(instanceId: string, stepRecord: any, context: PipelineContext): Promise<void> {
    logger.info(`[Pipeline] Executing step ${stepRecord.id} (${stepRecord.type})`);

    // 1. 更新状态为 RUNNING
    await db(this.STEP_TABLE).where({ id: stepRecord.id }).update({ status: StepStatus.RUNNING, updated_at: new Date() });

    try {
      // 2. 收集前置步骤的输出作为上下文变量
      const allSteps = await db(this.STEP_TABLE).where({ instance_id: instanceId });
      const outputs: Record<string, any> = {};
      allSteps.forEach(s => {
        if (s.output) {
          const stepId = s.id.split('-').pop();
          outputs[stepId] = JSON.parse(s.output);
        }
      });

      const stepContext = {
        ...context,
        variables: { ...context.variables, ...outputs }
      };

      // 3. 分发到具体的处理器
      const result = await this.dispatchStep(stepRecord, stepContext);

      // 4. [CORE_AUTO_02] 异常自愈逻辑处理
      if (result.status === StepStatus.FAILED) {
        logger.warn(`[Pipeline] Step ${stepRecord.id} failed, triggering AI self-healing agent...`);
        const healingAction = await SelfHealingAgent.diagnoseAndHeal(stepRecord, result.error || 'Unknown error');
        
        if (healingAction.type !== 'NOTIFY_HUMAN') {
          const healingResult = await SelfHealingAgent.executeHealing(healingAction);
          if (healingResult) {
            logger.info(`[Pipeline] Healing action ${healingAction.type} executed, retrying step...`);
            // 简单重试逻辑
            return this.executeStep(instanceId, stepRecord, context);
          }
        }
      }

      // 5. 更新步骤结果
      await db(this.STEP_TABLE).where({ id: stepRecord.id }).update({
        status: result.status,
        output: JSON.stringify(result.output || {}),
        error: result.error,
        updated_at: new Date()
      });

      // 6. 如果是完成，尝试运行下一步
      if (result.status === StepStatus.COMPLETED) {
        await this.runNextSteps(instanceId, context);
      }
    } catch (err: any) {
      logger.error(`[Pipeline] Step ${stepRecord.id} failed: ${err.message}`);
      await db(this.STEP_TABLE).where({ id: stepRecord.id }).update({
        status: StepStatus.FAILED,
        error: err.message,
        updated_at: new Date()
      });
    }
  }

  /**
   * 实际分发逻辑：根据 StepType 路由到不同服务
   */
  private static async dispatchStep(stepRecord: any, context: PipelineContext): Promise<StepResult> {
    const config = JSON.parse(stepRecord.config || '{}');
    const type = stepRecord.type;

    try {
      switch (type) {
        case 'CRAWL':
          // 提交到异步队列
          await CrawlerWorker.submit({
            url: config.url || context.variables.url,
            sandbox: config.sandbox,
            traceContext: context
          });
          // 对于异步任务，我们将状态设置为 RUNNING 并等待回执（这里简化为完成，实际应监听任务完成事件）
          return { status: StepStatus.COMPLETED, output: { status: 'submitted_to_worker' } };

        case 'AI_OPTIMIZE':
          // 模拟从前置 CRAWL 步骤获取数据
          const crawlOutput = context.variables.crawl || {};
          const optimized = await AIService.analyzeMultiModalProduct({
            title: crawlOutput.title || '',
            description: crawlOutput.description,
            attributes: crawlOutput.attributes || {},
            imageUrls: crawlOutput.images || []
          });
          return { status: StepStatus.COMPLETED, output: optimized };

        case 'DYNAMIC_PRICING':
          const optimizeOutput = context.variables.optimize || {};
          const pricingResult = await DynamicPricingService.generatePricingDecision(
            context.tenantId,
            context.shopId,
            optimizeOutput.id || '0'
          );
          return { status: StepStatus.COMPLETED, output: pricingResult };

        case 'MULTI_PUBLISH':
          const platforms = config.platforms || context.variables.targetPlatforms || [];
          const optimizedData = context.variables.optimize || {};
          const pricingData = context.variables.pricing || {};
          
          for (const platform of platforms) {
            await PublishService.submitPublishTask({
              productId: optimizedData.id || 'new_product',
              platform,
              shopId: context.shopId,
              tenantId: context.tenantId,
              traceId: context.traceId,
              productData: {
                ...optimizedData,
                price: pricingData.suggestedPrice || optimizedData.price
              }, 
            });
          }
          return { status: StepStatus.COMPLETED, output: { publishedPlatforms: platforms } };

        case 'AD_CAMPAIGN':
          const publishOutput = context.variables.publish || {};
          await AdAutoService.createCampaign({
            id: `AD-${Date.now()}`,
            tenantId: context.tenantId,
            productId: publishOutput.externalId || 'unknown_id',
            platform: config.platform || 'FACEBOOK',
            dailyBudget: config.budget || 50,
            cpaLimit: config.cpa || 10
          });
          return { status: StepStatus.COMPLETED, output: { campaignCreated: true } };

        default:
          throw new Error(`Unsupported step type: ${type}`);
      }
    } catch (err: any) {
      return { status: StepStatus.FAILED, error: err.message };
    }
  }

  /**
   * 获取流水线状态
   */
  static async getInstanceStatus(instanceId: string): Promise<any> {
    const instance = await db(this.INSTANCE_TABLE).where({ id: instanceId }).first();
    const steps = await db(this.STEP_TABLE).where({ instance_id: instanceId });

    return {
      instance,
      steps
    };
  }
}

