const { describe, it, before, after } = require('node:test');
const assert = require('node:assert/strict');
const { db, inject, getToken, cleanup } = require('./setup');

after(() => cleanup());

describe('Sessions', () => {
  let token, userId;

  before(async () => {
    const u = await getToken('student');
    token = u.token; userId = u.userId;

    // Ensure subject + questions exist
    const subj = db.prepare('SELECT id FROM subjects WHERE slug = ?').get('chem');
    if (!subj) {
      db.prepare("INSERT INTO subjects (slug, name, icon) VALUES ('chem', 'Химия', 'atom')").run();
    }
    const subjId = db.prepare('SELECT id FROM subjects WHERE slug = ?').get('chem').id;

    // Create some questions
    const ins = db.prepare('INSERT INTO questions (subject_id, text, difficulty) VALUES (?, ?, 1)');
    for (let i = 0; i < 5; i++) {
      const qId = ins.run(subjId, `Test question ${i + 1}`).lastInsertRowid;
      // Add options
      db.prepare('INSERT INTO options (question_id, text, is_correct) VALUES (?, ?, ?)').run(qId, 'Wrong', 0);
      db.prepare('INSERT INTO options (question_id, text, is_correct) VALUES (?, ?, ?)').run(qId, 'Correct', 1);
    }
  });

  it('validates subject_slug required', async () => {
    const res = await inject('POST', '/api/sessions', { mode: 'exam' }, token);
    assert.equal(res.status, 400);
  });

  it('validates mode enum', async () => {
    const res = await inject('POST', '/api/sessions', {
      subject_slug: 'chem', mode: 'invalid'
    }, token);
    assert.equal(res.status, 400);
  });

  it('validates count range', async () => {
    const res = await inject('POST', '/api/sessions', {
      subject_slug: 'chem', count: 999
    }, token);
    assert.equal(res.status, 400);
  });

  it('starts a session successfully', async () => {
    const res = await inject('POST', '/api/sessions', {
      subject_slug: 'chem', count: 3, mode: 'exam'
    }, token);
    assert.equal(res.status, 201);
    assert.ok(res.body.session_id);
    assert.equal(res.body.mode, 'exam');
    assert.ok(res.body.questions.length > 0);
  });

  it('submits an answer', async () => {
    // Start fresh session
    const s = await inject('POST', '/api/sessions', {
      subject_slug: 'chem', count: 2, mode: 'practice'
    }, token);
    const sessionId = s.body.session_id;
    const q = s.body.questions[0];

    const res = await inject('POST', `/api/sessions/${sessionId}/answer`, {
      question_id: q.id, option_id: q.options[0].id
    }, token);
    assert.equal(res.status, 200);
    assert.ok('is_correct' in res.body);
  });

  it('validates answer question_id required', async () => {
    const s = await inject('POST', '/api/sessions', {
      subject_slug: 'chem', count: 2
    }, token);
    const sessionId = s.body.session_id;

    const res = await inject('POST', `/api/sessions/${sessionId}/answer`, {}, token);
    assert.equal(res.status, 400);
  });

  it('finishes a session', async () => {
    const s = await inject('POST', '/api/sessions', {
      subject_slug: 'chem', count: 1
    }, token);
    const sessionId = s.body.session_id;

    const res = await inject('POST', `/api/sessions/${sessionId}/finish`, {}, token);
    assert.equal(res.status, 200);
    assert.ok('score' in res.body);
  });

  it('returns session history', async () => {
    const res = await inject('GET', '/api/sessions/history', null, token);
    assert.equal(res.status, 200);
    assert.ok(Array.isArray(res.body.rows));
  });

  it('rejects session start without auth', async () => {
    const res = await inject('POST', '/api/sessions', { subject_slug: 'chem' });
    assert.equal(res.status, 401);
  });
});
