import { describe, it, beforeEach, afterEach, expect } from 'bun:test';
import { Database } from 'bun:sqlite';
import { initializeDatabase } from '../../../src/db';
import { IdentityService } from '../../../src/services/identity';
import { WebhookServer } from '../../../src/server';
import { GroupSyncService } from '../../../src/services/group-sync';
import { setDb, resetDb } from '../../../src/db/locator';

const ORIGINAL_FETCH = globalThis.fetch;
const envBackup = { ...process.env };

describe('Alias @lid ↔ número: aprendizaje y uso en sync de miembros', () => {
  let memdb: Database;

  beforeEach(() => {
    process.env = { ...envBackup };
    memdb = new Database(':memory:');
    memdb.exec('PRAGMA foreign_keys = ON;');
    initializeDatabase(memdb);

    // Inyectar DB en servicios implicados
    (WebhookServer as any).dbInstance = memdb;
    setDb(memdb);

    // Limpiar caché de grupos para evitar interferencias
    GroupSyncService.activeGroupsCache.clear();
  });

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

  it('aprende alias desde participantAlt y luego resuelve miembros con solo @lid', async () => {
    // 1) Simular mensaje de grupo que trae participant (alias @lid) y participantAlt (número real)
    process.env.NODE_ENV = 'test'; // evita efectos de red/timers
    const payload = {
      key: {
        remoteJid: '12345-678@g.us',
        participant: 'userXYZ@lid',
        participantAlt: '666777888@s.whatsapp.net',
        fromMe: false
      },
      message: { conversation: 'hola' }
    };

    await WebhookServer.handleMessageUpsert(payload);

    // Verificar que el alias fue aprendido
    const resolved = IdentityService.resolveAliasOrNull('userXYZ@lid');
    expect(resolved).toBe('666777888');

    // Añadir un segundo alias manualmente para cubrir varios miembros
    IdentityService.upsertAlias('abc@lid', '999000111@s.whatsapp.net', 'test-seed');
    expect(IdentityService.resolveAliasOrNull('abc@lid')).toBe('999000111');

    // 2) Ahora simular la Evolution API devolviendo solo IDs con @lid en /group/participants
    process.env.NODE_ENV = 'development'; // evitar early-return en fetchGroupMembersFromAPI
    process.env.EVOLUTION_API_URL = 'http://evolution.test';
    process.env.EVOLUTION_API_INSTANCE = 'instance-1';
    process.env.EVOLUTION_API_KEY = 'apikey';

    globalThis.fetch = async (url: RequestInfo | URL) => {
      if (String(url).includes('/group/participants/')) {
        const body = {
          participants: [
            { id: 'userXYZ@lid', admin: 'admin' }, // debe resolverse a 666777888 (admin)
            { id: 'abc@lid', admin: null }         // debe resolverse a 999000111 (no admin)
          ]
        };
        return new Response(JSON.stringify(body), { status: 200, headers: { 'Content-Type': 'application/json' } });
      }
      return new Response('not found', { status: 404 });
    };

    const out = await (GroupSyncService as any).fetchGroupMembersFromAPI('12345-678@g.us');
    const map = new Map(out.map((x: any) => [x.userId, x.isAdmin]));

    expect(map.has('666777888')).toBe(true);
    expect(map.has('999000111')).toBe(true);
    expect(map.get('666777888')).toBe(true);   // admin resuelto
    expect(map.get('999000111')).toBe(false);  // no admin
  });
});
