import { describe, it, expect } from 'vitest';
import type { SessionConfigOption } from '@agentclientprotocol/sdk';
import {
  deriveModesFromACP,
  deriveModelDefinitionsFromACP,
  findThoughtLevelConfigId,
} from '../acp-derive.js';

describe('deriveModesFromACP', () => {
  it('prefers modeState.availableModes when present', () => {
    const { modes, currentModeId } = deriveModesFromACP(
      [{ id: 'fallback', label: 'Fallback' }],
      {
        currentModeId: 'plan',
        availableModes: [
          { id: 'plan', name: 'Plan', description: 'Read-only planning' },
          { id: 'code', name: 'Code' },
        ],
      },
    );

    expect(modes).toEqual([
      { id: 'plan', label: 'Plan', description: 'Read-only planning' },
      { id: 'code', label: 'Code', description: undefined },
    ]);
    expect(currentModeId).toBe('plan');
  });

  it('falls back to configOptions mode select', () => {
    const configOptions: SessionConfigOption[] = [
      {
        type: 'select',
        id: 'mode',
        category: 'mode',
        currentValue: 'auto',
        options: [
          { value: 'auto', name: 'Auto' },
          { value: 'manual', name: 'Manual', description: 'Ask first' },
        ],
      },
    ];

    const { modes, currentModeId } = deriveModesFromACP([], null, configOptions);

    expect(modes).toEqual([
      { id: 'auto', label: 'Auto', description: undefined },
      { id: 'manual', label: 'Manual', description: 'Ask first' },
    ]);
    expect(currentModeId).toBe('auto');
  });

  it('uses static fallback when no ACP mode data', () => {
    const fallback = [{ id: 'default', label: 'Default' }];
    const { modes, currentModeId } = deriveModesFromACP(fallback, null, null);

    expect(modes).toEqual(fallback);
    expect(currentModeId).toBeNull();
  });
});

describe('deriveModelDefinitionsFromACP', () => {
  it('maps availableModels with thought_level options', () => {
    const configOptions: SessionConfigOption[] = [
      {
        type: 'select',
        id: 'thought',
        category: 'thought_level',
        currentValue: 'medium',
        options: [
          { value: 'low', name: 'Low' },
          { value: 'medium', name: 'Medium' },
        ],
      },
    ];

    const models = deriveModelDefinitionsFromACP(
      {
        currentModelId: 'gpt-4',
        availableModels: [
          { modelId: 'gpt-4', name: 'GPT-4' },
          { modelId: 'gpt-4-mini', name: 'Mini', description: 'Cheaper' },
        ],
      },
      configOptions,
    );

    expect(models).toEqual([
      {
        id: 'gpt-4',
        label: 'GPT-4',
        description: undefined,
        isDefault: true,
        thinkingOptions: [
          { id: 'low', label: 'Low', isDefault: false },
          { id: 'medium', label: 'Medium', isDefault: true },
        ],
        defaultThinkingOptionId: 'medium',
      },
      {
        id: 'gpt-4-mini',
        label: 'Mini',
        description: 'Cheaper',
        isDefault: false,
        thinkingOptions: [
          { id: 'low', label: 'Low', isDefault: false },
          { id: 'medium', label: 'Medium', isDefault: true },
        ],
        defaultThinkingOptionId: 'medium',
      },
    ]);
  });

  it('falls back to model select config when no availableModels', () => {
    const configOptions: SessionConfigOption[] = [
      {
        type: 'select',
        id: 'model',
        category: 'model',
        currentValue: 'sonnet',
        options: [
          { value: 'sonnet', name: 'Sonnet' },
          { value: 'opus', name: 'Opus' },
        ],
      },
    ];

    const models = deriveModelDefinitionsFromACP(null, configOptions);

    expect(models).toEqual([
      { id: 'sonnet', label: 'Sonnet', isDefault: true, defaultThinkingOptionId: undefined },
      { id: 'opus', label: 'Opus', isDefault: false, defaultThinkingOptionId: undefined },
    ]);
  });
});

describe('findThoughtLevelConfigId', () => {
  it('returns thought_level select id', () => {
    const configOptions: SessionConfigOption[] = [
      {
        type: 'select',
        id: 'effort',
        category: 'thought_level',
        currentValue: 'high',
        options: [{ value: 'high', name: 'High' }],
      },
    ];

    expect(findThoughtLevelConfigId(configOptions)).toBe('effort');
  });

  it('returns null when missing', () => {
    expect(findThoughtLevelConfigId(null)).toBeNull();
  });
});
