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

const REDIS_HOST = process.env.REDIS_HOST || '127.0.0.1';
const REDIS_PORT = Number(process.env.REDIS_PORT) || 6379;

let connection: IORedis | null = null;
let redisConnected = false;

// 尝试连接Redis
const connectRedis = () => {
  try {
    connection = new IORedis({
      host: REDIS_HOST,
      port: REDIS_PORT,
      maxRetriesPerRequest: null,
      retryStrategy: (times) => {
        // 指数退避重试
        return Math.min(times * 100, 3000);
      },
    });

    connection.on('connect', () => {
      logger.info('[WorkerHub] Redis connected');
      redisConnected = true;
    });

    connection.on('error', (err) => {
      logger.warn(`[WorkerHub] Redis connection error: ${err.message}`);
      redisConnected = false;
    });

    connection.on('end', () => {
      logger.info('[WorkerHub] Redis connection ended');
      redisConnected = false;
    });
  } catch (error) {
    logger.error(`[WorkerHub] Failed to create Redis connection: ${(error as any).message}`);
  }
};

// 初始化Redis连接
connectRedis();

/**
 * [CORE_WORK_01] 容器化采集调度中心 (Worker Hub)
 * @description 统一管理 BullMQ 队列与 Worker，支持异步采集、发布与同步任务
 */
export class WorkerHub {
  private static queues: Record<string, Queue> = {};
  private static workers: Record<string, Worker> = {};

  /**
   * 检查Redis连接状态
   */
  private static isRedisConnected(): boolean {
    return redisConnected && connection !== null;
  }

  /**
   * 初始化队列
   */
  static getQueue(name: string): Queue | null {
    if (!this.isRedisConnected()) {
      logger.warn(`[WorkerHub] Redis not connected, queue ${name} not initialized`);
      return null;
    }

    if (!this.queues[name] && connection) {
      try {
        this.queues[name] = new Queue(name, { connection: connection as any });
        logger.info(`[WorkerHub] Queue initialized: ${name}`);
      } catch (error) {
        logger.error(`[WorkerHub] Failed to initialize queue ${name}: ${(error as any).message}`);
        return null;
      }
    }
    return this.queues[name] || null;
  }

  /**
   * 注册 Worker
   */
  static registerWorker(name: string, processor: (job: Job) => Promise<any>, concurrency: number = 5) {
    if (!this.isRedisConnected()) {
      logger.warn(`[WorkerHub] Redis not connected, worker ${name} not registered`);
      return;
    }

    if (this.workers[name]) return;

    if (connection) {
      try {
        const worker = new Worker(name, processor, { 
          connection: connection as any,
          concurrency,
          removeOnComplete: { count: 100 },
          removeOnFail: { count: 500 }
        });

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

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

        this.workers[name] = worker;
        logger.info(`[WorkerHub] Worker registered: ${name} (concurrency: ${concurrency})`);
      } catch (error) {
        logger.error(`[WorkerHub] Failed to register worker ${name}: ${(error as any).message}`);
      }
    }
  }

  /**
   * 关闭所有连接
   */
  static async shutdown() {
    try {
      for (const worker of Object.values(this.workers)) {
        await worker.close();
      }
      for (const queue of Object.values(this.queues)) {
        await queue.close();
      }
      if (connection) {
        await connection.quit();
      }
    } catch (error) {
      logger.warn(`[WorkerHub] Error during shutdown: ${(error as any).message}`);
    }
  }
}
