import type { ProgressRepository } from "./repositories/progress.ts";

interface ProgressPort {
  get(bookId: string): ReturnType<ProgressRepository["get"]>;
  save(bookId: string, input: Parameters<ProgressRepository["save"]>[1]): ReturnType<ProgressRepository["save"]>;
}

function invalid(message: string): Response {
  return Response.json({ error: { code: "invalid_progress", message } }, { status: 400 });
}

export function createProgressApi(repository: ProgressPort) {
  return {
    async get(bookId: string): Promise<Response> {
      try {
        return Response.json({ progress: await repository.get(bookId) });
      } catch (cause) {
        return invalid(cause instanceof Error ? cause.message : "播放进度无法加载。");
      }
    },

    async put(request: Request, bookId: string): Promise<Response> {
      try {
        if (!request.headers.get("content-type")?.toLowerCase().startsWith("application/json")) {
          throw new Error("请求必须使用 JSON。");
        }
        const value: unknown = await request.json();
        if (!value || typeof value !== "object" || Array.isArray(value)) throw new Error("进度必须是对象。");
        const source = value as Record<string, unknown>;
        if (typeof source.chapterId !== "string" || !source.chapterId.trim()) throw new Error("章节 ID 不能为空。");
        if (typeof source.segmentId !== "string" || !source.segmentId.trim()) throw new Error("片段 ID 不能为空。");
        if (typeof source.offsetMs !== "number" || !Number.isFinite(source.offsetMs) || source.offsetMs < 0) throw new Error("播放位置格式不正确。");
        if (typeof source.playbackRate !== "number" || !Number.isFinite(source.playbackRate) || source.playbackRate < 0.5 || source.playbackRate > 3) throw new Error("语速必须在 0.5 到 3 倍之间。");
        if (typeof source.updatedAt !== "string" || !Number.isFinite(Date.parse(source.updatedAt))) throw new Error("更新时间格式不正确。");
        const progress = await repository.save(bookId, {
          chapterId: source.chapterId,
          segmentId: source.segmentId,
          offsetMs: Math.round(source.offsetMs),
          playbackRate: source.playbackRate,
          updatedAt: source.updatedAt,
        });
        return Response.json({ progress });
      } catch (cause) {
        return invalid(cause instanceof Error ? cause.message : "播放进度无法保存。");
      }
    },
  };
}
