/**
 * Phase 18 Task 7 — first-run detection tests.
 *
 * The lenient isFreshInstall criteria: any of (root missing, config.yaml
 * missing, providers section empty) counts as first-run. Plugins-not-
 * granted is NOT a fresh-install signal — bundled plugins ship in
 * pending-grant state and the boot card surfaces them honestly.
 */
import { describe, it, expect, beforeEach, afterEach } from 'vitest';
import { promises as fs } from 'node:fs';
import path from 'node:path';
import os from 'node:os';

import {
  isFreshInstall,
  printPostWizardTutorial,
} from '../../../cli/v4/setupWizard';
import { Display } from '../../../cli/v4/display';
import { SkinEngine } from '../../../cli/v4/skinEngine';
import {
  resolveAidenPaths,
  ensureAidenDirsExist,
} from '../../../core/v4/paths';

let tmpRoot: string;

beforeEach(async () => {
  tmpRoot = await fs.mkdtemp(path.join(os.tmpdir(), 'aiden-firstrun-'));
});
afterEach(async () => {
  await fs.rm(tmpRoot, { recursive: true, force: true });
});

describe('isFreshInstall', () => {
  it('61. returns true when paths.root does not exist', async () => {
    const fakeRoot = path.join(tmpRoot, 'never-created');
    const paths = resolveAidenPaths({ rootOverride: fakeRoot });
    expect(await isFreshInstall(paths)).toBe(true);
  });

  it('62. returns true when config.yaml is missing (root exists)', async () => {
    const paths = resolveAidenPaths({ rootOverride: tmpRoot });
    await ensureAidenDirsExist(paths);
    expect(await isFreshInstall(paths)).toBe(true);
  });

  it('63. returns true when config.yaml has empty providers section', async () => {
    const paths = resolveAidenPaths({ rootOverride: tmpRoot });
    await ensureAidenDirsExist(paths);
    await fs.writeFile(
      paths.configYaml,
      'model:\n  provider: groq\n  modelId: llama-3.3-70b-versatile\n',
      'utf8',
    );
    // No providers: at all.
    expect(await isFreshInstall(paths)).toBe(true);
  });

  it('64. returns true when providers: is present but empty', async () => {
    const paths = resolveAidenPaths({ rootOverride: tmpRoot });
    await ensureAidenDirsExist(paths);
    await fs.writeFile(
      paths.configYaml,
      'model:\n  provider: groq\n  modelId: x\nproviders:\n',
      'utf8',
    );
    expect(await isFreshInstall(paths)).toBe(true);
  });

  it('65. returns false when providers: has at least one entry', async () => {
    const paths = resolveAidenPaths({ rootOverride: tmpRoot });
    await ensureAidenDirsExist(paths);
    await fs.writeFile(
      paths.configYaml,
      [
        'model:',
        '  provider: groq',
        '  modelId: llama-3.3-70b-versatile',
        'providers:',
        '  groq:',
        '    apiKey: ${GROQ_API_KEY}',
      ].join('\n') + '\n',
      'utf8',
    );
    expect(await isFreshInstall(paths)).toBe(false);
  });

  it('66. returns false for a wizard-saved OAuth config (providers.<id>.auth=oauth)', async () => {
    const paths = resolveAidenPaths({ rootOverride: tmpRoot });
    await ensureAidenDirsExist(paths);
    await fs.writeFile(
      paths.configYaml,
      [
        'model:',
        '  provider: claude-pro',
        '  modelId: claude-opus-4-7',
        'providers:',
        '  claude-pro:',
        '    auth: oauth',
      ].join('\n') + '\n',
      'utf8',
    );
    expect(await isFreshInstall(paths)).toBe(false);
  });
});

describe('printPostWizardTutorial', () => {
  // Phase 22 Task 6 replaced the bullet-list tutorial with a rounded
  // box ("Setup Complete" + config map + re-run commands + Try CTA).
  // Detailed shape assertions live in tests/v4/cli/setupWizard.test.ts;
  // this file keeps the cross-cutting first-run / version-flow checks.
  function captureTutorial(version: string): string {
    const chunks: string[] = [];
    const stdout = {
      isTTY: false,
      write(s: string) {
        chunks.push(s);
        return true;
      },
    } as unknown as NodeJS.WriteStream;
    const display = new Display({
      skin: new SkinEngine({ forceMono: true }),
      stdout,
    });
    printPostWizardTutorial(display, version);
    return chunks.join('');
  }

  it('67. renders the boxed setup-complete summary', () => {
    const text = captureTutorial('4.0.0');
    expect(text).toMatch(/┌── Setup Complete /);
    expect(text).toMatch(/Aiden v4\.0\.0 is ready/);
    expect(text).toMatch(/All your files in:/);
    expect(text).toMatch(/Re-run setup:/);
    expect(text).toMatch(/Try: aiden/);
  });

  it('68. version string flows through verbatim', () => {
    expect(captureTutorial('4.1.7-beta')).toContain('Aiden v4.1.7-beta is ready');
  });
});
