/**
 * Session 64 — the CLV gate is SERVER-SIDE, at the data layer.
 *
 * A Free request must never RECEIVE dclv data. Client/CSS hiding is rejected:
 * data that reaches the browser has left the building. These lock the gate and
 * the surface audit, so a future column addition can't quietly leak.
 */
const fs = require('fs');
const path = require('path');
const { canAccess } = require('../../src/config/tiers');

const read = (f) => fs.readFileSync(path.join(__dirname, '..', '..', f), 'utf8');

describe('TIER capability', () => {
  test('analyst and desk may see the badge; free may not', () => {
    expect(canAccess('analyst', 'clv_badge')).toBe(true);
    expect(canAccess('desk', 'clv_badge')).toBe(true);
    expect(canAccess('free', 'clv_badge')).toBeFalsy();
    expect(canAccess(undefined, 'clv_badge')).toBeFalsy();
  });
});

describe('SERVER GATE — the data never leaves for an unentitled tier', () => {
  const ledger = read('src/routes/ledger.js');

  test('CLV columns are appended only via a capability check', () => {
    expect(ledger).toMatch(/canAccess\(tier, 'clv_badge'\)/);
    expect(ledger).toMatch(/CLV_COLUMNS/);
  });

  test('the base column list does NOT contain dclv', () => {
    // Assert on the literal itself — a nearby comment mentioning dclv is fine.
    const m = ledger.match(/const ROW_COLUMNS = '([^']+)'/);
    expect(m).toBeTruthy();
    expect(m[1]).not.toMatch(/dclv/);
  });

  test('responses are ALSO stripped — defence in depth, not just the SELECT', () => {
    expect(ledger).toMatch(/function stripClv/);
    expect(ledger).toMatch(/stripClv\(data, req\)/);
  });

  test('de-vig internals (fair_lock/fair_close) are never SELECTED for clients', () => {
    // They may (and should) appear in the strip list — that is the guard.
    const sel = ledger.match(/const CLV_COLUMNS = '([^']+)'/);
    expect(sel[1]).not.toMatch(/fair_lock|fair_close/);
    expect(ledger).toMatch(/dclv_fair_lock, dclv_fair_close, \.\.\.rest/);
  });
});

describe('SURFACE AUDIT — every channel CLV could leak through', () => {
  const surfaces = {
    'public profile (share link)': 'src/routes/profiles.js',
    'snapshot / card feed': 'src/routes/snapshot.js',
    'ticker feed': 'src/routes/ticker.js',
    'share card / OG': 'src/routes/shareCard.js',
    'widget (embeddable)': 'src/routes/widget.js',
    'newsletter': 'src/services/newsletterService.js',
  };
  for (const [name, file] of Object.entries(surfaces)) {
    test(`${name} carries NO CLV data`, () => {
      expect(read(file)).not.toMatch(/dclv/);
    });
  }

  test('no ledger read uses select("*") — a star would auto-leak new columns', () => {
    for (const f of ['src/routes/ledger.js', 'src/routes/profiles.js', 'src/services/ledgerService.js']) {
      const src = read(f);
      const stars = src.match(/from\('ledger_entries'\)[\s\S]{0,60}?select\('\*'\)/g) || [];
      expect(stars).toHaveLength(0);
    }
  });
});

describe('IMMUTABILITY — a shown badge never silently flips', () => {
  const svc = read('src/services/ledgerService.js');
  test('dclv is computed only when it has never been computed', () => {
    expect(svc).toMatch(/row\.dclv_computed_at\s*\n?\s*\?\s*null/);
  });
  test('the settle read fetches dclv_computed_at so the guard can see it', () => {
    expect(svc).toMatch(/dclv_computed_at, player_key/);
  });
});
