import { describe, it, beforeEach, afterEach, expect } from 'bun:test';
import Database from 'bun:sqlite';
import { initializeDatabase } from '../../../src/db';
import { TaskService } from '../../../src/tasks/service';
import { AllowedGroups } from '../../../src/services/allowed-groups';
import { setDb, resetDb } from '../../../src/db/locator';
import { toIsoSql } from '../../helpers/dates';

function seedGroup(db: Database, groupId: string) {
  // Sembrado robusto: cubrir columnas NOT NULL sin valor por defecto
  const cols = db.query(`PRAGMA table_info(groups)`).all() as any[];
  const values: Record<string, any> = {};
  const nowIso = toIsoSql(new Date());

  for (const c of cols) {
    const name = String(c.name);
    const type = String(c.type || '').toUpperCase();
    const notnull = Number(c.notnull || 0) === 1;
    const hasDefault = c.dflt_value != null;

    if (name === 'id') {
      values[name] = groupId;
      continue;
    }

    // Preconfigurar algunos alias comunes
    if (name === 'name' || name === 'title' || name === 'subject') {
      values[name] = 'Test Group';
      continue;
    }
    if (name === 'created_by') {
      values[name] = 'tester';
      continue;
    }
    if (name.endsWith('_at')) {
      values[name] = nowIso;
      continue;
    }
    if (name === 'is_active' || name === 'active') {
      values[name] = 1;
      continue;
    }

    // Para columnas NOT NULL sin valor por defecto, asignar valores genéricos
    if (notnull && !hasDefault) {
      if (type.includes('INT')) values[name] = 1;
      else if (type.includes('REAL')) values[name] = 0;
      else values[name] = 'N/A';
    }
  }

  // Asegurar que id esté siempre
  if (!('id' in values)) values['id'] = groupId;

  const colsList = Object.keys(values);
  const placeholders = colsList.map(() => '?').join(', ');
  const sql = `INSERT OR REPLACE INTO groups (${colsList.join(', ')}) VALUES (${placeholders})`;
  db.prepare(sql).run(...colsList.map(k => values[k]));
}

describe('TaskService - gating en creación con group_id (enforce)', () => {
  const envBackup = process.env;
  let memdb: Database;

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

  afterEach(() => {
    process.env = envBackup;
    resetDb();
    memdb.close();
  });

  it('fuerza group_id=null cuando el grupo no está allowed', () => {
    const gid = 'na@g.us';
    seedGroup(memdb, gid);
    AllowedGroups.setStatus(gid, 'blocked');

    const taskId = TaskService.createTask(
      {
        description: 'Probar gating',
        due_date: null,
        group_id: gid,
        created_by: '34600123456',
      },
      [{ user_id: '34600123456', assigned_by: '34600123456' }]
    );

    const row = memdb
      .query(`SELECT group_id FROM tasks WHERE id = ?`)
      .get(taskId) as any;
    expect(row?.group_id).toBeNull();
  });

  it('conserva group_id cuando el grupo está allowed', () => {
    const gid = 'ok@g.us';
    seedGroup(memdb, gid);
    AllowedGroups.setStatus(gid, 'allowed');

    const taskId = TaskService.createTask(
      {
        description: 'Tarea en grupo allowed',
        due_date: null,
        group_id: gid,
        created_by: '34600123456',
      },
      [{ user_id: '34600123456', assigned_by: '34600123456' }]
    );

    const row = memdb
      .query(`SELECT group_id FROM tasks WHERE id = ?`)
      .get(taskId) as any;
    expect(String(row?.group_id)).toBe(gid);
  });
});
