import { describe, it, expect, vi } from 'vitest';
import { buildResolvedRegistry } from '../provider-config-registry.js';
import { PROVIDERS } from '../provider-registry.js';
import type { CoderProvidersFile } from '../provider-config.js';

describe('buildResolvedRegistry', () => {
  it('applies a built-in override (goose label)', () => {
    const config: CoderProvidersFile = { providers: { goose: { label: 'Goosey' } } };
    const reg = buildResolvedRegistry(PROVIDERS, config);
    const goose = reg.get('goose');
    expect(goose).toBeDefined();
    expect(goose!.label).toBe('Goosey');
    expect(goose!.configLabel).toBe('Goosey');
    expect(goose!.enabled).toBe(true);
    expect(goose!.isBuiltin).toBe(true);
    expect(goose!.isCustomAcp).toBe(false);
  });

  it('adds a custom ACP entry (extends:acp + label + command)', () => {
    const config: CoderProvidersFile = {
      providers: {
        'amp-acp': { extends: 'acp', label: 'Amp', description: 'ACP wrapper', command: ['amp-acp', '--acp'], env: { AMP: '1' } },
      },
    };
    const reg = buildResolvedRegistry(PROVIDERS, config);
    const amp = reg.get('amp-acp');
    expect(amp).toBeDefined();
    expect(amp!.isCustomAcp).toBe(true);
    expect(amp!.isBuiltin).toBe(false);
    expect(amp!.transport).toBe('acp');
    expect(amp!.modelSource).toBe('probe');
    expect(amp!.launchCommand).toEqual(['amp-acp', '--acp']);
    expect(amp!.env).toEqual({ AMP: '1' });
    expect(amp!.enabled).toBe(true);
  });

  it('keeps a disabled built-in in the registry flagged disabled (goose)', () => {
    const config: CoderProvidersFile = { providers: { goose: { enabled: false } } };
    const reg = buildResolvedRegistry(PROVIDERS, config);
    expect(reg.has('goose')).toBe(true);
    expect(reg.get('goose')!.enabled).toBe(false);
  });

  it('skips a custom id without extends (no throw)', () => {
    const config: CoderProvidersFile = { providers: { weird: { label: 'Weird', command: ['weird'] } } };
    const warn = vi.spyOn(console, 'warn').mockImplementation(() => {});
    const reg = buildResolvedRegistry(PROVIDERS, config);
    expect(reg.has('weird')).toBe(false);
    // built-ins untouched
    expect(reg.size).toBe(PROVIDERS.length);
    expect(warn).toHaveBeenCalled();
    warn.mockRestore();
  });

  it('ignores enabled:false on boocode and warns', () => {
    const config: CoderProvidersFile = { providers: { boocode: { enabled: false } } };
    const warn = vi.spyOn(console, 'warn').mockImplementation(() => {});
    const reg = buildResolvedRegistry(PROVIDERS, config);
    expect(reg.get('boocode')!.enabled).toBe(true);
    expect(warn).toHaveBeenCalled();
    warn.mockRestore();
  });

  it('carries config models + additionalModels onto built-in and custom defs', () => {
    const reg = buildResolvedRegistry(PROVIDERS, {
      providers: {
        claude: { models: [{ id: 'claude-opus-4-8', label: 'Opus 4.8' }] },
        'amp-acp': {
          extends: 'acp',
          label: 'Amp',
          command: ['amp-acp'],
          additionalModels: [{ id: 'amp-1', label: 'Amp 1' }],
        },
      },
    });
    expect(reg.get('claude')!.configModels).toEqual([{ id: 'claude-opus-4-8', label: 'Opus 4.8' }]);
    expect(reg.get('amp-acp')!.configAdditionalModels).toEqual([{ id: 'amp-1', label: 'Amp 1' }]);
  });

  it('REGRESSION: empty config returns exactly the built-ins, all enabled', () => {
    const reg = buildResolvedRegistry(PROVIDERS, { providers: {} });
    expect(reg.size).toBe(PROVIDERS.length);
    expect([...reg.keys()]).toEqual(PROVIDERS.map((p) => p.name));
    for (const def of PROVIDERS) {
      const r = reg.get(def.name)!;
      expect(r.enabled).toBe(true);
      expect(r.isBuiltin).toBe(true);
      expect(r.isCustomAcp).toBe(false);
      expect(r.launchCommand).toBeNull();
      expect(r.label).toBe(def.label);
    }
  });
});
