import { describe, it, expect, afterAll } from 'bun:test';
import Database from 'bun:sqlite';
import { startWebServer } from './helpers/server';
import { createTempDb } from './helpers/db';

import { sha256Hex } from '../helpers/crypto';

import { toIsoSql } from '../helpers/dates';

describe('API - /api/integrations/feeds', () => {
  const PORT = 19123;
  const BASE = `http://127.0.0.1:${PORT}`;
  const USER = '34600123456';
  const GROUP = '123@g.us';
  const SID = 'sid-test-123';

  const tmp = createTempDb();
  const db: any = tmp.db as Database;

  // Sembrar datos mínimos
  db.exec(`INSERT OR IGNORE INTO users (id) VALUES ('${USER}')`);
  db.exec(`INSERT OR IGNORE INTO groups (id, community_id, name, active) VALUES ('${GROUP}', 'comm1', 'Group 1', 1)`);
  db.exec(`INSERT OR IGNORE INTO allowed_groups (group_id, status, discovered_at, updated_at) VALUES ('${GROUP}', 'allowed', '${toIsoSql()}', '${toIsoSql()}')`);
  db.exec(`INSERT OR IGNORE INTO group_members (group_id, user_id, is_admin, is_active, first_seen_at, last_seen_at) VALUES ('${GROUP}', '${USER}', 0, 1, '${toIsoSql()}', '${toIsoSql()}')`);

  // Crear sesión web válida (cookie sid)
  const sidHashPromise = sha256Hex(SID);
  const serverPromise = startWebServer({
    port: PORT,
    env: {
      DB_PATH: tmp.path,
      WEB_BASE_URL: BASE
    }
  });

  let server: Awaited<typeof serverPromise> | null = null;

  afterAll(async () => {
    try { await server?.stop(); } catch {}
    try { tmp.cleanup(); } catch {}
  });

  it('GET: autogenera y devuelve URLs para personal, grupo y aggregate; POST rotate rota el de grupo', async () => {
    server = await serverPromise;

    const sidHash = await sidHashPromise;
    // Insertar sesión después de lanzar el server (mismo archivo)
    db.exec(`
      INSERT OR REPLACE INTO web_sessions (id, user_id, session_hash, created_at, last_seen_at, expires_at)
      VALUES ('sess-1', '${USER}', '${sidHash}', '${toIsoSql()}', '${toIsoSql()}', '${toIsoSql(new Date(Date.now() + 2 * 60 * 60 * 1000))}')
    `);

    // GET feeds
    const res = await fetch(`${BASE}/api/integrations/feeds`, {
      headers: { cookie: `sid=${SID}` }
    });
    expect(res.status).toBe(200);
    const body = await res.json();
    // Personal URL presente (recién creada)
    expect(typeof body.personal).toBe('object');
    expect(typeof body.personal.url === 'string' && body.personal.url.endsWith('.ics')).toBe(true);
    // Aggregate URL presente (recién creada)
    expect(typeof body.aggregate).toBe('object');
    expect(typeof body.aggregate.url === 'string' && body.aggregate.url.endsWith('.ics')).toBe(true);
    // Grupo autogenerado con URL presente
    const groupFeed = (body.groups || []).find((g: any) => g.groupId === GROUP);
    expect(groupFeed).toBeDefined();
    expect(typeof groupFeed.url === 'string' && groupFeed.url.endsWith('.ics')).toBe(true);

    const previousGroupUrl = groupFeed.url;

    // POST rotate para el grupo
    const resRotate = await fetch(`${BASE}/api/integrations/feeds/rotate`, {
      method: 'POST',
      headers: {
        'content-type': 'application/json',
        cookie: `sid=${SID}`
      },
      body: JSON.stringify({ type: 'group', groupId: GROUP })
    });
    expect(resRotate.status).toBe(200);
    const bodyRotate = await resRotate.json();
    expect(typeof bodyRotate.url === 'string' && bodyRotate.url.endsWith('.ics')).toBe(true);
    expect(bodyRotate.url).not.toBe(previousGroupUrl);
  });

  it('el feed de grupo devuelve 410 cuando el grupo está archivado y 200 cuando está activo', async () => {
    server = await serverPromise;

    const sidHash = await sidHashPromise;
    // Asegurar sesión
    db.exec(`
      INSERT OR REPLACE INTO web_sessions (id, user_id, session_hash, created_at, last_seen_at, expires_at)
      VALUES ('sess-2', '${USER}', '${sidHash}', '${toIsoSql()}', '${toIsoSql()}', '${toIsoSql(new Date(Date.now() + 2 * 60 * 60 * 1000))}')
    `);

    // Obtener URL de grupo
    const res = await fetch(`${BASE}/api/integrations/feeds`, {
      headers: { cookie: `sid=${SID}` }
    });
    expect(res.status).toBe(200);
    const body = await res.json();
    const groupFeed = (body.groups || []).find((g: any) => g.groupId === GROUP);
    expect(groupFeed).toBeDefined();

    // Activo: debe devolver 200
    const ok1 = await fetch(groupFeed.url);
    expect(ok1.status).toBe(200);

    // Archivar grupo y verificar 410
    db.exec(`UPDATE groups SET archived = 1 WHERE id = '${GROUP}'`);
    const gone = await fetch(groupFeed.url);
    expect(gone.status).toBe(410);
  });
});
