import { describe, it, expect, beforeAll, beforeEach } from 'bun:test';
import { Database } from 'bun:sqlite';
import { initializeDatabase, ensureUserExists } from '../../../src/db';
import { TaskService } from '../../../src/tasks/service';
import { setDb } from '../../../src/db/locator';

describe('TaskService - claim/unassign', () => {
  let memdb: Database;

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

  beforeEach(() => {
    memdb.exec(`
      DELETE FROM task_assignments;
      DELETE FROM tasks;
      DELETE FROM users;
    `);
  });

  function createTask(description: string, createdBy: string, due?: string | null, assignees: string[] = []): number {
    const creator = ensureUserExists(createdBy, memdb)!;
    const taskId = TaskService.createTask(
      {
        description,
        due_date: due ?? null,
        group_id: null,
        created_by: creator,
      },
      assignees.map(uid => ({ user_id: ensureUserExists(uid, memdb)!, assigned_by: creator }))
    );
    return taskId;
  }

  it('claim: happy path then idempotent', () => {
    const taskId = createTask('Probar claim', '111', '2025-09-12');
    const res1 = TaskService.claimTask(taskId, '222');
    expect(res1.status).toBe('claimed');
    expect(res1.task?.id).toBe(taskId);

    const res2 = TaskService.claimTask(taskId, '222');
    expect(res2.status).toBe('already');
    expect(res2.task?.id).toBe(taskId);
  });

  it('claim: not_found', () => {
    const res = TaskService.claimTask(999999, '111');
    expect(res.status).toBe('not_found');
  });

  it('claim: completed', () => {
    const taskId = createTask('Tarea ya completada', '111', '2025-10-10', ['111']);
    // marcar como completada (user 111 is assigned, so allowed)
    const comp = TaskService.completeTask(taskId, '111');
    expect(comp.status).toBe('updated');

    const res = TaskService.claimTask(taskId, '222');
    expect(res.status).toBe('completed');
    expect(res.task?.id).toBe(taskId);
  });

  it('unassign: happy path con múltiples asignados; luego not_assigned; now_unassigned=false', () => {
    const taskId = createTask('Soltar luego de asignar', '111', '2025-09-20', ['222', '333']);
    const res1 = TaskService.unassignTask(taskId, '222');
    expect(res1.status).toBe('unassigned');
    expect(res1.task?.id).toBe(taskId);
    expect(res1.now_unassigned).toBe(false);

    const res2 = TaskService.unassignTask(taskId, '222');
    expect(res2.status).toBe('not_assigned');
    expect(res2.now_unassigned).toBe(false);
  });

  it('unassign: personal + único asignado → forbidden_personal', () => {
    const taskId = createTask('Personal única asignación', '111', '2025-09-21', ['222']);
    const res = TaskService.unassignTask(taskId, '222');
    expect(res.status).toBe('forbidden_personal');
  });

  it('unassign: not_found', () => {
    const res = TaskService.unassignTask(424242, '111');
    expect(res.status).toBe('not_found');
  });

  it('unassign: completed', () => {
    const taskId = createTask('Unassign bloqueada por completada', '111', null, ['111', '222']);
    // user 111 is assigned, so can complete
    const comp = TaskService.completeTask(taskId, '111');
    expect(comp.status).toBe('updated');

    const res = TaskService.unassignTask(taskId, '222');
    expect(res.status).toBe('completed');
    expect(res.task?.id).toBe(taskId);
  });
});
