import { randomUUID } from "crypto";
import { mkdir, rm, writeFile } from "fs/promises";
import path from "path";

export const MEDIA_UPLOAD_ROOT = path.join(process.cwd(), "public", "uploads", "media");
export const MAX_MEDIA_FILE_SIZE = 5 * 1024 * 1024;

const MIME_EXTENSIONS: Record<string, string> = {
  "image/x-icon": ".ico",
  "image/vnd.microsoft.icon": ".ico",
  "image/gif": ".gif",
  "image/jpeg": ".jpg",
  "image/png": ".png",
  "image/webp": ".webp",
  "image/svg+xml": ".svg",
  "application/pdf": ".pdf",
};

export function sanitizeBaseName(value: string) {
  return value
    .toLowerCase()
    .replace(/[^a-z0-9]+/g, "-")
    .replace(/^-+|-+$/g, "")
    .slice(0, 60);
}

export function getExtensionForMimeType(mimeType: string) {
  return MIME_EXTENSIONS[mimeType] ?? null;
}

export function isManagedMediaFilePath(filePath: string | null | undefined) {
  return typeof filePath === "string" && filePath.startsWith("/uploads/media/");
}

export function resolveMediaUploadPath(filePath: string) {
  if (!isManagedMediaFilePath(filePath)) {
    throw new Error("Only managed media uploads can be resolved.");
  }

  const relativePath = filePath.replace("/uploads/media/", "");
  const absolutePath = path.resolve(MEDIA_UPLOAD_ROOT, relativePath);

  if (!absolutePath.startsWith(MEDIA_UPLOAD_ROOT)) {
    throw new Error("Resolved media upload path escapes the upload root.");
  }

  return absolutePath;
}

export async function removeManagedMediaFile(filePath: string | null | undefined) {
  if (!isManagedMediaFilePath(filePath)) {
    return false;
  }

  const managedFilePath = filePath as string;

  await rm(resolveMediaUploadPath(managedFilePath), {
    force: true,
  });

  return true;
}

export async function saveMediaUpload(file: File, folder: string) {
  if (!file || file.size === 0) {
    return null;
  }

  const extension = getExtensionForMimeType(file.type);

  if (!extension) {
    throw new Error("Unsupported file type.");
  }

  if (file.size > MAX_MEDIA_FILE_SIZE) {
    throw new Error("File is too large.");
  }

  const safeBaseName = sanitizeBaseName(file.name.replace(/\.[^.]+$/, "")) || "asset";
  const finalName = `${safeBaseName}-${randomUUID().slice(0, 8)}${extension}`;
  const targetDir = path.join(MEDIA_UPLOAD_ROOT, folder);
  const targetPath = path.join(targetDir, finalName);

  await mkdir(targetDir, { recursive: true });
  await writeFile(targetPath, Buffer.from(await file.arrayBuffer()));

  return {
    url: `/uploads/media/${folder}/${finalName}`,
    fileName: finalName,
    mimeType: file.type,
    size: file.size,
  };
}
