import { describe, it, expect } from 'vitest';
import {
  ALL_TOOLS,
  CORE_TOOL_NAMES,
  STANDARD_TOOL_NAMES,
  TOOLS_BY_NAME,
  resolveToolTier,
} from '../tools.js';

describe('ALL_TOOLS registry', () => {
  // v1.13.3: tools must be alpha-sorted at module load. llama.cpp's prompt
  // cache hits on byte-identical prefixes; the tool list lives near the
  // top of the system prompt, so any order drift invalidates every cached
  // turn. The registry sort is the single source of truth; downstream
  // helpers (toolJsonSchemas, TOOLS_BY_NAME, buildAiTools) inherit it.
  it('exports tools in alphabetical order by name', () => {
    const names = ALL_TOOLS.map((t) => t.name);
    expect(names).toEqual([...names].sort((a, b) => a.localeCompare(b)));
  });
});

describe('resolveToolTier (v1.13.15-tools)', () => {
  it('returns CORE tools for tier=core', () => {
    expect(resolveToolTier('core')).toEqual(CORE_TOOL_NAMES);
  });

  it('returns STANDARD tools for tier=standard', () => {
    const result = resolveToolTier('standard');
    expect(result.length).toBe(STANDARD_TOOL_NAMES.length);
    expect(result.length).toBeGreaterThan(CORE_TOOL_NAMES.length);
    // STANDARD is a strict superset of CORE.
    expect(result).toEqual(expect.arrayContaining([...CORE_TOOL_NAMES]));
  });

  it('returns ALL tool names for tier=all', () => {
    expect(resolveToolTier('all').length).toBe(ALL_TOOLS.length);
  });

  it('defaults to all when env var is undefined', () => {
    expect(resolveToolTier(undefined).length).toBe(ALL_TOOLS.length);
  });

  it('is case-insensitive', () => {
    expect(resolveToolTier('CORE')).toEqual(CORE_TOOL_NAMES);
    expect(resolveToolTier('Standard').length).toBe(STANDARD_TOOL_NAMES.length);
  });

  it('falls back to all for unknown tier strings', () => {
    expect(resolveToolTier('bogus').length).toBe(ALL_TOOLS.length);
  });
});

describe('CORE_TOOL_NAMES + STANDARD_TOOL_NAMES validation', () => {
  // The module-load validation in tools.ts throws if a tier references a
  // tool that doesn't exist in TOOLS_BY_NAME. These tests double-check that
  // invariant from the consumer side so a future tier-list edit can't smuggle
  // in a typo without a test failure.
  it('every CORE name exists in TOOLS_BY_NAME', () => {
    for (const name of CORE_TOOL_NAMES) {
      expect(TOOLS_BY_NAME[name], `CORE references unknown tool '${name}'`).toBeDefined();
    }
  });

  it('every STANDARD name exists in TOOLS_BY_NAME', () => {
    for (const name of STANDARD_TOOL_NAMES) {
      expect(TOOLS_BY_NAME[name], `STANDARD references unknown tool '${name}'`).toBeDefined();
    }
  });

  it('CORE is a subset of STANDARD', () => {
    const standardSet = new Set<string>(STANDARD_TOOL_NAMES);
    for (const name of CORE_TOOL_NAMES) {
      expect(standardSet.has(name), `'${name}' is in CORE but not STANDARD`).toBe(true);
    }
  });
});
