'use strict';
/**
 * Integration tests: GET /api/admin/overview
 * Covers: shape, required fields + types, auth guard, empty DB returns zeros.
 */
const { describe, it, before, after } = require('node:test');
const assert = require('node:assert/strict');
const { inject, getToken, cleanup } = require('./setup');

after(() => cleanup());

describe('Admin Overview', () => {
  let adminToken, teacherToken;

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

  // ── 1. 401 without token ──────────────────────────────────────────────────
  it('returns 401 without auth token', async () => {
    const res = await inject('GET', '/api/admin/overview', null, null);
    assert.equal(res.status, 401, `expected 401, got ${res.status}`);
  });

  // ── 2. 403 for non-admin ──────────────────────────────────────────────────
  it('returns 403 for teacher (non-admin)', async () => {
    const res = await inject('GET', '/api/admin/overview', null, teacherToken);
    assert.equal(res.status, 403, `expected 403, got ${res.status}`);
  });

  // ── 3. Returns expected shape ─────────────────────────────────────────────
  it('returns correct shape with all required fields', async () => {
    const res = await inject('GET', '/api/admin/overview', null, adminToken);
    assert.equal(res.status, 200, `expected 200, got ${res.status}: ${JSON.stringify(res.body)}`);

    const body = res.body;
    // Numeric fields
    const numericFields = [
      'newUsers24h', 'newSessions24h', 'activeUsers24h',
      'classesTotal', 'abandonedSessions24h',
    ];
    for (const field of numericFields) {
      assert.ok(field in body, `missing field: ${field}`);
      assert.equal(typeof body[field], 'number', `${field} should be a number, got ${typeof body[field]}`);
    }

    // Array fields
    const arrayFields = [
      'stuckSessions', 'bannedThisWeek', 'topSessions24h',
      'worstSessions24h', 'sessionsBySubject24h',
    ];
    for (const field of arrayFields) {
      assert.ok(field in body, `missing array field: ${field}`);
      assert.ok(Array.isArray(body[field]), `${field} should be an array`);
    }

    // Sparks object
    assert.ok('sparks' in body, 'missing sparks field');
    assert.ok(Array.isArray(body.sparks.users), 'sparks.users should be an array');
    assert.ok(Array.isArray(body.sparks.sessions), 'sparks.sessions should be an array');
    assert.ok(Array.isArray(body.sparks.active), 'sparks.active should be an array');

    // Inventory object
    assert.ok('inventory' in body, 'missing inventory field');
    assert.ok(typeof body.inventory === 'object', 'inventory should be an object');
  });

  // ── 4. Empty DB (no sessions) returns zeros, not crashes ─────────────────
  it('does not crash on empty DB — returns zero counts', async () => {
    const res = await inject('GET', '/api/admin/overview', null, adminToken);
    assert.equal(res.status, 200, `expected 200, got ${res.status}`);
    // counts should be >= 0 (not negative, not NaN, not null)
    assert.ok(res.body.newSessions24h >= 0, 'newSessions24h should be >= 0');
    assert.ok(res.body.abandonedSessions24h >= 0, 'abandonedSessions24h should be >= 0');
  });
});
