import { describe, it, expect, beforeAll, afterAll, beforeEach } from 'bun:test';
import { Database } from 'bun:sqlite';
import { initializeDatabase } from '../../../src/db';
import { TaskService } from '../../../src/tasks/service';
import { ResponseQueue } from '../../../src/services/response-queue';
import { AllowedGroups } from '../../../src/services/allowed-groups';
import { setDb, resetDb } from '../../../src/db/locator';

import { toIsoSql } from '../../helpers/dates';

describe('TaskService - reacción ✅ al completar (Fase 2)', () => {
  let memdb: Database;
  let envBackup: Record<string, string | undefined>;

  beforeAll(() => {
    envBackup = { ...process.env };
    memdb = new Database(':memory:');
    initializeDatabase(memdb);
    setDb(memdb);
  });

  afterAll(() => {
    process.env = envBackup;
    try { resetDb(); memdb.close(); } catch {}
  });

  beforeEach(() => {
    process.env.NODE_ENV = 'test';
    process.env.REACTIONS_ENABLED = 'true';
    process.env.REACTIONS_SCOPE = 'groups';
    process.env.REACTIONS_TTL_DAYS = '14';
    process.env.GROUP_GATING_MODE = 'enforce';

    memdb.exec(`
      DELETE FROM response_queue;
      DELETE FROM task_origins;
      DELETE FROM tasks;
      DELETE FROM users;
      DELETE FROM allowed_groups;
    `);
  });

  it('enqueuea ✅ al completar una tarea con task_origins dentro de TTL y grupo allowed', async () => {
    const groupId = 'grp-1@g.us';
    AllowedGroups.setStatus(groupId, 'allowed');

    const taskId = TaskService.createTask({
      description: 'Prueba ✅',
      due_date: null,
      group_id: groupId,
      created_by: '600111222'
    }, [{ user_id: '600111222', assigned_by: '600111222' }]);

    // Origen reciente (dentro de TTL)
    const msgId = 'MSG-OK-1';
    memdb.prepare(`
      INSERT INTO task_origins (task_id, chat_id, message_id, created_at)
      VALUES (?, ?, ?, ?)
    `).run(taskId, groupId, msgId, toIsoSql(new Date()));

    const res = TaskService.completeTask(taskId, '600111222');
    expect(res.status).toBe('updated');

    const row = memdb.prepare(`SELECT id, recipient, metadata FROM response_queue ORDER BY id DESC LIMIT 1`).get() as any;
    expect(row).toBeTruthy();
    expect(String(row.recipient)).toBe(groupId);

    const meta = JSON.parse(String(row.metadata || '{}'));
    expect(meta.kind).toBe('reaction');
    expect(meta.emoji).toBe('✅');
    expect(meta.chatId).toBe(groupId);
    expect(meta.messageId).toBe(msgId);
  });

  it('no encola ✅ si el origen está fuera de TTL', async () => {
    const groupId = 'grp-2@g.us';
    AllowedGroups.setStatus(groupId, 'allowed');

    // TTL 7 días para forzar expiración
    process.env.REACTIONS_TTL_DAYS = '7';

    const taskId = TaskService.createTask({
      description: 'Fuera TTL',
      due_date: null,
      group_id: groupId,
      created_by: '600111222'
    }, [{ user_id: '600111222', assigned_by: '600111222' }]);

    const msgId = 'MSG-OLD-1';
    const old = new Date(Date.now() - 8 * 24 * 60 * 60 * 1000); // 8 días atrás
    memdb.prepare(`
      INSERT INTO task_origins (task_id, chat_id, message_id, created_at)
      VALUES (?, ?, ?, ?)
    `).run(taskId, groupId, msgId, toIsoSql(old));

    const res = TaskService.completeTask(taskId, '600111222');
    expect(res.status).toBe('updated');

    const cnt = memdb.prepare(`SELECT COUNT(*) AS c FROM response_queue`).get() as any;
    expect(Number(cnt.c)).toBe(0);
  });

  it('idempotencia: completar dos veces encola solo un ✅', async () => {
    const groupId = 'grp-3@g.us';
    AllowedGroups.setStatus(groupId, 'allowed');

    const taskId = TaskService.createTask({
      description: 'Idempotencia ✅',
      due_date: null,
      group_id: groupId,
      created_by: '600111222'
    }, [{ user_id: '600111222', assigned_by: '600111222' }]);

    const msgId = 'MSG-IDEMP-1';
    memdb.prepare(`
      INSERT INTO task_origins (task_id, chat_id, message_id, created_at)
      VALUES (?, ?, ?, ?)
    `).run(taskId, groupId, msgId, toIsoSql(new Date()));

    const r1 = TaskService.completeTask(taskId, '600111222');
    const r2 = TaskService.completeTask(taskId, '600111222');
    expect(r1.status === 'updated' || r1.status === 'already').toBe(true);
    expect(r2.status === 'updated' || r2.status === 'already').toBe(true);

    const rows = memdb.query(`SELECT metadata FROM response_queue`).all() as any[];
    expect(rows.length).toBe(1);
    const meta = JSON.parse(String(rows[0].metadata || '{}'));
    expect(meta.emoji).toBe('✅');
  });

  it('enforce: grupo no allowed → no encola ✅', async () => {
    const groupId = 'grp-4@g.us';
    // Estado por defecto 'pending' (no allowed)

    const taskId = TaskService.createTask({
      description: 'No allowed',
      due_date: null,
      group_id: groupId,
      created_by: '600111222'
    }, [{ user_id: '600111222', assigned_by: '600111222' }]);

    const msgId = 'MSG-NO-ALLOW-1';
    memdb.prepare(`
      INSERT INTO task_origins (task_id, chat_id, message_id, created_at)
      VALUES (?, ?, ?, ?)
    `).run(taskId, groupId, msgId, toIsoSql(new Date()));

    const res = TaskService.completeTask(taskId, '600111222');
    expect(res.status === 'updated' || res.status === 'already').toBe(true);

    const cnt = memdb.prepare(`SELECT COUNT(*) AS c FROM response_queue`).get() as any;
    expect(Number(cnt.c)).toBe(0);
  });
});
