// test/parsers.test.mjs — tests del parser de Skool (Fase 1: encuesta + billing)
// Correr: npm test  (o: node --test test/)
import { test } from 'node:test';
import assert from 'node:assert/strict';
import { parseSkoolData, parseSurvey, extractSurveyFields, detectSubscription, aggregateMemberComments, detectTier } from '../background/parsers.js';

const FUTURE = new Date(Date.now() + 15 * 86400000).toISOString();
const PAST = new Date(Date.now() - 5 * 86400000).toISOString();

// ── parseSurvey ───────────────────────────────────────────
test('parseSurvey: JSON string con { survey: [...] }', () => {
  const raw = JSON.stringify({ survey: [
    { question: 'Tu WhatsApp', answer: '+51 999' },
    { question: 'Nicho', answer: 'Finanzas' },
  ] });
  const out = parseSurvey(raw);
  assert.equal(out.length, 2);
  assert.deepEqual(out[0], { question: 'Tu WhatsApp', answer: '+51 999' });
});

test('parseSurvey: array directo de {question, answer}', () => {
  const out = parseSurvey([{ question: 'Q', answer: 'A' }]);
  assert.equal(out.length, 1);
  assert.equal(out[0].answer, 'A');
});

test('parseSurvey: claves alternativas (q/a, value)', () => {
  const out = parseSurvey([{ q: 'Pregunta', a: 'Resp' }, { label: 'Otra', value: 'X' }]);
  assert.equal(out.length, 2);
  assert.equal(out[0].question, 'Pregunta');
  assert.equal(out[1].answer, 'X');
});

test('parseSurvey: respuesta array → join', () => {
  const out = parseSurvey([{ question: 'Intereses', answer: ['a', 'b'] }]);
  assert.equal(out[0].answer, 'a, b');
});

test('parseSurvey: basura → []', () => {
  assert.deepEqual(parseSurvey('no-json'), []);
  assert.deepEqual(parseSurvey(null), []);
  assert.deepEqual(parseSurvey(42), []);
});

// ── extractSurveyFields ───────────────────────────────────
test('extractSurveyFields: detecta whatsapp, instagram y nicho', () => {
  const f = extractSurveyFields([
    { question: '¿Cuál es tu número de WhatsApp?', answer: '+51 987-654-321' },
    { question: 'Tu usuario de Instagram', answer: '@maria.lopez' },
    { question: '¿Cuál es tu nicho?', answer: 'Coaching de finanzas personales' },
  ]);
  assert.equal(f.whatsapp, '+51987654321');
  assert.equal(f.instagram, '@maria.lopez');
  assert.equal(f.niche, 'Coaching de finanzas personales');
});

test('extractSurveyFields: instagram desde URL completa', () => {
  const f = extractSurveyFields([{ question: 'Instagram', answer: 'https://instagram.com/andreaestratega/' }]);
  assert.equal(f.instagram, '@andreaestratega');
});

test('extractSurveyFields: teléfono inválido (muy corto) → null', () => {
  const f = extractSurveyFields([{ question: 'Tu celular', answer: '123' }]);
  assert.equal(f.whatsapp, null);
});

test('extractSurveyFields: sin coincidencias → todo null', () => {
  const f = extractSurveyFields([{ question: 'Color favorito', answer: 'Azul' }]);
  assert.deepEqual(f, { whatsapp: null, instagram: null, niche: null });
});

// ── detectTier ────────────────────────────────────────────
test('detectTier: valor exacto premium', () => {
  assert.equal(detectTier({ mtier: 'Premium' }, {}, {}), 'Premium');
});
test('detectTier: vip se normaliza a mayúsculas', () => {
  assert.equal(detectTier({ membershipTier: 'vip' }, {}, {}), 'VIP');
});
test('detectTier: clave de tier con valor compuesto', () => {
  assert.equal(detectTier({ tierName: 'plan standard mensual' }, {}, {}), 'Standard');
});
test('detectTier: sin tier → null', () => {
  assert.equal(detectTier({ mbsltv: 4700 }, {}, {}), null);
});

// ── parseSkoolData (integración) ──────────────────────────
test('parseSkoolData: miembro de Skool con metadata.survey + billing', () => {
  const rawMember = {
    name: 'maria-lopez-123',
    firstName: 'María',
    lastName: 'López',
    createdAt: '2026-01-01T00:00:00Z',
    member: {
      role: 'member',
      metadata: {
        mbme: 'maria@gmail.com',
        mbsltv: 4700,          // $47.00
        mmbp: 4700,
        msbs: 'sub_abc123',
        survey: JSON.stringify({ survey: [
          { question: '¿Cuál es tu WhatsApp?', answer: '+51 987 654 321' },
          { question: 'Usuario de Instagram', answer: '@maria.lopez' },
          { question: '¿En qué nicho trabajas?', answer: 'Finanzas' },
        ] }),
      },
    },
  };
  const parsed = parseSkoolData('/members', { users: [rawMember] }, 'GET');
  assert.ok(parsed, 'debe parsear');
  assert.equal(parsed.type, 'members');
  const m = parsed.members[0];
  assert.equal(m.name, 'María López');
  assert.equal(m.email, 'maria@gmail.com');
  assert.equal(m.whatsapp, '+51987654321');
  assert.equal(m.instagram, '@maria.lopez');
  assert.equal(m.niche, 'Finanzas');
  assert.equal(m.ltv, 47);
  assert.equal(m.subId, 'sub_abc123');
  assert.ok(Array.isArray(m.surveyAnswers) && m.surveyAnswers.length === 3);
});

