import { describe, it, expect, afterEach } from 'vitest';
import { mkdtempSync, rmSync, writeFileSync } from 'fs';
import { join } from 'path';
import { tmpdir } from 'os';
import { loadConfig } from './config.js';

// Audit 2026-06-08 (config-consistency, P1×2). Both encode the documented,
// expected behavior that the current normalizer/env-override plumbing violates.
function withTempConfig(yaml: string, fn: (path: string) => void): void {
  const dir = mkdtempSync(join(tmpdir(), 'maestro-cfg-audit-'));
  try {
    const p = join(dir, 'config.yaml');
    writeFileSync(p, yaml);
    fn(p);
  } finally {
    rmSync(dir, { recursive: true, force: true });
  }
}

describe('config audit regression (2026-06-08)', () => {
  const envSnapshot: Record<string, string | undefined> = {};
  afterEach(() => {
    for (const [k, v] of Object.entries(envSnapshot)) {
      if (v === undefined) delete process.env[k];
      else process.env[k] = v;
    }
  });

  // P1: defaults seed tools.trashRetentionDays=30 BEFORE the normalizer runs, so
  // the reverse-backfill (`if (tools.X === undefined)`) is a no-op and a user's
  // v2 `storage.trash_retention_days` is silently ignored by the actual consumer
  // (server.ts reads config.tools.trashRetentionDays). Same default-precedence
  // trap as PR #368→#369.
  it('v2 storage.trash_retention_days actually takes effect on the consumed value', () => {
    withTempConfig('config_version: 2\nstorage:\n  trash_retention_days: 60\n', (p) => {
      const config = loadConfig(p);
      expect(config.tools.trashRetentionDays).toBe(60);
    });
  });

  // P1: OLLAMA_BASE_URL / OLLAMA_MODEL are applied to `provider.*` BEFORE
  // normalize, but for a v2 config with explicit llm.workers the backfill keeps
  // the YAML workers and never reads provider — so the documented env override
  // silently has no effect on the endpoint that is actually called.
  // The runtime executes config.provider.workers (worker.ts:459), so the env
  // override must reach THAT array. config.llm.workers is the v2 block that
  // config-manager persists, so it must stay the explicit YAML value — otherwise
  // saving any setting while OLLAMA_BASE_URL is set would bake the env value into
  // the YAML and permanently clobber the user's endpoint (codex P2).
  it('OLLAMA_BASE_URL overrides the executed (provider) worker but not the persisted llm block', () => {
    envSnapshot['OLLAMA_BASE_URL'] = process.env['OLLAMA_BASE_URL'];
    process.env['OLLAMA_BASE_URL'] = 'http://override-host:9999/v1';
    withTempConfig(
      'config_version: 2\nllm:\n  workers:\n    - name: w1\n      endpoint: http://yaml-host:11434/v1\n      model: m1\n',
      (p) => {
        const config = loadConfig(p);
        expect(config.provider.workers[0]?.endpoint).toBe('http://override-host:9999/v1'); // runtime
        expect(config.llm.workers[0]?.endpoint).toBe('http://yaml-host:11434/v1'); // persisted, untouched
      },
    );
  });

  // The override is scoped to the FIRST/default worker only — a multi-worker
  // pool (gateway/title/reflection) must NOT have every endpoint clobbered when
  // a Docker .env sets OLLAMA_BASE_URL (codex P1).
  it('OLLAMA_BASE_URL leaves additional workers untouched on the runtime array', () => {
    envSnapshot['OLLAMA_BASE_URL'] = process.env['OLLAMA_BASE_URL'];
    process.env['OLLAMA_BASE_URL'] = 'http://override-host:9999/v1';
    withTempConfig(
      'config_version: 2\nllm:\n  workers:\n' +
        '    - name: w1\n      endpoint: http://yaml-host:11434/v1\n      model: m1\n' +
        '    - name: w2\n      endpoint: http://gateway-host:4000/v1\n      model: m2\n',
      (p) => {
        const config = loadConfig(p);
        expect(config.provider.workers[0]?.endpoint).toBe('http://override-host:9999/v1');
        expect(config.provider.workers[1]?.endpoint).toBe('http://gateway-host:4000/v1');
      },
    );
  });
});
