import cron from 'node-cron';
import { EventEmitter } from 'events';
import { cronDb } from '../../database/db.js';

const MAX_PER_USER = 10;

class CronScheduler extends EventEmitter {
  #jobs = new Map(); // cronId → node-cron task

  // 服务启动时从 DB 恢复所有持久化任务（跳过已暂停的）
  loadFromDb() {
    const tasks = cronDb.getAll();
    let loaded = 0;
    for (const task of tasks) {
      if (task.isPaused) continue;
      this.#scheduleJob(task);
      loaded++;
    }
    if (tasks.length > 0) {
      console.log(`[CronScheduler] Loaded ${loaded}/${tasks.length} cron task(s) from DB (${tasks.length - loaded} paused)`);
    }
  }

  create({ id, cronExpr, prompt, recurring, userUuid, sessionId, projectPath,
           sessionMode, channel, feishuOpenId, chatId, webhookUrl }) {
    if (!cron.validate(cronExpr)) {
      throw new Error(`无效的 cron 表达式: ${cronExpr}`);
    }
    const existing = cronDb.listByUser(userUuid);
    if (existing.length >= MAX_PER_USER) {
      throw new Error(`每用户最多 ${MAX_PER_USER} 个定时任务，当前已有 ${existing.length} 个`);
    }

    const task = {
      id, cronExpr, prompt, recurring,
      userUuid, sessionId, projectPath,
      sessionMode: sessionMode || 'new_session',
      channel: channel ?? '',
      feishuOpenId: feishuOpenId || null,
      chatId: chatId || null,
      webhookUrl: webhookUrl || null,
      createdAt: Date.now(),
      lastFiredAt: null,
      isPaused: false,
    };

    cronDb.insert(task);
    this.#scheduleJob(task);
    console.log(`[CronScheduler] Created task ${id} (${cronExpr}) for user ${userUuid}, sessionMode=${sessionMode || 'new_session'}, channel=${channel || 'none'}`);
    return task;
  }

  delete(id, userUuid) {
    const job = this.#jobs.get(id);
    if (job) {
      job.stop();
      this.#jobs.delete(id);
    }
    const ok = cronDb.delete(id, userUuid);
    if (ok) {
      console.log(`[CronScheduler] Deleted task ${id}`);
    } else {
      // 任务不存在或 user_uuid 不匹配
      const allTasks = cronDb.getAll();
      const task = allTasks.find(t => t.id === id);
      if (task) {
        console.warn(`[CronScheduler] Delete denied: task ${id} belongs to user ${task.userUuid}, caller is ${userUuid}`);
      } else {
        console.warn(`[CronScheduler] Delete failed: task ${id} not found in DB`);
      }
    }
    return ok;
  }

  pause(id, userUuid) {
    const ok = cronDb.setPaused(id, userUuid, true);
    if (ok) {
      const job = this.#jobs.get(id);
      if (job) {
        job.stop();
        this.#jobs.delete(id);
      }
      console.log(`[CronScheduler] Paused task ${id}`);
    }
    return ok;
  }

  resume(id, userUuid) {
    const ok = cronDb.setPaused(id, userUuid, false);
    if (ok) {
      const allTasks = cronDb.getAll();
      const task = allTasks.find(t => t.id === id);
      if (task) {
        this.#scheduleJob(task);
        console.log(`[CronScheduler] Resumed task ${id}`);
      }
    }
    return ok;
  }

  update(id, userUuid, patch) {
    // 停止旧 job
    const job = this.#jobs.get(id);
    if (job) {
      job.stop();
      this.#jobs.delete(id);
    }
    const ok = cronDb.update(id, userUuid, patch);
    if (!ok) return null;
    // 重新读取并调度（若未暂停）
    const allTasks = cronDb.getAll();
    const task = allTasks.find(t => t.id === id);
    if (task && !task.isPaused) {
      this.#scheduleJob(task);
      console.log(`[CronScheduler] Updated task ${id} (${task.cronExpr})`);
    }
    return task || null;
  }

  list(userUuid) {
    return cronDb.listByUser(userUuid);
  }

  #scheduleJob(task) {
    if (this.#jobs.has(task.id)) {
      // 避免重复注册（loadFromDb 时防御）
      const old = this.#jobs.get(task.id);
      old.stop();
    }
    const job = cron.schedule(task.cronExpr, () => this.#onFire(task.id));
    this.#jobs.set(task.id, job);
  }

  #onFire(id) {
    // 从 DB 重新读取，以获取最新的 lastFiredAt 等字段
    const allTasks = cronDb.getAll();
    const task = allTasks.find(t => t.id === id);
    if (!task) {
      // 任务已被删除，停止 job
      const job = this.#jobs.get(id);
      if (job) { job.stop(); this.#jobs.delete(id); }
      return;
    }

    // 已暂停则跳过（防御：理论上已从 #jobs 移除，不会触发）
    if (task.isPaused) return;

    const now = Date.now();
    cronDb.updateLastFired(id, now);
    this.emit('cron-fire', { ...task, firedAt: now });
    console.log(`[CronScheduler] Task ${id} fired (sessionMode=${task.sessionMode || 'new_session'}, channel=${task.channel || 'none'})`);

    if (!task.recurring) {
      // 单次任务：触发后删除
      this.delete(id, task.userUuid);
    }
  }
}

export const cronScheduler = new CronScheduler();
