import { describe, it, beforeEach, expect } from 'bun:test';
import { Database } from 'bun:sqlite';
import { initializeDatabase } from '../../../src/db';
import { CommandService } from '../../../src/services/command';
import { setDb } from '../../../src/db/locator';

describe('CommandService - alarma recordatorios', () => {
  let memdb: Database;
  const SENDER = '34600123456';

  beforeEach(() => {
    process.env.NODE_ENV = 'test';
    process.env.TZ = 'Europe/Madrid';

    memdb = new Database(':memory:');
    initializeDatabase(memdb);

    // Inyectar DB
    setDb(memdb);

    // Limpiar tablas
    memdb.exec(`DELETE FROM response_queue;`);
    memdb.exec(`DELETE FROM user_preferences;`);
    memdb.exec(`DELETE FROM users;`);
  });

  async function runCmd(msg: string) {
    return await CommandService.handle({
      sender: SENDER,
      groupId: '123@g.us',
      message: msg,
      mentions: []
    });
  }

  function getPref(): { freq: string; time: string | null } | null {
    const row = memdb.prepare(`SELECT reminder_freq AS freq, reminder_time AS time FROM user_preferences WHERE user_id = ?`).get(SENDER) as any;
    if (!row) return null;
    return { freq: String(row.freq), time: row.time ? String(row.time) : null };
  }

  it('alarma daily guarda preferencia y responde confirmación', async () => {
    const res = await runCmd('t alarma daily');
    expect(res).toHaveLength(1);
    expect(res[0].recipient).toBe(SENDER);
    expect(res[0].message).toContain('✅ Recordatorios: diario');

    const pref = getPref();
    expect(pref).not.toBeNull();
    expect(pref!.freq).toBe('daily');
    expect(pref!.time).toBe('08:30'); // default
  });

  it('alarma weekly guarda preferencia y responde confirmación', async () => {
    const res = await runCmd('t alarma weekly');
    expect(res).toHaveLength(1);
    expect(res[0].message).toContain('semanal (lunes 08:30)');

    const pref = getPref();
    expect(pref).not.toBeNull();
    expect(pref!.freq).toBe('weekly');
  });

  it('alarma off guarda preferencia y responde confirmación', async () => {
    const res = await runCmd('t alarma off');
    expect(res).toHaveLength(1);
    expect(res[0].message).toContain('apagado');

    const pref = getPref();
    expect(pref).not.toBeNull();
    expect(pref!.freq).toBe('off');
  });

  it('alarma con opción inválida devuelve uso correcto y no escribe en DB', async () => {
    const res = await runCmd('t alarma foo');
    expect(res).toHaveLength(1);
    expect(res[0].message).toContain('Uso: `t alarma diario|l-v|semanal|off [HH:MM]`');

    const pref = getPref();
    expect(pref).toBeNull();
  });

  it('upsert idempotente: cambiar de daily a off actualiza la fila existente', async () => {
    await runCmd('t alarma daily');
    let pref = getPref();
    expect(pref!.freq).toBe('daily');

    await runCmd('t alarma off');
    pref = getPref();
    expect(pref!.freq).toBe('off');
  });

  it('alarma l-v con hora guarda weekdays y respeta hora', async () => {
    const res = await runCmd('t alarma l-v 8:00');
    expect(res).toHaveLength(1);
    expect(res[0].recipient).toBe(SENDER);
    expect(res[0].message).toContain('laborables');

    const pref = getPref();
    expect(pref).not.toBeNull();
    expect(pref!.freq).toBe('weekdays');
    expect(pref!.time).toBe('08:00');
  });
});
