import type { BookFormat } from "./types";

export const MAX_BOOK_BYTES = 200 * 1024 * 1024;

export type BookFileErrorCode =
  | "empty_file"
  | "file_too_large"
  | "unsupported_extension"
  | "unsupported_mime"
  | "signature_mismatch"
  | "drm_or_encrypted";

export class BookFileValidationError extends Error {
  readonly code: BookFileErrorCode;

  constructor(code: BookFileErrorCode, message: string) {
    super(message);
    this.name = "BookFileValidationError";
    this.code = code;
  }
}

export interface BookFileCandidate {
  name: string;
  size: number;
  mimeType: string;
  header: Uint8Array;
  encrypted?: boolean;
  protectedResources?: boolean;
}

const MIME_TYPES: Record<BookFormat, ReadonlySet<string>> = {
  pdf: new Set(["application/pdf", "application/octet-stream", ""]),
  epub: new Set([
    "application/epub+zip",
    "application/zip",
    "application/x-zip-compressed",
    "application/octet-stream",
    "",
  ]),
};

function extensionFormat(name: string): BookFormat | null {
  const extension = name.trim().toLowerCase().split(".").at(-1);
  return extension === "pdf" || extension === "epub" ? extension : null;
}

function hasSignature(format: BookFormat, header: Uint8Array): boolean {
  if (format === "pdf") {
    return String.fromCharCode(...header.slice(0, 5)) === "%PDF-";
  }
  return (
    header[0] === 0x50 &&
    header[1] === 0x4b &&
    [0x03, 0x05, 0x07].includes(header[2] ?? -1) &&
    [0x04, 0x06, 0x08].includes(header[3] ?? -1)
  );
}

export function validateBookFile(candidate: BookFileCandidate): {
  format: BookFormat;
} {
  if (!Number.isFinite(candidate.size) || candidate.size <= 0) {
    throw new BookFileValidationError("empty_file", "文件是空的，无法导入。");
  }
  if (candidate.size > MAX_BOOK_BYTES) {
    throw new BookFileValidationError(
      "file_too_large",
      "文件超过 200 MB，请压缩或拆分后再上传。",
    );
  }

  const format = extensionFormat(candidate.name);
  if (!format) {
    throw new BookFileValidationError(
      "unsupported_extension",
      "第一版只支持 EPUB 和 PDF。",
    );
  }
  if (!MIME_TYPES[format].has(candidate.mimeType.toLowerCase())) {
    throw new BookFileValidationError(
      "unsupported_mime",
      "文件类型与扩展名不一致。",
    );
  }
  if (!hasSignature(format, candidate.header)) {
    throw new BookFileValidationError(
      "signature_mismatch",
      "文件内容与扩展名不一致，可能已损坏。",
    );
  }
  if (candidate.encrypted || candidate.protectedResources) {
    throw new BookFileValidationError(
      "drm_or_encrypted",
      "文件受 DRM 或密码保护，听阅不会尝试绕过保护。",
    );
  }

  return { format };
}
