import { describe, it, expect, beforeAll, afterAll, beforeEach } from 'bun:test';
import { Database } from 'bun:sqlite';
import { initializeDatabase } from '../../../src/db';
import { WebhookServer } from '../../../src/server';
import { ResponseQueue } from '../../../src/services/response-queue';
import { AllowedGroups } from '../../../src/services/allowed-groups';
import { GroupSyncService } from '../../../src/services/group-sync';
import { setDb } from '../../../src/db/locator';

function makePayload(event: string, data: any) {
  return {
    event,
    instance: 'test-instance',
    data
  };
}

async function postWebhook(payload: any) {
  const req = new Request('http://localhost/webhook', {
    method: 'POST',
    headers: { 'Content-Type': 'application/json' },
    body: JSON.stringify(payload)
  });
  return await WebhookServer.handleRequest(req);
}

describe('WebhookServer E2E - reacciones por comando', () => {
  let memdb: Database;
  const envBackup = { ...process.env };

  beforeAll(() => {
    memdb = new Database(':memory:');
    initializeDatabase(memdb);
    (WebhookServer as any).dbInstance = memdb;
    setDb(memdb);
  });

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

  beforeEach(() => {
    process.env = {
      ...envBackup,
      NODE_ENV: 'test',
      REACTIONS_ENABLED: 'true',
      REACTIONS_SCOPE: 'groups',
      GROUP_GATING_MODE: 'enforce',
      CHATBOT_PHONE_NUMBER: '999'
    };
    memdb.exec(`
      DELETE FROM response_queue;
      DELETE FROM task_origins;
      DELETE FROM tasks;
      DELETE FROM users;
      DELETE FROM groups;
      DELETE FROM allowed_groups;
    `);
    GroupSyncService.activeGroupsCache?.clear?.();
  });

  it('encola 🤖 en grupo allowed y activo tras t n', async () => {
    const groupId = 'g1@g.us';
    // Sembrar grupo activo y allowed
    memdb.exec(`
      INSERT OR IGNORE INTO groups (id, community_id, name, active, archived, is_community, last_verified)
      VALUES ('${groupId}', 'comm-1', 'G1', 1, 0, 0, strftime('%Y-%m-%d %H:%M:%f','now'))
    `);
    GroupSyncService.activeGroupsCache.set(groupId, 'G1');
    AllowedGroups.setStatus(groupId, 'allowed');

    const payload = makePayload('MESSAGES_UPSERT', {
      key: { remoteJid: groupId, id: 'MSG-OK-1', fromMe: false, participant: '600111222@s.whatsapp.net' },
      message: { conversation: 't n prueba e2e' }
    });

    const res = await postWebhook(payload);
    expect(res.status).toBe(200);

    const row = memdb.prepare(`SELECT metadata FROM response_queue WHERE metadata LIKE '%"kind":"reaction"%' ORDER BY id DESC LIMIT 1`).get() as any;
    expect(row).toBeTruthy();
    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('MSG-OK-1');
  });

  it('no encola reacción en DM cuando REACTIONS_SCOPE=groups', async () => {
    const dmJid = '600111222@s.whatsapp.net';

    const payload = makePayload('MESSAGES_UPSERT', {
      key: { remoteJid: dmJid, id: 'MSG-DM-1', fromMe: false },
      message: { conversation: 't n en DM no reacciona' }
    });

    const res = await postWebhook(payload);
    expect(res.status).toBe(200);

    const cnt = memdb.prepare(`SELECT COUNT(*) AS c FROM response_queue WHERE metadata LIKE '%"kind":"reaction"%'`).get() as any;
    expect(Number(cnt.c)).toBe(0);
  });

  it('encola ⚠️ en grupo allowed y activo para comando inválido (t x sin IDs)', async () => {
    const groupId = 'g2@g.us';
    memdb.exec(`
      INSERT OR IGNORE INTO groups (id, community_id, name, active, archived, is_community, last_verified)
      VALUES ('${groupId}', 'comm-1', 'G2', 1, 0, 0, strftime('%Y-%m-%d %H:%M:%f','now'))
    `);
    GroupSyncService.activeGroupsCache.set(groupId, 'G2');
    AllowedGroups.setStatus(groupId, 'allowed');

    const payload = makePayload('MESSAGES_UPSERT', {
      key: { remoteJid: groupId, id: 'MSG-ERR-1', fromMe: false, participant: '600111222@s.whatsapp.net' },
      message: { conversation: 't x' }
    });

    const res = await postWebhook(payload);
    expect(res.status).toBe(200);

    const row = memdb.prepare(`SELECT metadata FROM response_queue WHERE metadata LIKE '%"kind":"reaction"%' ORDER BY id DESC LIMIT 1`).get() as any;
    expect(row).toBeTruthy();
    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('MSG-ERR-1');
  });
});
