import { describe, it, expect } from 'vitest';
import { execFileSync } from 'node:child_process';
import { mkdtempSync, copyFileSync, readFileSync, statSync, existsSync } from 'node:fs';
import { tmpdir } from 'node:os';
import { join, resolve } from 'node:path';
import { parse as parseYaml } from 'yaml';

const REPO = resolve(import.meta.dirname, '..');
const SETUP = join(REPO, 'scripts', 'setup.mjs');

// Run the wizard in --yes mode inside `dir`. extraArgs lets a case add --force.
function runYes(dir, env, extraArgs = []) {
  execFileSync('node', [SETUP, '--yes', ...extraArgs], {
    cwd: dir, env: { ...process.env, ...env }, stdio: 'pipe',
  });
}

describe('setup.mjs --yes smoke', () => {
  it('writes a minimal config.yaml (0600) and .env PORT for a direct setup', () => {
    const dir = mkdtempSync(join(tmpdir(), 'setup-smoke-'));
    copyFileSync(join(REPO, 'config.yaml.example'), join(dir, 'config.yaml.example'));
    runYes(dir, { SETUP_LLM_ENDPOINT: 'http://localhost:11434/v1', SETUP_MODEL: 'qwen3:32b', PORT: '9876' });

    const cfg = parseYaml(readFileSync(join(dir, 'config.yaml'), 'utf-8'));
    expect(cfg.config_version).toBe(2);
    expect(cfg.llm.workers).toHaveLength(1);
    expect(cfg.llm.workers[0]).toMatchObject({ connection_type: 'direct', endpoint: 'http://localhost:11434/v1', model: 'qwen3:32b' });
    expect(readFileSync(join(dir, '.env'), 'utf-8')).toContain('PORT=9876');
    if (process.platform !== 'win32') {
      expect((statSync(join(dir, 'config.yaml')).mode & 0o777).toString(8)).toBe('600');
    }
  });

  it('writes api_key for a gateway setup and backs up an existing config (with --force)', () => {
    const dir = mkdtempSync(join(tmpdir(), 'setup-smoke-'));
    copyFileSync(join(REPO, 'config.yaml.example'), join(dir, 'config.yaml')); // pre-existing -> forces backup
    runYes(dir, {
      SETUP_CONNECTION_TYPE: 'aao_gateway', SETUP_LLM_ENDPOINT: 'http://g:9876/v1',
      SETUP_LLM_API_KEY: 'sk-aao-secret123', SETUP_MODEL: 'm',
    }, ['--force']);

    const cfg = parseYaml(readFileSync(join(dir, 'config.yaml'), 'utf-8'));
    expect(cfg.llm.workers[0].api_key).toBe('sk-aao-secret123');
    expect(existsSync(join(dir, 'config.yaml.bak'))).toBe(true);
    if (process.platform !== 'win32') {
      expect((statSync(join(dir, 'config.yaml.bak')).mode & 0o777).toString(8)).toBe('600');
    }
  });

  it('exits non-zero when required env is missing', () => {
    const dir = mkdtempSync(join(tmpdir(), 'setup-smoke-'));
    expect(() => runYes(dir, { SETUP_LLM_ENDPOINT: 'http://h/v1' /* no SETUP_MODEL */ })).toThrow();
  });

  it('refuses to overwrite an existing config without --force', () => {
    const dir = mkdtempSync(join(tmpdir(), 'setup-smoke-'));
    copyFileSync(join(REPO, 'config.yaml.example'), join(dir, 'config.yaml'));
    expect(() => runYes(dir, { SETUP_LLM_ENDPOINT: 'http://h/v1', SETUP_MODEL: 'm' })).toThrow();
  });
});