// ── detectSubscription (Fase 2) ───────────────────────────
test('detectSubscription: cancelAt futuro → cancelling', () => {
  const s = detectSubscription({ mbcancelat: FUTURE }, {}, {});
  assert.equal(s.subStatus, 'cancelling');
  assert.ok(s.cancelAt > Date.now());
});

test('detectSubscription: status "canceled" + fecha pasada → canceled', () => {
  const s = detectSubscription({ mbss: 'canceled', mbcancelat: PAST }, {}, {});
  assert.equal(s.subStatus, 'canceled');
});

test('detectSubscription: flag boolean cancel + fin de periodo futuro → cancelling', () => {
  const s = detectSubscription({ mbcancelatperiodend: true, mbcurrentperiodend: FUTURE }, {}, {});
  assert.equal(s.subStatus, 'cancelling');
  assert.ok(s.cancelAt > Date.now());
});

test('detectSubscription: status activo → active', () => {
  const s = detectSubscription({ mbss: 'active' }, {}, {});
  assert.equal(s.subStatus, 'active');
});

test('detectSubscription: sin señales → null', () => {
  const s = detectSubscription({ mbsltv: 4700, mbme: 'x@y.com' }, {}, {});
  assert.equal(s.subStatus, null);
  assert.equal(s.cancelAt, null);
});

test('detectSubscription: ignora "false"/"none" en campos cancel', () => {
  const s = detectSubscription({ mbcancelreason: 'none', mbcanceled: 'false' }, {}, {});
  assert.equal(s.subStatus, null);
});

test('parseSkoolData: miembro cancelando se refleja en subStatus', () => {
  const parsed = parseSkoolData('/members', { users: [{
    name: 'ana', id: 'ana',
    member: { metadata: { mbss: 'cancelling', mbcancelat: FUTURE } },
  }] }, 'GET');
  const m = parsed.members[0];
  assert.equal(m.subStatus, 'cancelling');
  assert.ok(m.cancelAt > Date.now());
});

// ── aggregateMemberComments (Fase 3) ──────────────────────
test('aggregateMemberComments: cuenta y toma el último comentario', () => {
  const members = [{ id: 'maria-123', username: 'maria-123', name: 'María' }];
  const comments = [
    { id: 'c1', authorName: 'maria-123', content: 'viejo', createdAt: '2026-01-01T00:00:00Z' },
    { id: 'c2', authorName: 'maria-123', content: 'nuevo', createdAt: '2026-06-01T00:00:00Z' },
  ];
  const agg = aggregateMemberComments(members, comments);
  assert.equal(agg['maria-123'].commentCount, 2);
  assert.equal(agg['maria-123'].lastCommentText, 'nuevo');
});

test('aggregateMemberComments: empareja por authorId contra userId', () => {
  const members = [{ id: 'handle-x', userId: '99', username: 'handle-x' }];
  const comments = [{ id: 'c1', authorId: '99', content: 'hola', createdAt: '2026-05-01T00:00:00Z' }];
  const agg = aggregateMemberComments(members, comments);
  assert.equal(agg['handle-x'].commentCount, 1);
});

test('aggregateMemberComments: deduplica el mismo comentario por id', () => {
  const members = [{ id: 'h', username: 'h', name: 'h' }]; // varias claves = mismo valor
  const comments = [
    { id: 'c1', authorName: 'h', content: 'x', createdAt: '2026-05-01T00:00:00Z' },
    { id: 'c1', authorName: 'h', content: 'x', createdAt: '2026-05-01T00:00:00Z' },
  ];
  const agg = aggregateMemberComments(members, comments);
  assert.equal(agg['h'].commentCount, 1);
});

test('aggregateMemberComments: sin coincidencias → objeto vacío', () => {
  const agg = aggregateMemberComments([{ id: 'a', username: 'a' }], [{ id: 'c1', authorName: 'otro' }]);
  assert.deepEqual(agg, {});
});

test('parseSkoolData: miembro sin survey ni billing no rompe', () => {
  const parsed = parseSkoolData('/members', { users: [{ name: 'juan', id: 'juan' }] }, 'GET');
  const m = parsed.members[0];
  assert.equal(m.whatsapp, null);
  assert.equal(m.ltv, null);
  assert.equal(m.surveyAnswers, undefined);
});
