// Session 65 (P0 deploy fix) — the API crashed at boot because a GARNISH
// file (content/stark-lines.json) was a hard module-load readFileSync and
// wasn't in the container image. These tests lock the fix: the media engine
// boots and functions with the file ABSENT, and the preflight names what's
// missing without ever throwing.

describe('mediaEngine — boots and posts with the Stark library absent (§L2)', () => {
  let media;
  beforeEach(() => {
    jest.resetModules();
    // Make EVERY stark-lines.json read throw ENOENT — simulate the file
    // missing from the image (the exact production failure).
    jest.doMock('fs', () => {
      const real = jest.requireActual('fs');
      return {
        ...real,
        readFileSync: (p, ...rest) => {
          if (String(p).includes('stark-lines.json')) {
            const err = new Error('ENOENT: no such file');
            err.code = 'ENOENT';
            throw err;
          }
          return real.readFileSync(p, ...rest);
        },
      };
    });
    media = require('../../src/services/mediaEngine');
  });
  afterEach(() => { jest.dontMock('fs'); jest.resetModules(); });

  test('requiring the module does NOT throw (this was the boot crash)', () => {
    expect(media).toBeTruthy();
    expect(media.__internals.STARK).toEqual({}); // empty library, not a crash
  });

  test('starkLine returns null with no library — the garnish is simply absent', () => {
    expect(media.starkLine('morning', '2026-07-12T14:00:00Z')).toBeNull();
  });

  test('formats still produce valid, VOICE-clean posts without the kicker', () => {
    const wire = media.morningWire({ dateIso: '2026-07-12T14:00:00Z', counts: { mlb: 15 }, loudest: null });
    expect(wire).toContain('15 MLB.');
    expect(wire).toContain('vyndr.app');
    expect(media.lintVoice(wire)).toEqual([]);

    const settle = media.theSettle({
      aggregate: { settled: 5, hits: 3, misses: 2, pushes: 0, hit_pct: null, pending: 10, by_tier: {} },
      misses: [{ player_name: 'A Guy', stat: 'points', line: 23.5, side: 'over' }],
      dateIso: '2026-07-12T14:00:00Z',
    });
    expect(settle).toContain('All grades: 3-2');
    expect(media.lintVoice(settle)).toEqual([]);
  });
});

describe('deskService assembles with the Stark library absent', () => {
  test('variants() tolerates an empty STARK (no throw, no kicker to strip)', () => {
    jest.resetModules();
    jest.doMock('fs', () => {
      const real = jest.requireActual('fs');
      return {
        ...real,
        readFileSync: (p, ...rest) => {
          if (String(p).includes('stark-lines.json')) { const e = new Error('ENOENT'); e.code = 'ENOENT'; throw e; }
          return real.readFileSync(p, ...rest);
        },
      };
    });
    const { assembleDeskPack } = require('../../src/services/deskService');
    expect(typeof assembleDeskPack).toBe('function');
    jest.dontMock('fs');
    jest.resetModules();
  });
});

describe('preflight — names what is missing, never throws (§A4)', () => {
  const { runPreflight } = require('../../src/preflight');

  test('reports OK with a captured logger when content + env are present', () => {
    const logs = [];
    const fake = { log: (m) => logs.push(['log', m]), warn: (m) => logs.push(['warn', m]) };
    const prev = { SUPABASE_URL: process.env.SUPABASE_URL, SUPABASE_SERVICE_ROLE_KEY: process.env.SUPABASE_SERVICE_ROLE_KEY, REDIS_URL: process.env.REDIS_URL, VYNDR_INTERNAL_KEY: process.env.VYNDR_INTERNAL_KEY };
    process.env.SUPABASE_URL = 'x'; process.env.SUPABASE_SERVICE_ROLE_KEY = 'x'; process.env.REDIS_URL = 'x'; process.env.VYNDR_INTERNAL_KEY = 'x';
    const res = runPreflight(fake);
    // content/stark-lines.json + src/config/coaches.json both exist in the tree.
    expect(res.ok).toBe(true);
    expect(logs.some(([lvl, m]) => lvl === 'log' && m.includes('[preflight] OK'))).toBe(true);
    Object.assign(process.env, prev);
    for (const k of Object.keys(prev)) if (prev[k] === undefined) delete process.env[k];
  });

  test('names missing env, does not throw, returns not-ok', () => {
    const logs = [];
    const fake = { log: (m) => logs.push(m), warn: (m) => logs.push(m) };
    const prev = { SUPABASE_URL: process.env.SUPABASE_URL, REDIS_URL: process.env.REDIS_URL, VYNDR_INTERNAL_KEY: process.env.VYNDR_INTERNAL_KEY, SUPABASE_SERVICE_ROLE_KEY: process.env.SUPABASE_SERVICE_ROLE_KEY, SUPABASE_SERVICE_KEY: process.env.SUPABASE_SERVICE_KEY };
    delete process.env.SUPABASE_URL; delete process.env.REDIS_URL; delete process.env.VYNDR_INTERNAL_KEY;
    delete process.env.SUPABASE_SERVICE_ROLE_KEY; delete process.env.SUPABASE_SERVICE_KEY;
    const res = runPreflight(fake);
    expect(res.ok).toBe(false);
    expect(res.missingEnv).toEqual(expect.arrayContaining(['SUPABASE_URL', 'REDIS_URL', 'VYNDR_INTERNAL_KEY']));
    expect(logs.some((m) => m.includes('DEGRADED'))).toBe(true);
    Object.assign(process.env, prev);
    for (const k of Object.keys(prev)) if (prev[k] === undefined) delete process.env[k];
  });
});
