const dayjs = require("dayjs");

class Scheduler {
  constructor(store, telegram) {
    this.store = store;
    this.telegram = telegram;
    this.running = false;
    this.timer = null;
  }

  isRunning() {
    return this.running;
  }

  start(settings) {
    if (this.running) return;
    this.running = true;
    this.settings = settings;
    this._scheduleNext();
  }

  stop() {
    this.running = false;
    if (this.timer) clearTimeout(this.timer);
    this.timer = null;
  }

  _scheduleNext() {
    if (!this.running) return;
    const minMs = Number(this.settings.minIntervalMinutes || 5) * 60 * 1000;
    const maxMs = Number(this.settings.maxIntervalMinutes || 10) * 60 * 1000;
    const jitter = Math.max(minMs, Math.min(maxMs, minMs + Math.random() * (maxMs - minMs)));
    this.timer = setTimeout(() => this._runBatch(), jitter);
  }

  async _runBatch() {
    const startedAt = dayjs().toISOString();
    const errors = [];
    const successIds = [];
    let invitedCount = 0;

    try {
      const dailyLimit = Number(this.settings.dailyLimit || 100);
      const alreadyInvited = this.store.countInvitesToday();
      if (alreadyInvited >= dailyLimit) {
        errors.push("Daily limit reached");
      } else {
        const remaining = dailyLimit - alreadyInvited;
        const batchSize = Math.min(20, remaining);
        const pending = this.store.getPendingInvites(0, batchSize);

        const accountIds = new Set(this.store.listAccounts().map((account) => account.user_id).filter(Boolean));
        for (const item of pending) {
          if (accountIds.has(item.user_id)) {
            this.store.markInviteStatus(item.id, "skipped");
            this.store.recordInvite(
              0,
              item.user_id,
              item.username,
              0,
              "",
              item.source_chat,
              "skipped",
              "",
              "account_own",
              "skip"
            );
            continue;
          }
          const result = await this.telegram.inviteUser(this.settings.ourGroup, item.user_id);
          if (result.ok) {
            invitedCount += 1;
            successIds.push(item.user_id);
            this.store.markInviteStatus(item.id, "invited");
            this.store.recordInvite(
              0,
              item.user_id,
              item.username,
              result.accountId,
              result.accountPhone,
              item.source_chat,
              "success",
              "",
              "",
              "invite"
            );
          } else {
            errors.push(`${item.user_id}: ${result.error}`);
            this.store.markInviteStatus(item.id, "failed");
            this.store.recordInvite(
              0,
              item.user_id,
              item.username,
              result.accountId,
              result.accountPhone,
              item.source_chat,
              "failed",
              result.error || "",
              result.error || "",
              "invite"
            );
          }
        }
      }
    } catch (error) {
      errors.push(error.message || String(error));
    }

    const finishedAt = dayjs().toISOString();
    this.store.addLog({
      startedAt,
      finishedAt,
      invitedCount,
      successIds,
      errors
    });

    this._scheduleNext();
  }
}

module.exports = { Scheduler };
