import { logger } from '../../utils/logger';
import { ConnectorBus, PlatformProduct, PublishResult } from '../connectors/IPlatformConnector';
import { TaskFSM, TaskStatus, TaskRecord } from '../../domains/Trade/TaskFSM';
import { NodeProtocolService, TaskReceipt } from '../protocols/NodeProtocolService';
import { SchemaMappingService } from '../ai/SchemaMappingService';

/**
 * [CORE_INT_03] 发布编排与回执中心 (Publish Orchestrator)
 * @description 统一管理 API 与 No-API 平台的发布流程、任务重试与回执处理
 */
export class PublishOrchestrator {
  /**
   * 启动发布流程
   */
  static async startPublish(task: TaskRecord, product: PlatformProduct, platform: string, shopId: string): Promise<void> {
    logger.info(`[Orchestrator] Starting publish flow for Task: ${task.id}, Platform: ${platform}`);

    try {
      // 1. 状态转移至 EXECUTING
      await TaskFSM.transit(task, TaskStatus.EXECUTING);

      // 2. [CORE_AI_19] 自动类目映射
      const mapping = await SchemaMappingService.getOrCreateMapping(
        product.platform || 'UNKNOWN',
        product.category || 'Default',
        platform
      );
      
      const mappedProduct: PlatformProduct = {
        ...product,
        category: mapping.targetCategory,
        attributes: { ...product.attributes, ...mapping.attributeMapping }
      };

      const connector = ConnectorBus.getConnector(platform);

      // 3. 根据平台能力选择发布路径 (API vs No-API)
      if (connector.capabilities.hasApi) {
        await this.handleApiPublish(task, connector, shopId, mappedProduct);
      } else {
        await this.handleNoApiPublish(task, shopId, mappedProduct);
      }
    } catch (err: any) {
      logger.error(`[Orchestrator] Publish failed: ${err.message}`);
      await this.handleFailure(task, err.message);
    }
  }

  /**
   * 处理 API 平台的自动发布
   */
  private static async handleApiPublish(task: TaskRecord, connector: any, shopId: string, product: PlatformProduct) {
    logger.info(`[Orchestrator] Executing API publish for Task: ${task.id}`);
    
    const result: PublishResult = await connector.pushListing(shopId, product);
    
    if (result.success) {
      await this.handleReceipt({
        taskId: task.id,
        traceId: task.traceId,
        status: 'success',
        resultData: { externalId: result.externalId, publishUrl: result.publishUrl }
      });
    } else {
      throw new Error(result.error || 'Unknown API publish error');
    }
  }

  /**
   * 处理无 API 平台的异步发布 (下发至 Win Node Agent)
   */
  private static async handleNoApiPublish(task: TaskRecord, shopId: string, product: PlatformProduct) {
    logger.info(`[Orchestrator] Queuing No-API publish for Task: ${task.id} to Win Node`);
    
    // 实际业务中：将任务存入数据库或 Redis 队列，等待 Node Agent 拉取
    // 这里模拟下发成功，由 NodeAgent 异步回执
    logger.info(`[Orchestrator] Task ${task.id} is now waiting for Win Node agent receipt.`);
  }

  /**
   * 处理任务回执 (Task Receipt)
   */
  static async handleReceipt(receipt: TaskReceipt): Promise<void> {
    logger.info(`[Orchestrator] Received receipt for Task: ${receipt.taskId}, Status: ${receipt.status}`);

    // 1. 获取任务记录 (Mock)
    const task: TaskRecord = { id: receipt.taskId, tenantId: 'TEN-123', traceId: receipt.traceId, status: TaskStatus.EXECUTING, retryCount: 0 };

    // 2. 状态转移至 PUBLISHED 或 FAILED
    if (receipt.status === 'success') {
      await TaskFSM.transit(task, TaskStatus.PUBLISHED);
      // 3. 触发后续流程 (如对账通知)
      logger.info(`[Orchestrator] Task ${receipt.taskId} published successfully. Result: ${JSON.stringify(receipt.resultData)}`);
    } else {
      await this.handleFailure(task, receipt.errorMessage || 'Unknown failure', receipt.errorType);
    }
  }

  /**
   * 处理失败与重试逻辑
   */
  private static async handleFailure(task: TaskRecord, message: string, errorType?: 'RETRYABLE' | 'MANUAL_INTERVENTION') {
    logger.warn(`[Orchestrator] Handling failure for Task: ${task.id}, Error: ${message}`);
    
    const nextStatus = errorType === 'RETRYABLE' ? TaskStatus.FAILED_RETRYABLE : TaskStatus.FAILED_MANUAL;
    
    await TaskFSM.transit({ ...task, lastError: message }, nextStatus);
    
    // 如果可重试且未超过限制，自动重试
    if (nextStatus === TaskStatus.FAILED_RETRYABLE && task.retryCount < 3) {
      logger.info(`[Orchestrator] Auto-retrying Task: ${task.id} (Attempt ${task.retryCount + 1})`);
      // await this.startPublish(task, ...); // 实际应异步重试
    }
  }
}
