import { describe, it, expect, beforeEach, afterEach } from 'vitest';
import * as fs from 'fs';
import * as path from 'path';
import { tmpdir } from 'os';
import {
  readSlidesDoc, writeSlidesDoc, appendSlide,
  setTheme, resetSlides, DEFAULT_DOC,
} from './state.js';

function tmpWorkspace(): string {
  return fs.mkdtempSync(path.join(tmpdir(), 'slide-state-'));
}

describe('state.ts', () => {
  let ws: string;
  beforeEach(() => { ws = tmpWorkspace(); });
  afterEach(() => { fs.rmSync(ws, { recursive: true, force: true }); });

  it('readSlidesDoc returns DEFAULT_DOC when file does not exist', () => {
    expect(readSlidesDoc(ws)).toEqual(DEFAULT_DOC);
  });

  it('writeSlidesDoc creates output/.slides.json', () => {
    writeSlidesDoc(ws, DEFAULT_DOC);
    const raw = fs.readFileSync(path.join(ws, 'output/.slides.json'), 'utf-8');
    expect(JSON.parse(raw)).toEqual(DEFAULT_DOC);
  });

  it('appendSlide pushes to slides array', () => {
    appendSlide(ws, { layout: 'title', content: { title: 'Hi' }, notes: null });
    appendSlide(ws, { layout: 'bullets', content: { title: 'B', bullets: ['x'] }, notes: 'n' });
    const doc = readSlidesDoc(ws);
    expect(doc.slides).toHaveLength(2);
    expect(doc.slides[0].layout).toBe('title');
    expect(doc.slides[1].notes).toBe('n');
  });

  it('setTheme replaces theme, preserves slides[]', () => {
    appendSlide(ws, { layout: 'title', content: { title: 'A' }, notes: null });
    setTheme(ws, { preset: 'dark', overrides: { primary: '#fff' } });
    const doc = readSlidesDoc(ws);
    expect(doc.theme.preset).toBe('dark');
    expect(doc.theme.overrides.primary).toBe('#fff');
    expect(doc.slides).toHaveLength(1);
  });

  it('resetSlides clears slides[], preserves theme', () => {
    setTheme(ws, { preset: 'vibrant', overrides: {} });
    appendSlide(ws, { layout: 'title', content: { title: 'A' }, notes: null });
    resetSlides(ws);
    const doc = readSlidesDoc(ws);
    expect(doc.slides).toHaveLength(0);
    expect(doc.theme.preset).toBe('vibrant');
  });

  it('readSlidesDoc throws SchemaError when version mismatch', () => {
    fs.mkdirSync(path.join(ws, 'output'), { recursive: true });
    fs.writeFileSync(
      path.join(ws, 'output/.slides.json'),
      JSON.stringify({ version: 2, theme: {}, slides: [] }),
    );
    expect(() => readSlidesDoc(ws)).toThrow(/version/i);
  });

  it('readSlidesDoc throws SchemaError when slides is not array', () => {
    fs.mkdirSync(path.join(ws, 'output'), { recursive: true });
    fs.writeFileSync(
      path.join(ws, 'output/.slides.json'),
      JSON.stringify({ version: 1, theme: { preset: 'dark', overrides: {} }, slides: 'x' }),
    );
    expect(() => readSlidesDoc(ws)).toThrow(/slides/i);
  });
});
