import test from 'node:test';
import assert from 'node:assert/strict';
import os from 'os';
import path from 'path';
import { rm } from 'fs/promises';

import { contentLoader } from './ContentLoader.js';
import { emailService } from './EmailService.js';
import { progressionSystem } from './ProgressionSystem.js';
import { questEngine } from './QuestEngine.js';
import { saveState } from './SaveState.js';
import { ticketService } from './TicketService.js';
import { trustSystem } from './TrustSystem.js';
import { validationEngine } from './ValidationEngine.js';

async function resetState(testId) {
  await saveState._writeQueue.catch(() => {});
  process.env.CONTENT_DIR = path.resolve(process.cwd(), '../content');
  process.env.SAVE_DIR = path.join(os.tmpdir(), `sc-server-test-${testId}-${Date.now()}`);

  saveState._savePath = null;
  saveState._state = null;
  saveState._writeQueue = Promise.resolve();

  await rm(process.env.SAVE_DIR, { recursive: true, force: true });
  await contentLoader.load();
  await saveState.load();

  const state = saveState.get();
  progressionSystem.initialize(state);
  trustSystem.initialize(state);
  questEngine.initialize(state);
  ticketService.initialize(state);
  emailService.initialize(state);
  await saveState._writeQueue.catch(() => {});
}

test('fresh state only exposes T001 as the active ticket', async () => {
  await resetState('fresh');

  const tickets = ticketService.getAll();
  assert.deepEqual(tickets.map((ticket) => ticket.id), ['T001']);
  assert.equal(questEngine.getState('Q001'), 'active');
  assert.equal(questEngine.getState('Q002'), 'locked');
});

test('markComplete resolves the active ticket, unlocks world flags, and activates the next ticket', async () => {
  await resetState('complete-clean');

  const originalResolveBranch = validationEngine.resolveBranch.bind(validationEngine);
  validationEngine.resolveBranch = async (quest) => ({
    branch: quest.solution_branches.find((branch) => branch.id === 'correct-setup'),
    failures: []
  });

  try {
    const result = await ticketService.markComplete('T001');
    assert.equal(result.passed, true);
    assert.equal(result.branch, 'correct-setup');
    assert.equal(result.trust_delta, 1);
    assert.equal(ticketService.getEntry('T001').status, 'resolved');
    assert.equal(ticketService.getEntry('T002').status, 'open');
    assert.equal(questEngine.getState('Q001'), 'completed');
    assert.equal(questEngine.getState('Q002'), 'active');
    assert.equal(trustSystem.getScore(), 51);

    const state = saveState.get();
    assert.ok(state.world_flags.includes('player_ssh_configured'));
  } finally {
    validationEngine.resolveBranch = originalResolveBranch;
  }
});

test('non-positive branch outcomes send follow-up mail and still open the next ticket', async () => {
  await resetState('complete-permissive');

  const result = await ticketService.markComplete('T001', { branchId: 'permissive-setup' });
  assert.equal(result.passed, true);
  assert.equal(result.branch, 'permissive-setup');
  assert.equal(result.trust_delta, 0);
  assert.equal(ticketService.getEntry('T002').status, 'open');
  assert.ok(result.follow_up_mail_ids.length > 0);

  const followUp = emailService.getAll().find((mail) => result.follow_up_mail_ids.includes(mail.id));
  assert.ok(followUp);
});
