import { Job } from 'bullmq';
import { WorkerHub } from './WorkerHub';
import { PlatformApiService, PlatformApiConfig, SyncOptions } from '../services/PlatformApiService';
import { ProductService } from '../services/ProductService';
import { OrderService } from '../services/OrderService';
import { AuditService } from '../services/AuditService';
import { logger } from '../utils/logger';

/**
 * PlatformSyncWorker - 平台数据同步Worker
 * 
 * 功能定位：
 * - 异步执行有API平台的数据同步（Amazon, eBay, Shopee等）
 * - 支持商品同步、订单同步、库存更新
 * - 无API平台的采集由浏览器插件处理，不经过此Worker
 * 
 * 安全约束：
 * - 并发数限制 ≤ 10（符合资源保护要求）
 * - 所有操作携带五元组追踪信息
 * - 支持限流和错误重试
 * 
 * @author AI-Backend-1
 * @taskId BE-P008, BE-O007
 */

interface SyncJobData {
  syncType: 'PRODUCT' | 'ORDER' | 'INVENTORY';
  platformConfig: PlatformApiConfig;
  syncOptions: SyncOptions;
  retryCount?: number;
}

export class PlatformSyncWorker {
  private static readonly QUEUE_NAME = 'platform-sync-tasks';
  private static readonly MAX_RETRIES = 3;
  private static readonly CONCURRENCY = 10; // 符合资源限制

  /**
   * 初始化并注册Worker
   */
  static init() {
    WorkerHub.registerWorker(
      this.QUEUE_NAME,
      async (job: Job<SyncJobData>) => {
        const { syncType, platformConfig, syncOptions, retryCount = 0 } = job.data;
        const { tenantId, shopId, taskId, traceId, businessType } = syncOptions;

        logger.info(`[PlatformSyncWorker] Starting ${syncType} sync task`, {
          jobId: job.id,
          platform: platformConfig.platform,
          tenantId,
          shopId,
          taskId,
          traceId,
          businessType,
          retryCount,
        });

        const startTime = Date.now();

        try {
          let result: any;

          switch (syncType) {
            case 'PRODUCT':
              result = await this.syncProducts(platformConfig, syncOptions);
              break;
            case 'ORDER':
              result = await this.syncOrders(platformConfig, syncOptions);
              break;
            case 'INVENTORY':
              result = await this.syncInventory(platformConfig, syncOptions);
              break;
            default:
              throw new Error(`Unknown sync type: ${syncType}`);
          }

          const duration = Date.now() - startTime;

          // 审计日志 - 成功
          await AuditService.log({
            tenantId,
            shopId,
            taskId,
            traceId,
            businessType,
            module: 'PLATFORM_SYNC',
            action: `${syncType}_SYNC_SUCCESS`,
            resourceType: 'sync_job',
            resourceId: String(job.id),
            afterSnapshot: {
              platform: platformConfig.platform,
              syncType,
              duration,
              resultCount: result?.length || 0,
            },
            result: 'success',
            source: 'node',
          });

          logger.info(`[PlatformSyncWorker] ${syncType} sync completed`, {
            jobId: job.id,
            duration,
            resultCount: result?.length || 0,
          });

          return {
            success: true,
            syncType,
            platform: platformConfig.platform,
            duration,
            resultCount: result?.length || 0,
            data: result,
          };
        } catch (error: any) {
          const duration = Date.now() - startTime;

          logger.error(`[PlatformSyncWorker] ${syncType} sync failed`, {
            jobId: job.id,
            platform: platformConfig.platform,
            error: error.message,
            duration,
            retryCount,
          });

          // 审计日志 - 失败
          await AuditService.log({
            tenantId,
            shopId,
            taskId,
            traceId,
            businessType,
            module: 'PLATFORM_SYNC',
            action: `${syncType}_SYNC_FAILED`,
            resourceType: 'sync_job',
            resourceId: String(job.id),
            result: 'failed',
            errorCode: 'PLATFORM_SYNC_ERROR',
            errorMessage: error.message,
            source: 'node',
          });

          // 重试逻辑
          if (retryCount < this.MAX_RETRIES) {
            logger.info(`[PlatformSyncWorker] Retrying task ${job.id}`, {
              retryCount: retryCount + 1,
            });
            throw error; // 抛出错误触发BullMQ重试
          }

          // 超过重试次数，返回失败结果
          return {
            success: false,
            syncType,
            platform: platformConfig.platform,
            duration,
            error: error.message,
            retryCount,
          };
        }
      },
      this.CONCURRENCY
    );

    logger.info('[PlatformSyncWorker] Worker registered successfully');
  }

