// End-to-end test of the Module-1 unlock gate (ECO-15/38).
//
// Drives a Silver mentee from approved purchase through L01..L07 confirmations
// and asserts that on L07 confirmation:
//   1. accessLevel flips course_only → dossier_pending
//   2. module1CompletedAt is set
//   3. The "module1_complete_dossier_pending" copy is sent to the group
//
//   node scripts/test-module1-gate.mjs

import { mkdirSync, rmSync, existsSync, cpSync } from 'fs';
import { join, dirname } from 'path';
import { fileURLToPath } from 'url';
import { tmpdir } from 'os';
import { configureTest, _resetTestState, readOutbox, clearOutbox } from '../lib/whatsappAdapter.js';
import { handleHotmartWebhook } from '../lib/hotmartWebhook.js';
import { handleSilverMessage } from '../lib/silverCourse.js';
import { loadSilver, lessonByDay, markLessonSent, saveSilver } from '../lib/silverStore.js';

const REAL = dirname(fileURLToPath(import.meta.url)).replace(/\/scripts$/, '');
const TMP = join(tmpdir(), `ecobot-m1-test-${Date.now()}`);

let pass = 0, fail = 0;
function check(label, ok, detail) {
  if (ok) { pass += 1; console.log(`✅ ${label}`); }
  else    { fail += 1; console.log(`❌ ${label}${detail ? ' — ' + detail : ''}`); }
}

async function main() {
  if (existsSync(TMP)) rmSync(TMP, { recursive: true, force: true });
  mkdirSync(TMP, { recursive: true });
  cpSync(join(REAL, 'data'), join(TMP, 'data'), { recursive: true });
  configureTest();
  _resetTestState();

  process.env.HOTMART_HOTTOK = 'TEST_HOTTOK';

  // 1. Onboard via Hotmart webhook
  const fixture = (await import('fs')).readFileSync(join(REAL, 'scripts', 'fixtures', 'hotmart-approved.json'), 'utf8');
  const payload = JSON.parse(fixture);
  payload.hottok = 'TEST_HOTTOK';
  const r = await handleHotmartWebhook(TMP, {
    rawBody: Buffer.from(JSON.stringify(payload)),
    headers: { 'content-type': 'application/json' },
  });
  check('hotmart approved → 200', r.status === 200);
  const slug = r.body.slug;
  let state = loadSilver(TMP, slug);
  check('initial accessLevel = course_only', state.accessLevel === 'course_only');

  // 2. Walk L01..L07: simulate sendLesson having marked awaitingYesFor, then user replies Yes
  for (let day = 1; day <= 7; day += 1) {
    const lesson = lessonByDay(TMP, day);
    state = loadSilver(TMP, slug);
    markLessonSent(state, lesson.id);  // sets awaitingYesFor=lesson.id
    saveSilver(TMP, slug, state);

    clearOutbox();
    await handleSilverMessage(TMP, slug, { text: 'Yes', fromNum: '41791234567' });
    state = loadSilver(TMP, slug);
    check(`L0${day} marked complete`, !!state.lessons[lesson.id]?.completedAt, `lessons.${lesson.id}=${JSON.stringify(state.lessons[lesson.id])}`);

    if (day < 7) {
      check(`after L0${day} accessLevel still course_only`, state.accessLevel === 'course_only', `got ${state.accessLevel}`);
      check(`after L0${day} module1CompletedAt still null`, state.module1CompletedAt === null);
    }
  }

  // 3. After L07 (lessons done, tasks NOT yet claimed): module 1 should NOT
  // yet flip to complete. The bot should send the
  // "module_lessons_done_tasks_remaining" copy instead.
  // (Refined flow: a module is complete only when lessons + tasks are all
  // green. See lib/silverStore.maybeMarkModuleComplete.)
  state = loadSilver(TMP, slug);
  check('after L07 (no tasks) accessLevel still course_only', state.accessLevel === 'course_only', `got ${state.accessLevel}`);
  check('after L07 (no tasks) modulesCompleted[1] is false', !state.modulesCompleted?.[1]);

  const tasksRemainingMsg = readOutbox().find(o => typeof o.text === 'string' && /Almost there for \*Module 1\*/i.test(o.text));
  check('tasks-remaining message sent after L07', !!tasksRemainingMsg);

  // 4. Claim all 4 Module-1 tasks → module 1 should now flip
  clearOutbox();
  state = loadSilver(TMP, slug);
  for (const id of ['T-W1-career-plan', 'T-W1-cv-v1', 'T-W1-linkedin', 'T-W1-applications']) {
    state.tasks[id] = { taskId: id, status: 'claimed', recordedAt: new Date().toISOString() };
  }
  saveSilver(TMP, slug, state);

  // Trigger the module check by replaying the Yes for L07 (idempotent for
  // lesson completion but re-runs the module loop)
  const lesson7 = lessonByDay(TMP, 7);
  state = loadSilver(TMP, slug);
  state.awaitingYesFor = lesson7.id;
  saveSilver(TMP, slug, state);
  await handleSilverMessage(TMP, slug, { text: 'Yes', fromNum: '41791234567' });

  state = loadSilver(TMP, slug);
  check('after L07 + tasks accessLevel = dossier_pending', state.accessLevel === 'dossier_pending', `got ${state.accessLevel}`);
  check('after L07 + tasks module1CompletedAt set', !!state.module1CompletedAt);
  check('after L07 + tasks modulesCompleted[1] = true', state.modulesCompleted[1] === true);
  check('accessLevelChangedBy = system:module1_complete', state.accessLevelChangedBy === 'system:module1_complete');

  const outbox = readOutbox();
  const m1Message = outbox.find(o => typeof o.text === 'string' && /Module 1 done/i.test(o.text));
  check('module1_complete_strategy_url message sent', !!m1Message);
  check('m1 message references career strategy', m1Message && /Career Strategy|career strategy/i.test(m1Message.text));
  const hasJobbotUrl = m1Message && /jobbot\.|\/plan\?t=/i.test(m1Message.text);
  check('m1 message contains a strategy URL', m1Message && /https?:\/\//i.test(m1Message.text));
  check('m1 message does NOT contain a Job-bot link', m1Message && !hasJobbotUrl);

  rmSync(TMP, { recursive: true, force: true });
  console.log(`\n${pass} passed, ${fail} failed`);
  process.exit(fail === 0 ? 0 : 1);
}

main().catch(e => { console.error(e); process.exit(1); });
