'use strict';
/**
 * Integration tests: DELETE /api/admin/sessions/:id
 * Covers: session removal + cascade, audit entry, 404 for missing, 403 for non-admin.
 */
const { describe, it, before, after } = require('node:test');
const assert = require('node:assert/strict');
const { db, inject, getToken, cleanup } = require('./setup');

after(() => cleanup());

describe('Admin Session Delete', () => {
  let adminToken, studentUser, subjectId, sessionId;

  before(async () => {
    const a = await getToken('admin');
    adminToken = a.token;

    const s = await getToken('student');
    studentUser = s;

    // Ensure subject exists
    let subj = db.prepare("SELECT id FROM subjects WHERE slug = 'admin-sess-test'").get();
    if (!subj) {
      db.prepare("INSERT INTO subjects (slug, name, icon) VALUES ('admin-sess-test', 'Admin Sess Test', 'test')").run();
      subj = db.prepare("SELECT id FROM subjects WHERE slug = 'admin-sess-test'").get();
    }
    subjectId = subj.id;

    // Create a question with options
    const qId = db.prepare(
      'INSERT INTO questions (subject_id, text, difficulty) VALUES (?, ?, 1)'
    ).run(subjectId, 'Admin session delete test question').lastInsertRowid;
    db.prepare('INSERT INTO options (question_id, text, is_correct) VALUES (?, ?, 0)').run(qId, 'Wrong');
    db.prepare('INSERT INTO options (question_id, text, is_correct) VALUES (?, ?, 1)').run(qId, 'Correct');

    // Start a session via API
    const sessRes = await inject('POST', '/api/sessions', {
      subject_slug: 'admin-sess-test', count: 1, mode: 'exam',
    }, studentUser.token);
    assert.equal(sessRes.status, 201, `session create failed: ${JSON.stringify(sessRes.body)}`);
    sessionId = sessRes.body.session_id;

    // Answer to create user_answers row
    const q = sessRes.body.questions[0];
    await inject('POST', `/api/sessions/${sessionId}/answer`, {
      question_id: q.id, option_id: q.options[0].id,
    }, studentUser.token);
  });

  // ── 1. Non-admin gets 403 ────────────────────────────────────────────────
  it('student gets 403 when trying to delete a session', async () => {
    const res = await inject('DELETE', `/api/admin/sessions/${sessionId}`, null, studentUser.token);
    assert.equal(res.status, 403, `expected 403, got ${res.status}`);
  });

  // ── 2. 404 for non-existent session ─────────────────────────────────────
  it('returns 404 for non-existent session id', async () => {
    const res = await inject('DELETE', '/api/admin/sessions/999999', null, adminToken);
    assert.equal(res.status, 404, `expected 404, got ${res.status}: ${JSON.stringify(res.body)}`);
  });

  // ── 3. Session delete cascades user_answers and session_questions ─────────
  it('deletes session and cascades related rows', async () => {
    // Verify rows exist before delete
    const answersBefore = db.prepare('SELECT COUNT(*) AS n FROM user_answers WHERE session_id = ?')
      .get(sessionId).n;
    const sqBefore = db.prepare('SELECT COUNT(*) AS n FROM session_questions WHERE session_id = ?')
      .get(sessionId).n;

    // The session must still exist
    const sessBefore = db.prepare('SELECT id FROM test_sessions WHERE id = ?').get(sessionId);
    assert.ok(sessBefore, 'session should exist before delete');

    const res = await inject('DELETE', `/api/admin/sessions/${sessionId}`, null, adminToken);
    assert.equal(res.status, 200, `expected 200, got ${res.status}: ${JSON.stringify(res.body)}`);
    assert.equal(res.body.ok, true);

    // Session gone
    const sessAfter = db.prepare('SELECT id FROM test_sessions WHERE id = ?').get(sessionId);
    assert.equal(sessAfter, undefined, 'session should be deleted');

    // user_answers gone
    const answersAfter = db.prepare('SELECT COUNT(*) AS n FROM user_answers WHERE session_id = ?')
      .get(sessionId).n;
    assert.equal(answersAfter, 0, 'user_answers should be cleared after session delete');

    // session_questions gone
    const sqAfter = db.prepare('SELECT COUNT(*) AS n FROM session_questions WHERE session_id = ?')
      .get(sessionId).n;
    assert.equal(sqAfter, 0, 'session_questions should be cleared after session delete');
  });

  // ── 4. Audit entry created on delete ─────────────────────────────────────
  it('creates audit log entry on session delete', async () => {
    // Create and immediately delete another session
    const sessRes = await inject('POST', '/api/sessions', {
      subject_slug: 'admin-sess-test', count: 1, mode: 'practice',
    }, studentUser.token);
    assert.equal(sessRes.status, 201);
    const newSessId = sessRes.body.session_id;

    const countBefore = db.prepare(
      "SELECT COUNT(*) AS n FROM admin_audit_log WHERE action = 'session.delete'"
    ).get().n;

    await inject('DELETE', `/api/admin/sessions/${newSessId}`, null, adminToken);

    const countAfter = db.prepare(
      "SELECT COUNT(*) AS n FROM admin_audit_log WHERE action = 'session.delete'"
    ).get().n;
    assert.ok(countAfter > countBefore, 'Expected session.delete audit entry to be created');
  });
});
