import PptxGenJS from 'pptxgenjs';
import { ToolDef } from '../../../llm/openai-compat.js';
import type { ToolContext, ToolResult } from '../core.js';
import { resolveOutputPathWithin } from '../core.js';
import { readSlidesDoc, SlideStateSchemaError } from './state.js';
import { resolveTheme } from './themes.js';
import { renderSlide, type RenderExtra } from './layouts.js';

const DEFAULT_OUTPUT = 'output/slides.pptx';

export const BUILD_PPTX_DEF: ToolDef = {
  type: 'function',
  function: {
    name: 'BuildPptx',
    description:
      '蓄積された .slides.json を読み、pptxgenjs で .pptx を生成する。スライド組み立て後に最後に 1 度呼ぶ。詳細は ReadToolDoc({ name: "BuildPptx" })。',
    parameters: {
      type: 'object',
      properties: {
        output: { type: 'string', description: '出力先 (workspace 相対、output/ 配下)。既定 "output/slides.pptx"' },
      },
      additionalProperties: false,
    },
  },
};

export async function executeBuildPptx(
  input: Record<string, unknown>,
  ctx: ToolContext,
): Promise<ToolResult> {
  const outputRel = typeof input['output'] === 'string' && input['output']
    ? input['output'] as string : DEFAULT_OUTPUT;

  let outputAbs: string;
  try { outputAbs = resolveOutputPathWithin(ctx.workspacePath, outputRel, ['output']); }
  catch (e) { return { output: `BuildPptx error: ${(e as Error).message}`, isError: true }; }

  let doc;
  try { doc = readSlidesDoc(ctx.workspacePath); }
  catch (e) {
    const baseMsg = e instanceof SlideStateSchemaError ? e.message : (e as Error).message;
    return {
      output: `BuildPptx error: ${baseMsg}. Call ResetSlides() to discard the corrupt state and start over.`,
      isError: true,
    };
  }

  if (doc.slides.length === 0)
    return { output: 'BuildPptx error: no slides queued. Call AddSlide first.', isError: true };

  const theme = resolveTheme(doc.theme.preset, doc.theme.overrides);
  const pres = new PptxGenJS();
  pres.layout = 'LAYOUT_WIDE';

  const warnings: string[] = [];
  const extra: RenderExtra = { workspacePath: ctx.workspacePath, warnings };

  doc.slides.forEach((entry, i) => {
    const slide = pres.addSlide();
    renderSlide(slide, entry.layout, entry.content, theme, { index: i, total: doc.slides.length }, extra);
    if (entry.notes) slide.addNotes(entry.notes);
  });

  try {
    await pres.writeFile({ fileName: outputAbs });
  } catch (e) {
    return { output: `BuildPptx error: write failed: ${(e as Error).message}`, isError: true };
  }

  const fs = await import('fs');
  if (!fs.existsSync(outputAbs))
    return { output: `BuildPptx error: expected ${outputRel} not produced`, isError: true };
  const size = fs.statSync(outputAbs).size;

  const warnLine = warnings.length > 0 ? `\nWarnings:\n - ${warnings.join('\n - ')}` : '';
  return {
    output: `Built ${doc.slides.length} slide(s) to ${outputRel} (${size} bytes, theme=${doc.theme.preset}).${warnLine}`,
    isError: false,
  };
}
