import type {
  ChapterInput,
  ChapterRepository,
  ChapterSegmentInput,
} from "./repositories/chapters.ts";

function object(value: unknown, label: string): Record<string, unknown> {
  if (!value || typeof value !== "object" || Array.isArray(value)) {
    throw new Error(`${label}必须是对象。`);
  }
  return value as Record<string, unknown>;
}

function string(value: unknown, label: string): string {
  if (typeof value !== "string") throw new Error(`${label}必须是文字。`);
  return value;
}

function number(value: unknown, label: string): number {
  if (typeof value !== "number") throw new Error(`${label}必须是数字。`);
  return value;
}

function nullableNumber(value: unknown, label: string): number | null {
  return value === null || value === undefined ? null : number(value, label);
}

function nullableString(value: unknown, label: string): string | null {
  return value === null || value === undefined ? null : string(value, label);
}

function segment(value: unknown): ChapterSegmentInput {
  const source = object(value, "片段");
  return {
    id: string(source.id, "片段 ID"),
    position: number(source.position, "片段顺序"),
    text: string(source.text, "正文"),
    language: string(source.language, "语言") as ChapterSegmentInput["language"],
    contentHash: string(source.contentHash, "内容哈希"),
    included: source.included === undefined ? true : Boolean(source.included),
    sourceKind: string(source.sourceKind, "正文来源") as ChapterSegmentInput["sourceKind"],
    pageNumber: nullableNumber(source.pageNumber, "页码"),
    ocrConfidence: nullableNumber(source.ocrConfidence, "OCR 置信度"),
    warning: nullableString(source.warning, "提示"),
  };
}

function chapter(value: unknown): ChapterInput {
  const source = object(value, "章节");
  if (!Array.isArray(source.segments)) throw new Error("章节片段必须是数组。");
  return {
    id: string(source.id, "章节 ID"),
    title: string(source.title, "章节标题"),
    position: number(source.position, "章节顺序"),
    pageStart: nullableNumber(source.pageStart, "起始页"),
    pageEnd: nullableNumber(source.pageEnd, "结束页"),
    segments: source.segments.map(segment),
  };
}

function errorResponse(error: unknown): Response {
  return Response.json(
    {
      error: {
        code: "invalid_chapter_request",
        message: error instanceof Error ? error.message : "章节请求无法处理。",
      },
    },
    { status: 400 },
  );
}

export function createChapterApi(
  repository: ChapterRepository,
  deleteAudioObjects: (keys: string[]) => Promise<void>,
) {
  return {
    async list(bookId: string) {
      try {
        return Response.json({ chapters: await repository.list(bookId) });
      } catch (error) {
        return errorResponse(error);
      }
    },

    async save(request: Request, bookId: string) {
      try {
        const payload = object(await request.json(), "请求");
        if (!Array.isArray(payload.chapters)) throw new Error("chapters 必须是数组。");
        const result = await repository.saveBatch(bookId, payload.chapters.map(chapter));
        await deleteAudioObjects(result.invalidatedAudioKeys);
        return Response.json({ chapters: await repository.list(bookId) });
      } catch (error) {
        return errorResponse(error);
      }
    },

    async finalize(request: Request, bookId: string) {
      try {
        const payload = object(await request.json(), "请求");
        if (
          !Array.isArray(payload.chapterIds) ||
          payload.chapterIds.some((id) => typeof id !== "string")
        ) {
          throw new Error("chapterIds 必须是文字数组。");
        }
        const result = await repository.finalize(
          bookId,
          payload.chapterIds as string[],
        );
        await deleteAudioObjects(result.invalidatedAudioKeys);
        return Response.json({ chapters: await repository.list(bookId) });
      } catch (error) {
        return errorResponse(error);
      }
    },
  };
}
