import { describe, expect, it } from 'vitest';
import { buildInstallerPlan } from './planner.js';

describe('buildInstallerPlan', () => {
  it('plans brew and node installers when required binaries are present', () => {
    const plan = buildInstallerPlan(
      [
        { type: 'brew', packages: ['jq'] },
        { type: 'node', packages: ['typescript'] },
      ],
      {
        hasBinary: (name) => name === 'brew' || name === 'pnpm',
      },
    );

    expect(plan.mode).toBe('dry-run');
    expect(plan.steps).toEqual([
      { installerType: 'brew', command: 'brew install jq' },
      { installerType: 'node', command: 'pnpm add -g typescript' },
    ]);
    expect(plan.skipped).toEqual([]);
  });

  it('skips installers when required package managers are missing', () => {
    const plan = buildInstallerPlan(
      [
        { type: 'brew', packages: ['wget'] },
        { type: 'node', packages: ['tsx'] },
        { type: 'go', packages: ['golang.org/x/tools/cmd/stringer'] },
      ],
      {
        hasBinary: () => false,
      },
    );

    expect(plan.steps).toEqual([]);
    expect(plan.skipped).toEqual([
      { installerType: 'brew', reason: 'brew not available in PATH' },
      { installerType: 'node', reason: 'neither pnpm nor npm available in PATH' },
      { installerType: 'go', reason: 'go not available in PATH' },
    ]);
  });

  it('expands go packages and includes download installers', () => {
    const plan = buildInstallerPlan(
      [
        { type: 'go', packages: ['example.com/tool/a', 'example.com/tool/b'] },
        { type: 'download', url: 'https://example.com/tool.tgz', destination: '/tmp/tool.tgz' },
      ],
      {
        hasBinary: (name) => name === 'go',
      },
    );

    expect(plan.steps).toEqual([
      { installerType: 'go', command: 'go install example.com/tool/a@latest' },
      { installerType: 'go', command: 'go install example.com/tool/b@latest' },
      { installerType: 'download', command: 'download https://example.com/tool.tgz -> /tmp/tool.tgz' },
    ]);
    expect(plan.skipped).toEqual([]);
  });
});
