import { describe, it, expect, vi, afterEach } from 'vitest';
import type { WizardState } from '../types.js';
import { providerSetupStage } from './provider-setup.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(''),
    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('providerSetupStage', () => {
  const originalEnv = { ...process.env };

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

  it('detects Anthropic key from prefix in headless mode', async () => {
    process.env['MOSAIC_ASSUME_YES'] = '1';
    process.env['MOSAIC_ANTHROPIC_API_KEY'] = 'sk-ant-api03-test123';
    const state = makeState();
    const p = buildPrompter();

    await providerSetupStage(p, state);

    expect(state.providerKey).toBe('sk-ant-api03-test123');
    expect(state.providerType).toBe('anthropic');
  });

  it('detects OpenAI key from prefix in headless mode', async () => {
    process.env['MOSAIC_ASSUME_YES'] = '1';
    process.env['MOSAIC_OPENAI_API_KEY'] = 'sk-proj-test123';
    const state = makeState();
    const p = buildPrompter();

    await providerSetupStage(p, state);

    expect(state.providerKey).toBe('sk-proj-test123');
    expect(state.providerType).toBe('openai');
  });

  it('sets provider type to none when no key is provided in headless mode', async () => {
    process.env['MOSAIC_ASSUME_YES'] = '1';
    delete process.env['MOSAIC_ANTHROPIC_API_KEY'];
    delete process.env['MOSAIC_OPENAI_API_KEY'];
    const state = makeState();
    const p = buildPrompter();

    await providerSetupStage(p, state);

    expect(state.providerKey).toBeUndefined();
    expect(state.providerType).toBe('none');
  });

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

    const state = makeState();
    const p = buildPrompter({
      text: vi.fn().mockResolvedValue('sk-ant-api03-interactive'),
    });

    await providerSetupStage(p, state);

    expect(p.text).toHaveBeenCalled();
    expect(state.providerKey).toBe('sk-ant-api03-interactive');
    expect(state.providerType).toBe('anthropic');

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

  it('handles empty key 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({
      text: vi.fn().mockResolvedValue(''),
    });

    await providerSetupStage(p, state);

    expect(state.providerType).toBe('none');
    expect(state.providerKey).toBeUndefined();

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