import type { ParsedBlock, ParsedBook } from "../parsers/contracts.ts";
import type { OcrCheckpoint } from "./checkpoints.ts";
import { cleanOcrPages } from "./layout.ts";
import { classifyParagraph } from "../../domain/text.ts";

interface OcrBookInput {
  checkpoints: readonly OcrCheckpoint[];
  pageCount: number;
  title: string;
  author: string;
  pagesPerChapter?: number;
}

export function ocrCheckpointsToParsedBook(input: OcrBookInput): ParsedBook {
  if (!Number.isInteger(input.pageCount) || input.pageCount < 1) {
    throw new Error("PDF 页数必须是正整数。");
  }
  const pagesPerChapter = input.pagesPerChapter ?? 10;
  if (!Number.isInteger(pagesPerChapter) || pagesPerChapter < 1) {
    throw new Error("每章页数必须是正整数。");
  }

  const uniquePages = new Map<number, OcrCheckpoint>();
  for (const checkpoint of [...input.checkpoints].sort((left, right) => left.pageNumber - right.pageNumber)) {
    if (checkpoint.pageNumber >= 1 && checkpoint.pageNumber <= input.pageCount && !uniquePages.has(checkpoint.pageNumber)) {
      uniquePages.set(checkpoint.pageNumber, checkpoint);
    }
  }
  const cleanedPages = cleanOcrPages([...uniquePages.values()]);
  const groups = new Map<number, typeof cleanedPages>();
  for (const page of cleanedPages) {
    const group = Math.floor((page.pageNumber - 1) / pagesPerChapter);
    const values = groups.get(group) ?? [];
    values.push(page);
    groups.set(group, values);
  }

  const chapters = [...groups.entries()].map(([group, pages]) => {
    const nominalStart = group * pagesPerChapter + 1;
    const nominalEnd = Math.min(input.pageCount, nominalStart + pagesPerChapter - 1);
    const blocks: ParsedBlock[] = pages.flatMap((page) =>
      page.blocks
        .filter((block) => block.text.length > 0)
        .map((block, blockIndex) => {
          const classified = classifyParagraph(block.text);
          const kind: ParsedBlock["kind"] = classified === "empty" || classified === "readable"
            ? "prose"
            : classified;
          return {
            id: `ocr-page-${page.pageNumber}-block-${blockIndex + 1}`,
            text: block.text,
            kind,
            included: block.included,
            pageNumber: page.pageNumber,
            confidence: block.confidence,
            ...(block.warning ? { warning: block.warning } : {}),
          };
        }),
    );
    return {
      id: `ocr-pages-${nominalStart}-${nominalEnd}`,
      title: `第 ${nominalStart}–${nominalEnd} 页`,
      sourceHref: `pdf:pages:${nominalStart}-${nominalEnd}`,
      pageStart: pages[0].pageNumber,
      pageEnd: pages.at(-1)?.pageNumber ?? pages[0].pageNumber,
      blocks,
    };
  });

  return {
    format: "pdf",
    title: input.title,
    author: input.author,
    pageCount: input.pageCount,
    requiresOcr: true,
    chapters,
  };
}
