export const MAX_RECEIPT_BYTES = 10 * 1024 * 1024;

export const RECEIPT_ACCEPT = ".jpg,.jpeg,.png,.webp,.pdf,image/jpeg,image/png,image/webp,application/pdf";

const allowedExtensions = new Set([".jpg", ".jpeg", ".png", ".webp", ".pdf"]);
const allowedMimeTypes = new Set(["image/jpeg", "image/png", "image/webp", "application/pdf"]);

const mimeExtensions: Record<string, string> = {
  "image/jpeg": ".jpg",
  "image/png": ".png",
  "image/webp": ".webp",
  "application/pdf": ".pdf"
};

const extensionContentTypes: Record<string, string> = {
  ".jpg": "image/jpeg",
  ".jpeg": "image/jpeg",
  ".png": "image/png",
  ".webp": "image/webp",
  ".pdf": "application/pdf"
};

export type ReceiptKind = "image" | "pdf" | "file";

export type ReceiptFileLike = {
  name: string;
  size: number;
  type?: string;
};

export type ReceiptValidation =
  | { valid: true }
  | { valid: false; message: string };

export function receiptExtension(fileName: string) {
  const cleanName = fileName.split(/[?#]/)[0] ?? "";
  const slashName = cleanName.split(/[/\\]/).pop() ?? cleanName;
  const dotIndex = slashName.lastIndexOf(".");
  return dotIndex >= 0 ? slashName.slice(dotIndex).toLowerCase() : "";
}

export function isAllowedReceiptExtension(fileName: string) {
  return allowedExtensions.has(receiptExtension(fileName));
}

export function isAllowedReceiptMimeType(mimeType?: string | null) {
  if (!mimeType) return true;
  return allowedMimeTypes.has(mimeType.toLowerCase());
}

export function receiptContentType(fileName: string, mimeType?: string | null) {
  const normalizedMime = mimeType?.toLowerCase() ?? "";
  if (allowedMimeTypes.has(normalizedMime)) return normalizedMime;
  return extensionContentTypes[receiptExtension(fileName)] ?? "application/octet-stream";
}

export function receiptKind(fileName?: string | null, mimeType?: string | null): ReceiptKind {
  const normalizedMime = mimeType?.toLowerCase() ?? "";
  const extension = receiptExtension(fileName ?? "");

  if (normalizedMime.startsWith("image/") || [".jpg", ".jpeg", ".png", ".webp"].includes(extension)) {
    return "image";
  }
  if (normalizedMime === "application/pdf" || extension === ".pdf") {
    return "pdf";
  }
  return "file";
}

export function validateReceiptFile(file: ReceiptFileLike | null | undefined): ReceiptValidation {
  if (!file || file.size === 0) return { valid: true };
  if (file.size > MAX_RECEIPT_BYTES) {
    return { valid: false, message: "Receipt must be 10 MB or smaller." };
  }

  const extension = receiptExtension(file.name);
  const mimeType = file.type?.toLowerCase() ?? "";
  const hasAllowedExtension = allowedExtensions.has(extension);
  const hasAllowedMime = !mimeType || mimeType === "application/octet-stream" || allowedMimeTypes.has(mimeType);

  if (!hasAllowedExtension || !hasAllowedMime) {
    return {
      valid: false,
      message: "Use a JPG, JPEG, PNG, WEBP, or PDF receipt file."
    };
  }

  if (mimeType && mimeType !== "application/octet-stream") {
    const expectedExtension = mimeExtensions[mimeType];
    const isJpegPair = mimeType === "image/jpeg" && [".jpg", ".jpeg"].includes(extension);
    if (expectedExtension && expectedExtension !== extension && !isJpegPair) {
      return {
        valid: false,
        message: "The receipt file type does not match its filename."
      };
    }
  }

  return { valid: true };
}

export function safeReceiptFileName(fileName: string, mimeType?: string | null) {
  const baseName = fileName.split(/[/\\]/).pop() || "receipt";
  const safeName = baseName.replace(/[^a-zA-Z0-9._-]+/g, "-").replace(/^-+|-+$/g, "") || "receipt";
  const extension = receiptExtension(safeName);
  if (extension) return safeName;

  const fallbackExtension = mimeType ? mimeExtensions[mimeType.toLowerCase()] : "";
  return `${safeName}${fallbackExtension || ".png"}`;
}

export function isSimpleReceiptFileName(fileName: string) {
  return Boolean(fileName) && !fileName.includes("/") && !fileName.includes("\\") && fileName === safeReceiptFileName(fileName);
}

export function safeDecodeReceiptFileName(fileName: string) {
  try {
    return decodeURIComponent(fileName);
  } catch {
    return fileName;
  }
}

export function receiptStorageUrl(storedName: string) {
  return `/api/receipts/${encodeURIComponent(storedName)}`;
}

export function receiptUrlCandidates(storedName: string) {
  const encodedName = encodeURIComponent(storedName);
  return [
    `/api/receipts/${encodedName}`,
    `/uploads/receipts/${encodedName}`,
    `/api/receipts/${storedName}`,
    `/uploads/receipts/${storedName}`
  ];
}

export function receiptFileNameFromUrl(url?: string | null) {
  if (!url) return null;
  const cleanUrl = url.split(/[?#]/)[0] ?? "";
  const fileName = cleanUrl.split("/").pop();
  return fileName ? safeDecodeReceiptFileName(fileName) : null;
}

export function receiptUploadErrorMessage() {
  return "Receipt must be a JPG, JPEG, PNG, WEBP, or PDF file under 10 MB.";
}
