import Database from 'bun:sqlite';
import { initializeDatabase, ensureUserExists } from '../../../src/db';
import { TaskService } from '../../../src/tasks/service';
import { setDb, resetDb } from '../../../src/db/locator';

describe('TaskService - listAllActive', () => {
  let memdb: Database;

  beforeEach(() => {
    process.env.NODE_ENV = 'test';
    process.env.GROUP_GATING_MODE = 'off';
    memdb = new Database(':memory:');
    initializeDatabase(memdb);
    setDb(memdb);
  });

  afterEach(() => {
    try { resetDb(); memdb.close(); } catch {}
  });

  function seedGroup(id: string, name: string = 'Group') {
    memdb.prepare(`
      INSERT INTO groups (id, community_id, name, active, last_verified)
      VALUES (?, 'comm-1', ?, 1, strftime('%Y-%m-%d %H:%M:%f','now'))
    `).run(id, name);
  }

  function createTask(desc: string, due: string | null, groupId: string | null, creator: string) {
    const ensured = ensureUserExists(creator, memdb)!;
    return TaskService.createTask(
      { description: desc, due_date: due, group_id: groupId, created_by: ensured },
      []
    );
  }

  it('devuelve solo tareas activas en orden por due_date (NULL al final)', () => {
    seedGroup('g1@g.us', 'G1');
    seedGroup('g2@g.us', 'G2');

    const c = '34600123456';
    const t1 = createTask('Tarea A', '2025-10-10', 'g1@g.us', c);
    const t2 = createTask('Tarea B', '2025-10-05', 'g2@g.us', c);
    const t3 = createTask('Tarea C', null, 'g1@g.us', c);
    const t4 = createTask('Tarea D', '2025-10-01', 'g2@g.us', c);

    // Completar una de ellas para que no aparezca
    memdb.prepare(`INSERT OR IGNORE INTO task_assignments (task_id, user_id, assigned_by) VALUES (?, ?, ?)`).run(t4, c, c);
    TaskService.completeTask(t4, c);

    const rows = TaskService.listAllActive(10);
    expect(rows.map(r => r.description)).toEqual(['Tarea B', 'Tarea A', 'Tarea C']);
    expect(TaskService.countAllActive()).toBe(3);
  });

  it('respeta el límite indicado', () => {
    seedGroup('g1@g.us', 'G1');
    const c = '34600123456';
    createTask('Tarea 1', '2025-10-02', 'g1@g.us', c);
    createTask('Tarea 2', '2025-10-03', 'g1@g.us', c);
    createTask('Tarea 3', '2025-10-04', 'g1@g.us', c);

    const rows = TaskService.listAllActive(2);
    expect(rows.length).toBe(2);
  });

  it('excluye tareas de grupos archivados o inactivos en listAllActive y countAllActive', () => {
    seedGroup('g1@g.us', 'G1');
    seedGroup('g2@g.us', 'G2');

    const c = '34600123456';
    createTask('G1 A', '2025-11-01', 'g1@g.us', c);
    createTask('G2 A', '2025-11-02', 'g2@g.us', c);

    // Archivar g1 -> solo debe aparecer G2 A
    memdb.prepare(`UPDATE groups SET archived = 1 WHERE id = ?`).run('g1@g.us');
    let rows = TaskService.listAllActive(10);
    expect(rows.map(r => r.description)).toEqual(['G2 A']);
    expect(TaskService.countAllActive()).toBe(1);

    // Reactivar g1 y desactivar g2 -> solo debe aparecer G1 A
    memdb.prepare(`UPDATE groups SET archived = 0 WHERE id = ?`).run('g1@g.us');
    memdb.prepare(`UPDATE groups SET active = 0 WHERE id = ?`).run('g2@g.us');
    rows = TaskService.listAllActive(10);
    expect(rows.map(r => r.description)).toEqual(['G1 A']);
    expect(TaskService.countAllActive()).toBe(1);
  });
});
