import { describe, it, expect, afterEach } from 'vitest';
import type { MenuSection } from '../types.js';
import { detectProviderType, INTENT_PRESETS } from '../constants.js';

/**
 * Tests for the drill-down menu system and its supporting utilities.
 *
 * The menu loop itself is in wizard.ts and is hard to unit test in isolation
 * because it orchestrates many async stages. These tests verify the building
 * blocks: provider detection, intent presets, and the WizardState shape.
 */

describe('detectProviderType', () => {
  it('detects Anthropic from sk-ant- prefix', () => {
    expect(detectProviderType('sk-ant-api03-abc123')).toBe('anthropic');
  });

  it('detects OpenAI from sk- prefix', () => {
    expect(detectProviderType('sk-proj-abc123')).toBe('openai');
  });

  it('returns none for empty string', () => {
    expect(detectProviderType('')).toBe('none');
  });

  it('returns none for unrecognized prefix', () => {
    expect(detectProviderType('gsk_abc123')).toBe('none');
  });
});

describe('INTENT_PRESETS', () => {
  it('has all expected intent categories', () => {
    expect(Object.keys(INTENT_PRESETS)).toEqual(
      expect.arrayContaining([
        'general',
        'software-dev',
        'devops',
        'research',
        'content',
        'custom',
      ]),
    );
  });

  it('each preset has label, hint, and suggestedName', () => {
    for (const [key, preset] of Object.entries(INTENT_PRESETS)) {
      expect(preset.label, `${key}.label`).toBeTruthy();
      expect(preset.hint, `${key}.hint`).toBeTruthy();
      expect(preset.suggestedName, `${key}.suggestedName`).toBeTruthy();
    }
  });

  it('maps software-dev to Forge', () => {
    expect(INTENT_PRESETS['software-dev']?.suggestedName).toBe('Forge');
  });

  it('maps devops to Sentinel', () => {
    expect(INTENT_PRESETS['devops']?.suggestedName).toBe('Sentinel');
  });
});

describe('WizardState completedSections', () => {
  it('tracks completed sections as a Set', () => {
    const completed = new Set<MenuSection>();
    completed.add('providers');
    completed.add('identity');

    expect(completed.has('providers')).toBe(true);
    expect(completed.has('identity')).toBe(true);
    expect(completed.has('skills')).toBe(false);
    expect(completed.size).toBe(2);
  });
});

describe('headless backward compat', () => {
  const originalEnv = { ...process.env };

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

  it('MOSAIC_ASSUME_YES=1 triggers headless path', () => {
    process.env['MOSAIC_ASSUME_YES'] = '1';
    const isHeadless = process.env['MOSAIC_ASSUME_YES'] === '1' || !process.stdin.isTTY;
    expect(isHeadless).toBe(true);
  });

  it('non-TTY triggers headless path', () => {
    delete process.env['MOSAIC_ASSUME_YES'];
    // In test environments, process.stdin.isTTY is typically undefined (falsy)
    const isHeadless = process.env['MOSAIC_ASSUME_YES'] === '1' || !process.stdin.isTTY;
    expect(isHeadless).toBe(true);
  });

  it('all headless env vars are recognized', () => {
    // This test documents the expected env vars for headless installs.
    const headlessVars = [
      'MOSAIC_ASSUME_YES',
      'MOSAIC_ADMIN_NAME',
      'MOSAIC_ADMIN_EMAIL',
      'MOSAIC_ADMIN_PASSWORD',
      'MOSAIC_GATEWAY_PORT',
      'MOSAIC_HOSTNAME',
      'MOSAIC_CORS_ORIGIN',
      'MOSAIC_STORAGE_TIER',
      'MOSAIC_DATABASE_URL',
      'MOSAIC_VALKEY_URL',
      'MOSAIC_ANTHROPIC_API_KEY',
      'MOSAIC_AGENT_NAME',
      'MOSAIC_AGENT_INTENT',
    ];

    // Just verify none of them throw when accessed
    for (const v of headlessVars) {
      expect(() => process.env[v]).not.toThrow();
    }
  });
});