  // ==================== Private Methods ====================

  /**
   * 同步商品数据
   */
  private static async syncProducts(
    config: PlatformApiConfig,
    options: SyncOptions
  ): Promise<any[]> {
    const products = await PlatformApiService.syncProducts(config, options);

    // 保存到数据库
    const savedProducts = [];
    for (const product of products) {
      try {
        const productId = await ProductService.create(options.tenantId, {
          shopId: options.shopId,
          platform: config.platform,
          platformProductId: product.platformProductId,
          title: product.title,
          price: product.price,
          currency: product.currency,
          status: product.status,
          traceId: options.traceId,
          businessType: options.businessType,
          syncedAt: product.syncedAt,
        });
        savedProducts.push({ ...product, internalId: productId });
      } catch (error: any) {
        logger.error('[PlatformSyncWorker] Failed to save product', {
          platformProductId: product.platformProductId,
          error: error.message,
        });
        // 继续处理其他商品
      }
    }

    return savedProducts;
  }

  /**
   * 同步订单数据
   */
  private static async syncOrders(
    config: PlatformApiConfig,
    options: SyncOptions
  ): Promise<any[]> {
    const orders = await PlatformApiService.syncOrders(config, options);

    // 保存到数据库
    const savedOrders = [];
    for (const order of orders) {
      try {
        const orderId = await OrderService.createOrder({
          tenantId: options.tenantId,
          shopId: options.shopId,
          platform: config.platform,
          platformOrderId: order.platformOrderId,
          status: order.status,
          totalAmount: order.totalAmount,
          currency: order.currency,
          items: order.items,
          traceId: options.traceId,
          taskId: options.taskId,
          businessType: options.businessType,
          syncedAt: order.syncedAt,
        });
        savedOrders.push({ ...order, internalId: orderId });
      } catch (error: any) {
        logger.error('[PlatformSyncWorker] Failed to save order', {
          platformOrderId: order.platformOrderId,
          error: error.message,
        });
        // 继续处理其他订单
      }
    }

    return savedOrders;
  }

  /**
   * 同步库存数据
   */
  private static async syncInventory(
    config: PlatformApiConfig,
    options: SyncOptions
  ): Promise<any[]> {
    // 先同步商品获取最新库存
    const products = await PlatformApiService.syncProducts(config, options);

    // 更新库存
    const updatedInventory = [];
    for (const product of products) {
      try {
        // TODO: 调用库存服务更新库存
        // await InventoryService.updateStock(...);
        updatedInventory.push({
          platformProductId: product.platformProductId,
          stock: product.stock,
          updatedAt: new Date(),
        });
      } catch (error: any) {
        logger.error('[PlatformSyncWorker] Failed to update inventory', {
          platformProductId: product.platformProductId,
          error: error.message,
        });
      }
    }

    return updatedInventory;
  }

  /**
   * 提交同步任务
   */
  static async submitSyncTask(
    syncType: 'PRODUCT' | 'ORDER' | 'INVENTORY',
    platformConfig: PlatformApiConfig,
    syncOptions: SyncOptions
  ): Promise<string> {
    const job = await WorkerHub.addJob(this.QUEUE_NAME, {
      syncType,
      platformConfig,
      syncOptions,
      retryCount: 0,
    }, {
      attempts: this.MAX_RETRIES,
      backoff: {
        type: 'exponential',
        delay: 5000, // 5秒初始延迟
      },
    });

    logger.info(`[PlatformSyncWorker] Sync task submitted`, {
      jobId: job.id,
      syncType,
      platform: platformConfig.platform,
    });

    return job.id as string;
  }
}
