import { describe, it, expect } from 'vitest';
import { splitPieces, resolvePieceOptions } from './splitPieces';
import type { PieceSummary } from '../api';

function makePiece(name: string, source?: PieceSummary['source']): PieceSummary {
  return { name, description: 'test', source };
}

describe('splitPieces', () => {
  it('puts builtin pieces in defaults', () => {
    const pieces = [makePiece('chat', 'builtin'), makePiece('general', 'builtin')];
    const { defaults, customs } = splitPieces(pieces);
    expect(defaults).toHaveLength(2);
    expect(customs).toHaveLength(0);
  });

  it('puts user-custom pieces in customs', () => {
    const pieces = [makePiece('my-piece', 'user-custom')];
    const { defaults, customs } = splitPieces(pieces);
    expect(defaults).toHaveLength(0);
    expect(customs).toHaveLength(1);
    expect(customs[0].name).toBe('my-piece');
  });

  it('puts global-custom pieces in customs', () => {
    const pieces = [makePiece('global-piece', 'global-custom')];
    const { defaults, customs } = splitPieces(pieces);
    expect(defaults).toHaveLength(0);
    expect(customs).toHaveLength(1);
  });

  it('splits mixed list correctly', () => {
    const pieces = [
      makePiece('chat', 'builtin'),
      makePiece('general', 'builtin'),
      makePiece('my-chat', 'user-custom'),
      makePiece('chat', 'user-custom'), // same name as builtin, but still custom
    ];
    const { defaults, customs } = splitPieces(pieces);
    expect(defaults).toHaveLength(2);
    expect(customs).toHaveLength(2);
    expect(defaults.map(p => p.name)).toEqual(['chat', 'general']);
    expect(customs.map(p => p.name)).toEqual(['my-chat', 'chat']);
  });

  it('handles pieces with undefined source as custom', () => {
    const pieces = [makePiece('legacy')]; // no source
    const { defaults, customs } = splitPieces(pieces);
    expect(defaults).toHaveLength(0);
    expect(customs).toHaveLength(1);
  });

  it('returns empty arrays for empty input', () => {
    const { defaults, customs } = splitPieces([]);
    expect(defaults).toHaveLength(0);
    expect(customs).toHaveLength(0);
  });
});

describe('resolvePieceOptions', () => {
  it('returns unique names with no duplicates when all sources differ', () => {
    const pieces = [makePiece('chat', 'builtin'), makePiece('my-tool', 'user-custom')];
    const result = resolvePieceOptions(pieces);
    expect(result).toHaveLength(2);
    expect(result.map(p => p.name).sort()).toEqual(['chat', 'my-tool']);
  });

  it('user-custom wins over builtin for the same name', () => {
    const pieces = [makePiece('chat', 'builtin'), makePiece('chat', 'user-custom')];
    const result = resolvePieceOptions(pieces);
    expect(result).toHaveLength(1);
    expect(result[0].source).toBe('user-custom');
  });

  it('user-custom wins over global-custom for the same name', () => {
    const pieces = [makePiece('chat', 'global-custom'), makePiece('chat', 'user-custom')];
    const result = resolvePieceOptions(pieces);
    expect(result).toHaveLength(1);
    expect(result[0].source).toBe('user-custom');
  });

  it('global-custom wins over builtin for the same name', () => {
    const pieces = [makePiece('chat', 'builtin'), makePiece('chat', 'global-custom')];
    const result = resolvePieceOptions(pieces);
    expect(result).toHaveLength(1);
    expect(result[0].source).toBe('global-custom');
  });

  it('user-custom wins over both global-custom and builtin', () => {
    const pieces = [
      makePiece('chat', 'builtin'),
      makePiece('chat', 'global-custom'),
      makePiece('chat', 'user-custom'),
    ];
    const result = resolvePieceOptions(pieces);
    expect(result).toHaveLength(1);
    expect(result[0].source).toBe('user-custom');
  });

  it('de-duplicates only same-name entries, keeps different names', () => {
    const pieces = [
      makePiece('chat', 'builtin'),
      makePiece('general', 'builtin'),
      makePiece('chat', 'user-custom'),
      makePiece('my-tool', 'user-custom'),
    ];
    const result = resolvePieceOptions(pieces);
    expect(result).toHaveLength(3);
    const byName = Object.fromEntries(result.map(p => [p.name, p]));
    expect(byName['chat'].source).toBe('user-custom');
    expect(byName['general'].source).toBe('builtin');
    expect(byName['my-tool'].source).toBe('user-custom');
  });

  it('returns empty array for empty input', () => {
    expect(resolvePieceOptions([])).toHaveLength(0);
  });

  it('undefined source is treated as builtin priority (lowest)', () => {
    const pieces = [makePiece('chat', 'global-custom'), makePiece('chat', undefined)];
    const result = resolvePieceOptions(pieces);
    expect(result).toHaveLength(1);
    expect(result[0].source).toBe('global-custom');
  });
});
