import { describe, it, expect, vi, afterEach } from 'vitest';
import type { WizardState } from '../types.js';
import { agentIntentStage } from './agent-intent.js';

function buildPrompter(overrides: Partial<Record<string, unknown>> = {}) {
  return {
    intro: vi.fn(),
    outro: vi.fn(),
    note: vi.fn(),
    log: vi.fn(),
    warn: vi.fn(),
    text: vi.fn().mockResolvedValue('Mosaic'),
    confirm: vi.fn().mockResolvedValue(false),
    select: vi.fn().mockResolvedValue('general'),
    multiselect: vi.fn(),
    groupMultiselect: vi.fn(),
    spinner: vi.fn().mockReturnValue({ update: vi.fn(), stop: vi.fn() }),
    separator: vi.fn(),
    ...overrides,
  };
}

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

describe('agentIntentStage', () => {
  const originalEnv = { ...process.env };

  afterEach(() => {
    process.env = { ...originalEnv };
  });

  it('uses default intent and name in headless mode', async () => {
    process.env['MOSAIC_ASSUME_YES'] = '1';
    delete process.env['MOSAIC_AGENT_INTENT'];
    delete process.env['MOSAIC_AGENT_NAME'];
    const state = makeState();
    const p = buildPrompter();

    await agentIntentStage(p, state);

    expect(state.agentIntent).toBe('general');
    expect(state.soul.agentName).toBe('Mosaic');
  });

  it('reads intent from MOSAIC_AGENT_INTENT env var', async () => {
    process.env['MOSAIC_ASSUME_YES'] = '1';
    process.env['MOSAIC_AGENT_INTENT'] = 'software-dev';
    delete process.env['MOSAIC_AGENT_NAME'];
    const state = makeState();
    const p = buildPrompter();

    await agentIntentStage(p, state);

    expect(state.agentIntent).toBe('software-dev');
    expect(state.soul.agentName).toBe('Forge');
  });

  it('honors MOSAIC_AGENT_NAME env var override', async () => {
    process.env['MOSAIC_ASSUME_YES'] = '1';
    process.env['MOSAIC_AGENT_INTENT'] = 'devops';
    process.env['MOSAIC_AGENT_NAME'] = 'MyBot';
    const state = makeState();
    const p = buildPrompter();

    await agentIntentStage(p, state);

    expect(state.agentIntent).toBe('devops');
    expect(state.soul.agentName).toBe('MyBot');
  });

  it('falls back to general for unknown intent values', async () => {
    process.env['MOSAIC_ASSUME_YES'] = '1';
    process.env['MOSAIC_AGENT_INTENT'] = 'nonexistent';
    delete process.env['MOSAIC_AGENT_NAME'];
    const state = makeState();
    const p = buildPrompter();

    await agentIntentStage(p, state);

    expect(state.agentIntent).toBe('general');
    expect(state.soul.agentName).toBe('Mosaic');
  });

  it('prompts for intent and name in interactive mode', async () => {
    delete process.env['MOSAIC_ASSUME_YES'];
    const origIsTTY = process.stdin.isTTY;
    Object.defineProperty(process.stdin, 'isTTY', { value: true, configurable: true });

    const state = makeState();
    const p = buildPrompter({
      select: vi.fn().mockResolvedValue('research'),
      text: vi.fn().mockResolvedValue('Atlas'),
    });

    await agentIntentStage(p, state);

    expect(state.agentIntent).toBe('research');
    expect(state.soul.agentName).toBe('Atlas');
    expect(p.select).toHaveBeenCalled();
    expect(p.text).toHaveBeenCalled();

    Object.defineProperty(process.stdin, 'isTTY', { value: origIsTTY, configurable: true });
  });

  it('maps content intent to Muse suggested name', async () => {
    process.env['MOSAIC_ASSUME_YES'] = '1';
    process.env['MOSAIC_AGENT_INTENT'] = 'content';
    delete process.env['MOSAIC_AGENT_NAME'];
    const state = makeState();
    const p = buildPrompter();

    await agentIntentStage(p, state);

    expect(state.agentIntent).toBe('content');
    expect(state.soul.agentName).toBe('Muse');
  });
});
