import { describe, it, expect, beforeEach, afterEach } from 'vitest';
import * as fs from 'fs';
import * as path from 'path';
import { tmpdir } from 'os';
import { executeBuildPptx } from './build-pptx.js';
import { setTheme, appendSlide } from './state.js';

const ctx = (ws: string) => ({ workspacePath: ws } as any);

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

  it('errors when no slides queued', async () => {
    const r = await executeBuildPptx({}, ctx(ws));
    expect(r.isError).toBe(true);
    expect(r.output).toMatch(/no slides/i);
  });

  it('builds a 3-slide deck with default output path', async () => {
    setTheme(ws, { preset: 'minimal-mono', overrides: {} });
    appendSlide(ws, { layout: 'title', content: { title: 'Hi' }, notes: null });
    appendSlide(ws, { layout: 'bullets', content: { title: 'B', bullets: ['a', 'b'] }, notes: null });
    appendSlide(ws, { layout: 'closing', content: {}, notes: null });
    const r = await executeBuildPptx({}, ctx(ws));
    expect(r.isError).toBeFalsy();
    const out = path.join(ws, 'output/slides.pptx');
    expect(fs.existsSync(out)).toBe(true);
    expect(fs.statSync(out).size).toBeGreaterThan(0);
  });

  it('uses default theme minimal-mono when SetTheme was never called', async () => {
    appendSlide(ws, { layout: 'title', content: { title: 'Default' }, notes: null });
    const r = await executeBuildPptx({}, ctx(ws));
    expect(r.isError).toBeFalsy();
  });

  it('rejects output outside output/', async () => {
    appendSlide(ws, { layout: 'title', content: { title: 'X' }, notes: null });
    const r = await executeBuildPptx({ output: '../escape.pptx' }, ctx(ws));
    expect(r.isError).toBe(true);
  });

  it('emits warning when image is missing', async () => {
    appendSlide(ws, {
      layout: 'image-right',
      content: { title: 'X', body: 'hi', image: { path: 'input/missing.png' } },
      notes: null,
    });
    const r = await executeBuildPptx({}, ctx(ws));
    expect(r.isError).toBeFalsy();
    expect(r.output).toMatch(/missing|not found/i);
  });

  it('errors on corrupt .slides.json with ResetSlides suggestion', async () => {
    fs.mkdirSync(path.join(ws, 'output'), { recursive: true });
    fs.writeFileSync(path.join(ws, 'output/.slides.json'), '{not json}');
    const r = await executeBuildPptx({}, ctx(ws));
    expect(r.isError).toBe(true);
    expect(r.output).toMatch(/ResetSlides/);
  });
});
