import { Queue, Worker, Job } from 'bullmq';
import { logger } from '../utils/logger';

// Redis 连接选项
const redisConnection = {
  host: process.env.REDIS_HOST || 'localhost',
  port: Number(process.env.REDIS_PORT) || 6379,
};

/**
 * [CORE_QUEUE_01] BullMQ 服务
 * @description 处理异步任务队列，支持订单事件、支付通知等
 */
export class BullMQService {
  private static queues: Record<string, Queue> = {};

  /**
   * 获取或创建队列
   */
  private static getQueue(name: string): Queue {
    if (!this.queues[name]) {
      this.queues[name] = new Queue(name, {
        connection: redisConnection,
      });
    }
    return this.queues[name];
  }

  /**
   * 添加任务到队列
   */
  static async addJob(queueName: string, data: any, options?: any): Promise<Job> {
    try {
      const queue = this.getQueue(queueName);
      const job = await queue.add(queueName, data, options);
      logger.info(`[BullMQService] Added job to ${queueName}: ${job.id}`);
      return job;
    } catch (error: any) {
      logger.error(`[BullMQService] Failed to add job: ${error.message}`);
      throw error;
    }
  }

  /**
   * 处理队列任务
   */
  static async processQueue(queueName: string, handler: (job: Job) => Promise<void>) {
    try {
      const worker = new Worker(queueName, handler, {
        connection: redisConnection,
      });

      worker.on('completed', (job) => {
        logger.info(`[BullMQService] Job completed: ${job.id}`);
      });

      worker.on('failed', (job, error) => {
        logger.error(`[BullMQService] Job failed: ${job?.id}, error: ${error.message}`);
      });

      logger.info(`[BullMQService] Started worker for ${queueName}`);
    } catch (error: any) {
      logger.error(`[BullMQService] Failed to start worker: ${error.message}`);
      throw error;
    }
  }

