import { describe, it, expect, beforeEach, afterEach } from 'vitest';
import { mkdtempSync, mkdirSync, writeFileSync, rmSync } from 'node:fs';
import { join } from 'node:path';
import { tmpdir } from 'node:os';
import { HeadlessPrompter } from '../../src/prompter/headless-prompter.js';
import { detectInstallStage } from '../../src/stages/detect-install.js';
import type { WizardState } from '../../src/types.js';
import type { ConfigService } from '../../src/config/config-service.js';

function createState(mosaicHome: string): WizardState {
  return {
    mosaicHome,
    sourceDir: mosaicHome,
    mode: 'quick',
    installAction: 'fresh',
    soul: {},
    user: {},
    tools: {},
    runtimes: { detected: [], mcpConfigured: false },
    selectedSkills: [],
  };
}

const mockConfig: ConfigService = {
  readSoul: async () => ({ agentName: 'TestAgent' }),
  readUser: async () => ({ userName: 'TestUser' }),
  readTools: async () => ({}),
  writeSoul: async () => {},
  writeUser: async () => {},
  writeTools: async () => {},
  syncFramework: async () => {},
};

describe('detectInstallStage', () => {
  let tmpDir: string;

  beforeEach(() => {
    tmpDir = mkdtempSync(join(tmpdir(), 'mosaic-test-'));
  });

  afterEach(() => {
    rmSync(tmpDir, { recursive: true, force: true });
  });

  it('sets fresh for empty directory', async () => {
    const p = new HeadlessPrompter({});
    const state = createState(join(tmpDir, 'nonexistent'));
    await detectInstallStage(p, state, mockConfig);

    expect(state.installAction).toBe('fresh');
  });

  it('detects existing install and offers choices', async () => {
    // Create a mock existing install
    mkdirSync(join(tmpDir, 'bin'), { recursive: true });
    writeFileSync(join(tmpDir, 'AGENTS.md'), '# Test');
    writeFileSync(join(tmpDir, 'SOUL.md'), 'You are **Jarvis** in this session.');

    const p = new HeadlessPrompter({
      'What would you like to do?': 'keep',
    });
    const state = createState(tmpDir);
    await detectInstallStage(p, state, mockConfig);

    expect(state.installAction).toBe('keep');
    expect(state.soul.agentName).toBe('TestAgent');
  });

  it('pre-populates state when reconfiguring', async () => {
    mkdirSync(join(tmpDir, 'bin'), { recursive: true });
    writeFileSync(join(tmpDir, 'SOUL.md'), 'You are **Jarvis** in this session.');
    writeFileSync(join(tmpDir, 'USER.md'), '**Name:** TestUser');

    const p = new HeadlessPrompter({
      'What would you like to do?': 'reconfigure',
    });
    const state = createState(tmpDir);
    await detectInstallStage(p, state, mockConfig);

    expect(state.installAction).toBe('reconfigure');
    // Existing values loaded as defaults for reconfiguration
    expect(state.soul.agentName).toBe('TestAgent');
    expect(state.user.userName).toBe('TestUser');
  });

  it('does not pre-populate state on fresh reset', async () => {
    mkdirSync(join(tmpDir, 'bin'), { recursive: true });
    writeFileSync(join(tmpDir, 'SOUL.md'), 'You are **Jarvis** in this session.');

    const p = new HeadlessPrompter({
      'What would you like to do?': 'reset',
    });
    const state = createState(tmpDir);
    await detectInstallStage(p, state, mockConfig);

    expect(state.installAction).toBe('reset');
    // Reset should NOT load existing values
    expect(state.soul.agentName).toBeUndefined();
  });
});
