/**
 * SET 30a — global stats reset: hardcoded server-side password, never a
 * client-side check. Unit tests the password verifier + Telemetry.reset(),
 * then an actual-behavior HTTP test (no supertest — a real listening server)
 * for the 403 / 200 route contract.
 */
import { describe, expect, it, beforeEach, afterEach } from 'vitest';
import express from 'express';
import fs from 'node:fs';
import os from 'node:os';
import path from 'node:path';
import type { AddressInfo } from 'node:net';
import { Telemetry } from '../src/server/telemetry';
import { createGlobalStatsAdminRouter, verifyGlobalStatsResetPassword } from '../src/server/globalStatsAdmin';

describe('verifyGlobalStatsResetPassword', () => {
  it('accepts only the exact hardcoded password', () => {
    expect(verifyGlobalStatsResetPassword('foreignhippopotamus998651')).toBe(true);
    expect(verifyGlobalStatsResetPassword('wrong')).toBe(false);
    expect(verifyGlobalStatsResetPassword('')).toBe(false);
    expect(verifyGlobalStatsResetPassword('foreignhippopotamus998651 ')).toBe(false);
  });
});

describe('Telemetry.reset', () => {
  let dir: string;

  beforeEach(() => {
    dir = fs.mkdtempSync(path.join(os.tmpdir(), 'rha-telemetry-'));
  });

  afterEach(() => {
    fs.rmSync(dir, { recursive: true, force: true });
  });

  it('zeroes totals and daily, and persists the zeroed state to disk', () => {
    const t = new Telemetry(dir);
    t.recordHit('Mozilla/5.0 real browser');
    t.recordRunStart();
    t.recordRunEnd(true);
    expect(t.snapshot().totals.hits).toBe(1);
    expect(t.snapshot().totals.runsExecuted).toBe(1);

    t.reset();
    const snap = t.snapshot();
    expect(snap.totals).toEqual({
      hits: 0, botHits: 0, pluginDownloads: 0, runsExecuted: 0, runsSucceeded: 0, runsFailed: 0,
    });
    expect(Object.keys(snap.daily)).toHaveLength(0);

    const onDisk = JSON.parse(fs.readFileSync(path.join(dir, 'telemetry.json'), 'utf8'));
    expect(onDisk.totals.hits).toBe(0);
  });
});

describe('POST /reset-global-stats (actual HTTP behavior)', () => {
  let dir: string;
  let telemetry: Telemetry;
  let server: ReturnType<express.Express['listen']>;
  let base: string;

  beforeEach(async () => {
    dir = fs.mkdtempSync(path.join(os.tmpdir(), 'rha-telemetry-http-'));
    telemetry = new Telemetry(dir);
    telemetry.recordHit('Mozilla/5.0 real browser');
    telemetry.recordRunStart();

    const app = express();
    app.use('/api/admin', createGlobalStatsAdminRouter(telemetry));
    await new Promise<void>(resolve => {
      server = app.listen(0, () => resolve());
    });
    const port = (server.address() as AddressInfo).port;
    base = `http://127.0.0.1:${port}`;
  });

  afterEach(async () => {
    await new Promise<void>(resolve => server.close(() => resolve()));
    fs.rmSync(dir, { recursive: true, force: true });
  });

  it('wrong password → 403, no-op (counters untouched)', async () => {
    const r = await fetch(`${base}/api/admin/reset-global-stats`, {
      method: 'POST',
      headers: { 'content-type': 'application/json' },
      body: JSON.stringify({ password: 'nope' }),
    });
    expect(r.status).toBe(403);
    expect(telemetry.snapshot().totals.hits).toBe(1);
  });

  it('correct password → 200, counters zeroed, response logs the reset', async () => {
    const r = await fetch(`${base}/api/admin/reset-global-stats`, {
      method: 'POST',
      headers: { 'content-type': 'application/json' },
      body: JSON.stringify({ password: 'foreignhippopotamus998651' }),
    });
    expect(r.status).toBe(200);
    const j = await r.json() as { ok: boolean; message: string; ts: string };
    expect(j.ok).toBe(true);
    expect(j.message).toBe('global stats reset');
    expect(typeof j.ts).toBe('string');
    expect(telemetry.snapshot().totals.hits).toBe(0);
    expect(telemetry.snapshot().totals.runsExecuted).toBe(0);
  });
});