  /**
   * 初始化队列处理器
   */
  static async initQueueProcessors() {
    // 订单相关队列处理器
    await this.processQueue('order.created', async (job) => {
      try {
        const { orderId, tenantId } = job.data;
        logger.info(`[OrderQueue] Processing order created: ${orderId}`);
        // 这里可以添加订单创建后的处理逻辑
        // 例如：发送通知、更新统计数据等
      } catch (error) {
        logger.error(`[OrderQueue] Failed to process order.created: ${(error as any).message}`);
      }
    });

    await this.processQueue('order.updated', async (job) => {
      try {
        const { orderId, tenantId, updates } = job.data;
        logger.info(`[OrderQueue] Processing order updated: ${orderId}`);
        // 这里可以添加订单更新后的处理逻辑
      } catch (error) {
        logger.error(`[OrderQueue] Failed to process order.updated: ${(error as any).message}`);
      }
    });

    await this.processQueue('order.deleted', async (job) => {
      try {
        const { orderId, tenantId } = job.data;
        logger.info(`[OrderQueue] Processing order deleted: ${orderId}`);
        // 这里可以添加订单删除后的处理逻辑
      } catch (error) {
        logger.error(`[OrderQueue] Failed to process order.deleted: ${(error as any).message}`);
      }
    });

    await this.processQueue('order.status.changed', async (job) => {
      try {
        const { orderId, tenantId, oldStatus, newStatus, reason } = job.data;
        logger.info(`[OrderQueue] Processing order status change: ${orderId} from ${oldStatus} to ${newStatus}`);
        // 这里可以添加订单状态变更后的处理逻辑
        // 例如：发送状态变更通知、触发相关业务流程等
      } catch (error) {
        logger.error(`[OrderQueue] Failed to process order.status.changed: ${(error as any).message}`);
      }
    });

    await this.processQueue('order.payment', async (job) => {
      try {
        const { orderId, tenantId, paymentInfo } = job.data;
        logger.info(`[OrderQueue] Processing order payment: ${orderId}`);
        // 这里可以添加支付处理逻辑
      } catch (error) {
        logger.error(`[OrderQueue] Failed to process order.payment: ${(error as any).message}`);
      }
    });

    await this.processQueue('order.shipping', async (job) => {
      try {
        const { orderId, tenantId, shippingInfo } = job.data;
        logger.info(`[OrderQueue] Processing order shipping: ${orderId}`);
        // 这里可以添加发货处理逻辑
      } catch (error) {
        logger.error(`[OrderQueue] Failed to process order.shipping: ${(error as any).message}`);
      }
    });

    await this.processQueue('order.batch.updated', async (job) => {
      try {
        const { orderIds, tenantId, updates } = job.data;
        logger.info(`[OrderQueue] Processing batch update for ${orderIds.length} orders`);
        // 这里可以添加批量更新后的处理逻辑
      } catch (error) {
        logger.error(`[OrderQueue] Failed to process order.batch.updated: ${(error as any).message}`);
      }
    });

    // 支付相关事件
    await this.processQueue('payment.created', async (job) => {
      try {
        const { paymentId, tenantId, orderId, amount, paymentMethod } = job.data;
        logger.info(`[PaymentQueue] Processing payment created: ${paymentId}, order: ${orderId}`);
        // 这里可以添加支付创建后的处理逻辑
      } catch (error) {
        logger.error(`[PaymentQueue] Failed to process payment.created: ${(error as any).message}`);
      }
    });

    await this.processQueue('payment.callback', async (job) => {
      try {
        const { paymentId, orderId, status, transactionId, amount, currency } = job.data;
        logger.info(`[PaymentQueue] Processing payment callback: ${paymentId}, status: ${status}`);
        // 这里可以添加支付回调后的处理逻辑
      } catch (error) {
        logger.error(`[PaymentQueue] Failed to process payment.callback: ${(error as any).message}`);
      }
    });

    await this.processQueue('payment.success', async (job) => {
      try {
        const { paymentId, orderId, amount, currency } = job.data;
        logger.info(`[PaymentQueue] Processing payment success: ${paymentId}, order: ${orderId}`);
        // 这里可以添加支付成功后的处理逻辑
      } catch (error) {
        logger.error(`[PaymentQueue] Failed to process payment.success: ${(error as any).message}`);
      }
    });

    await this.processQueue('payment.failed', async (job) => {
      try {
        const { paymentId, orderId, amount, currency } = job.data;
        logger.info(`[PaymentQueue] Processing payment failed: ${paymentId}, order: ${orderId}`);
        // 这里可以添加支付失败后的处理逻辑
      } catch (error) {
        logger.error(`[PaymentQueue] Failed to process payment.failed: ${(error as any).message}`);
      }
    });

    // 退款相关事件
    await this.processQueue('refund.created', async (job) => {
      try {
        const { refundId, tenantId, paymentId, orderId, amount, reason } = job.data;
        logger.info(`[RefundQueue] Processing refund created: ${refundId}, payment: ${paymentId}`);
        // 这里可以添加退款创建后的处理逻辑
      } catch (error) {
        logger.error(`[RefundQueue] Failed to process refund.created: ${(error as any).message}`);
      }
    });

    await this.processQueue('refund.success', async (job) => {
      try {
        const { refundId, tenantId, paymentId, orderId, amount } = job.data;
        logger.info(`[RefundQueue] Processing refund success: ${refundId}, payment: ${paymentId}`);
        // 这里可以添加退款成功后的处理逻辑
      } catch (error) {
        logger.error(`[RefundQueue] Failed to process refund.success: ${(error as any).message}`);
      }
    });

    // 事件总线相关事件
    await this.processQueue('event.published', async (job) => {
      try {
        const { event, destinations } = job.data;
        logger.info(`[EventBusQueue] Processing published event: ${event.type} (${event.id})`);
        logger.info(`[EventBusQueue] Event routed to: ${destinations.join(', ')}`);
        // 这里可以添加事件发布后的处理逻辑
        // 例如：通知外部服务、更新事件状态等
      } catch (error) {
        logger.error(`[EventBusQueue] Failed to process event.published: ${(error as any).message}`);
      }
    });
  }

  /**
   * 获取队列大小
   */
  static async getQueueSize(queueName: string): Promise<number> {
    try {
      const queue = this.getQueue(queueName);
      const size = await queue.count();
      return size;
    } catch (error: any) {
      logger.error(`[BullMQService] Failed to get queue size: ${error.message}`);
      return 0;
    }
  }

  /**
   * 关闭所有队列连接
   */
  static async close() {
    for (const queue of Object.values(this.queues)) {
      await queue.close();
    }
    logger.info('[BullMQService] All queues closed');
  }
}