import type { RequestHandler } from './$types';
import { getDb } from '$lib/server/db';
import { REACTIONS_ENABLED, REACTIONS_TTL_DAYS, REACTIONS_SCOPE, GROUP_GATING_MODE } from '$lib/server/env';

export const POST: RequestHandler = async (event) => {
  const userId = event.locals.userId ?? null;
  if (!userId) {
    return new Response('Unauthorized', { status: 401 });
  }

  const idStr = event.params.id || '';
  const taskId = parseInt(idStr, 10);
  if (!Number.isFinite(taskId) || taskId <= 0) {
    return new Response('Bad Request', { status: 400 });
  }

  const db = await getDb();

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

  if (!task) {
    return new Response(JSON.stringify({ status: 'not_found' }), {
      status: 404,
      headers: { 'content-type': 'application/json; charset=utf-8', 'cache-control': 'no-store' }
    });
  }

  // Gating:
  // - Si tiene group_id: grupo allowed y miembro activo
  // - Si NO tiene group_id: debe estar asignada al usuario
  const groupId: string | null = task.group_id ? String(task.group_id) : null;
  if (groupId) {
    const allowed = db
      .prepare(`SELECT 1 FROM allowed_groups WHERE group_id = ? AND status = 'allowed' LIMIT 1`)
      .get(groupId);
    const active = db
      .prepare(`SELECT 1 FROM group_members WHERE group_id = ? AND user_id = ? AND is_active = 1 LIMIT 1`)
      .get(groupId, userId);
    if (!allowed || !active) {
      return new Response('Forbidden', { status: 403 });
    }
  } else {
    const isAssigned = db
      .prepare(`SELECT 1 FROM task_assignments WHERE task_id = ? AND user_id = ? LIMIT 1`)
      .get(taskId, userId);
    if (!isAssigned) {
      return new Response('Forbidden', { status: 403 });
    }
  }

  if (Number(task.completed) !== 0 || task.completed_at) {
    const body = {
      status: 'already',
      task: {
        id: Number(task.id),
        description: String(task.description || ''),
        due_date: task.due_date ? String(task.due_date) : null,
        display_code: task.display_code != null ? Number(task.display_code) : null,
        completed: 1,
        completed_at: task.completed_at ? String(task.completed_at) : null
      }
    };
    return new Response(JSON.stringify(body), {
      status: 200,
      headers: { 'content-type': 'application/json; charset=utf-8', 'cache-control': 'no-store' }
    });
  }

  // Transacción: auto-asignar si no hay responsables y completar
  const tx = db.transaction(() => {
    const cntRow = db
      .prepare(`SELECT COUNT(*) AS cnt FROM task_assignments WHERE task_id = ?`)
      .get(taskId) as any;
    const cnt = Number(cntRow?.cnt || 0);
    if (cnt === 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';

  // Encolar reacción ✅ desde la web si procede (idéntico formato al bot)
  try {
    if (statusStr === 'updated' && REACTIONS_ENABLED) {
      // Buscar origen con columnas opcionales (participant/from_me) si existen
      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 && origin.chat_id && origin.message_id) {
        const chatId = String(origin.chat_id);

        // Scope: por defecto solo reaccionar en grupos
        if (REACTIONS_SCOPE === 'all' || chatId.endsWith('@g.us')) {
          // TTL (por defecto 14 días)
          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);
          const withinTtl = Number.isFinite(createdMs) ? (Date.now() - createdMs <= ttlMs) : false;

          // Gating 'enforce' (solo aplica a grupos)
          let allowed = true;
          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;
            allowed = !!row;
          }

          if (withinTtl && allowed) {
            // Idempotencia 24h por metadata canónica exacta
            const nowIso = new Date().toISOString().replace('T', ' ').replace('Z', '');
            const cutoff = new Date(Date.now() - 24 * 60 * 60 * 1000).toISOString().replace('T', ' ').replace('Z', '');

            const meta: any = { kind: 'reaction', emoji: '✅', chatId, messageId: String(origin.message_id) };
            if (origin && (origin.from_me === 1 || origin.from_me === true)) meta.fromMe = true;
            if (origin && 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 {}

  const body = {
    status: statusStr,
    task: {
      id: Number(updated.id),
      description: String(updated.description || ''),
      due_date: updated.due_date ? String(updated.due_date) : null,
      display_code: updated.display_code != null ? Number(updated.display_code) : null,
      completed: Number(updated.completed || 0),
      completed_at: updated.completed_at ? String(updated.completed_at) : null
    }
  };

  return new Response(JSON.stringify(body), {
    status: 200,
    headers: { 'content-type': 'application/json; charset=utf-8', 'cache-control': 'no-store' }
  });
};
