import { describe, it, expect, beforeEach, afterEach } from 'vitest';
import * as fs from 'fs';
import * as path from 'path';
import { tmpdir } from 'os';
import { fileURLToPath } from 'url';
import { executeTool, TOOL_DEFS } from './slide.js';

const __filename = fileURLToPath(import.meta.url);
const __dirname = path.dirname(__filename);

function ctx(ws: string) { return { workspacePath: ws } as any; }

describe('slide.ts dispatcher', () => {
  let ws: string;
  beforeEach(() => { ws = fs.mkdtempSync(path.join(tmpdir(), 'slide-disp-')); });
  afterEach(() => { fs.rmSync(ws, { recursive: true, force: true }); });

  it('exposes 4 tool defs', () => {
    expect(Object.keys(TOOL_DEFS).sort()).toEqual(['AddSlide', 'BuildPptx', 'ResetSlides', 'SetTheme']);
  });

  it('returns null for unknown tool name', async () => {
    expect(await executeTool('NotASlideTool', {}, ctx(ws))).toBeNull();
  });

  it('runs full SetTheme → AddSlide × 9 → BuildPptx flow with all Phase-1 layouts (no images)', async () => {
    const fixture = JSON.parse(fs.readFileSync(
      path.join(__dirname, '__fixtures__/slide/all-layouts.json'),
      'utf-8',
    )) as Array<{ layout: string; content: Record<string, unknown> }>;

    expect((await executeTool('SetTheme', { preset: 'corporate-blue' }, ctx(ws)))!.isError).toBeFalsy();

    for (const entry of fixture) {
      const r = await executeTool('AddSlide', entry, ctx(ws));
      expect(r!.isError, `${entry.layout}: ${r!.output}`).toBeFalsy();
    }

    const r = await executeTool('BuildPptx', {}, ctx(ws));
    expect(r!.isError).toBeFalsy();

    const JSZip = (await import('jszip')).default;
    const buf = fs.readFileSync(path.join(ws, 'output/slides.pptx'));
    const zip = await JSZip.loadAsync(buf);
    for (let i = 1; i <= fixture.length; i++) {
      expect(zip.file(`ppt/slides/slide${i}.xml`), `slide${i}.xml missing`).not.toBeNull();
    }
  });
});
