import type { DocumentStatus, ReminderStatus } from "@prisma/client";

export const MAX_DOCUMENT_BYTES = 25 * 1024 * 1024;

export const DOCUMENT_ACCEPT = [
  ".pdf",
  ".jpg",
  ".jpeg",
  ".png",
  ".webp",
  ".doc",
  ".docx",
  ".xls",
  ".xlsx",
  "application/pdf",
  "image/jpeg",
  "image/png",
  "image/webp",
  "application/msword",
  "application/vnd.openxmlformats-officedocument.wordprocessingml.document",
  "application/vnd.ms-excel",
  "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"
].join(",");

const allowedExtensions = new Set([".pdf", ".jpg", ".jpeg", ".png", ".webp", ".doc", ".docx", ".xls", ".xlsx"]);
const allowedMimeTypes = new Set([
  "application/pdf",
  "image/jpeg",
  "image/png",
  "image/webp",
  "application/msword",
  "application/vnd.openxmlformats-officedocument.wordprocessingml.document",
  "application/vnd.ms-excel",
  "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"
]);

const extensionContentTypes: Record<string, string> = {
  ".pdf": "application/pdf",
  ".jpg": "image/jpeg",
  ".jpeg": "image/jpeg",
  ".png": "image/png",
  ".webp": "image/webp",
  ".doc": "application/msword",
  ".docx": "application/vnd.openxmlformats-officedocument.wordprocessingml.document",
  ".xls": "application/vnd.ms-excel",
  ".xlsx": "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"
};

const mimeExtensions: Record<string, string> = {
  "application/pdf": ".pdf",
  "image/jpeg": ".jpg",
  "image/png": ".png",
  "image/webp": ".webp",
  "application/msword": ".doc",
  "application/vnd.openxmlformats-officedocument.wordprocessingml.document": ".docx",
  "application/vnd.ms-excel": ".xls",
  "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet": ".xlsx"
};

export const defaultDocumentCategoryNames = [
  "Purchase / Closing",
  "Mortgage / Loan",
  "Insurance",
  "Property Tax / City",
  "Utility",
  "Permit / Inspection",
  "Renovation / Contractor",
  "Tenant / Lease",
  "Security Deposit",
  "Partner Agreement",
  "Legal / Notice",
  "Warranty",
  "Appliance / Equipment",
  "Other"
];

export const documentStatusLabels: Record<DocumentStatus, string> = {
  ACTIVE: "Active",
  PENDING: "Pending",
  EXPIRED: "Expired",
  ARCHIVED: "Archived",
  NEEDS_REVIEW: "Needs Review"
};

export const reminderStatusLabels: Record<ReminderStatus, string> = {
  OPEN: "Open",
  DONE: "Done",
  DISMISSED: "Dismissed"
};

export type DocumentKind = "image" | "pdf" | "office" | "file";

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

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

export function documentExtension(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 documentKind(fileName?: string | null, mimeType?: string | null): DocumentKind {
  const normalizedMime = mimeType?.toLowerCase() ?? "";
  const extension = documentExtension(fileName ?? "");
  if (normalizedMime.startsWith("image/") || [".jpg", ".jpeg", ".png", ".webp"].includes(extension)) return "image";
  if (normalizedMime === "application/pdf" || extension === ".pdf") return "pdf";
  if ([".doc", ".docx", ".xls", ".xlsx"].includes(extension)) return "office";
  return "file";
}

export function validateDocumentFile(file: DocumentFileLike | null | undefined): DocumentValidation {
  if (!file || file.size === 0) return { valid: true };
  if (file.size > MAX_DOCUMENT_BYTES) {
    return { valid: false, message: "Document must be 25 MB or smaller." };
  }

  const extension = documentExtension(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 PDF, image, Word, or Excel document file." };
  }

  return { valid: true };
}

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

export function safeDocumentFileName(fileName: string, mimeType?: string | null) {
  const baseName = fileName.split(/[/\\]/).pop() || "document";
  const safeName = baseName.replace(/[^a-zA-Z0-9._-]+/g, "-").replace(/^-+|-+$/g, "") || "document";
  const extension = documentExtension(safeName);
  if (extension) return safeName;
  const fallbackExtension = mimeType ? mimeExtensions[mimeType.toLowerCase()] : "";
  return `${safeName}${fallbackExtension || ".pdf"}`;
}

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

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

export function isAllowedDocumentExtension(fileName: string) {
  return allowedExtensions.has(documentExtension(fileName));
}

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

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

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