import type { RequestHandler } from './$types';
import { loadTaskAndGating, formatTask, respondTask } from '$lib/server/task-helpers';
import { REACTIONS_ENABLED, REACTIONS_TTL_DAYS, REACTIONS_SCOPE, GROUP_GATING_MODE } from '$lib/server/env';
import { toIsoSqlUTC } from '$lib/server/datetime';

// ---------------------------------------------------------------------------
// Reaction helper
// ---------------------------------------------------------------------------

function tryEnqueueCompletionReaction(db: any, taskId: number): void {
  try {
    // Look up origin (fallback for missing participant/from_me columns)
    let origin: any = null;
    try {
      origin = db.prepare(`SELECT chat_id, message_id, created_at, participant, from_me FROM task_origins WHERE task_id = ?`).get(taskId) as any;
    } catch {
      origin = db.prepare(`SELECT chat_id, message_id, created_at FROM task_origins WHERE task_id = ?`).get(taskId) as any;
    }

    if (!origin?.chat_id || !origin?.message_id) return;
    const chatId = String(origin.chat_id);

    // Scope: por defecto solo reaccionar en grupos
    if (REACTIONS_SCOPE !== 'all' && !chatId.endsWith('@g.us')) return;

    // TTL
    const ttlMs = REACTIONS_TTL_DAYS * 24 * 60 * 60 * 1000;
    const createdRaw = String(origin.created_at || '');
    const createdIso = createdRaw.includes('T') ? createdRaw : (createdRaw.replace(' ', 'T') + 'Z');
    const createdMs = Date.parse(createdIso);
    if (!Number.isFinite(createdMs) || Date.now() - createdMs > ttlMs) return;

    // Gating 'enforce'
    if (GROUP_GATING_MODE === 'enforce' && chatId.endsWith('@g.us')) {
      const row = db.prepare(`SELECT 1 FROM allowed_groups WHERE group_id = ? AND status = 'allowed' LIMIT 1`).get(chatId) as any;
      if (!row) return;
    }

    // Idempotencia 24h por metadata canónica exacta
    const nowIso = toIsoSqlUTC(new Date());
    const cutoff = toIsoSqlUTC(new Date(Date.now() - 24 * 60 * 60 * 1000));

    const meta: any = { kind: 'reaction', emoji: '✅', chatId, messageId: String(origin.message_id) };
    if (origin.from_me === 1 || origin.from_me === true) meta.fromMe = true;
    if (origin.participant) meta.participant = String(origin.participant);
    const metadata = JSON.stringify(meta);

    const exists = db.prepare(`
      SELECT 1
      FROM response_queue
      WHERE metadata = ?
        AND status IN ('queued','processing','sent')
        AND (updated_at > ? OR created_at > ?)
      LIMIT 1
    `).get(metadata, cutoff, cutoff) as any;

    if (!exists) {
      db.prepare(`INSERT INTO response_queue (recipient, message, metadata, next_attempt_at) VALUES (?, ?, ?, ?)`).run(chatId, '', metadata, nowIso);
    }
  } catch {}
}

// ---------------------------------------------------------------------------
// Handler
// ---------------------------------------------------------------------------

export const POST: RequestHandler = async (event) => {
  const ctx = await loadTaskAndGating(event);
  if (ctx instanceof Response) return ctx;
  const { db, task, userId, groupId } = ctx;

  // Idempotencia: ya está completada
  if (Number(task.completed) !== 0 || task.completed_at) {
    return respondTask('already', {
      ...formatTask(task),
      completed: 1,
      completed_at: task.completed_at ? String(task.completed_at) : null
    });
  }

  // Transacción: auto-asignar si no hay responsables y completar
  const taskId = task.id;
  const tx = db.transaction(() => {
    const cntRow = db
      .prepare(`SELECT COUNT(*) AS cnt FROM task_assignments WHERE task_id = ?`)
      .get(taskId) as any;
    if (Number(cntRow?.cnt || 0) === 0) {
      db.prepare(`INSERT OR IGNORE INTO task_assignments (task_id, user_id, assigned_by) VALUES (?, ?, ?)`)
        .run(taskId, userId, userId);
    }
    db.prepare(`
      UPDATE tasks
      SET completed = 1,
          completed_at = strftime('%Y-%m-%d %H:%M:%f', 'now'),
          completed_by = ?
      WHERE id = ?
        AND COALESCE(completed, 0) = 0
        AND completed_at IS NULL
    `).run(userId, taskId);
  });
  tx();

  const updated = db.prepare(`
    SELECT id, description, due_date, display_code, COALESCE(completed, 0) AS completed, completed_at
    FROM tasks
    WHERE id = ?
  `).get(taskId) as any;

  const statusStr = Number(updated.completed || 0) === 1 ? 'updated' : 'already';

  if (statusStr === 'updated' && REACTIONS_ENABLED) {
    tryEnqueueCompletionReaction(db, taskId);
  }

  return respondTask(statusStr, formatTask(updated));
};
