import path from "path";

import { MediaKind, MediaSource } from "@prisma/client";

import { createMediaAsset, getMediaAssetById } from "@/lib/media";
import { getExtensionForMimeType, removeManagedMediaFile, saveMediaUpload } from "@/lib/media-storage";
import type { MediaFieldInput } from "@/lib/media-validation";

function getFileNameFromUrl(url: string) {
  const pathname = new URL(url, "https://placeholder.local").pathname;
  const fileName = path.basename(pathname);

  return fileName && fileName !== "/" ? fileName : "external-file";
}

export async function resolveMediaSelection(input: {
  media: MediaFieldInput | undefined;
  uploadFile: FormDataEntryValue | null;
  folder: string;
  fallbackLabel: string;
  required: boolean;
}) {
  const media = input.media;

  if (!media) {
    if (input.required) {
      throw new Error("Media configuration is missing.");
    }

    return {
      assetId: null,
      url: "",
      uploadedUrl: null,
    };
  }

  if (media.mode === "library") {
    const asset = media.assetId ? await getMediaAssetById(media.assetId) : null;

    if (!asset) {
      throw new Error("Selected media asset was not found.");
    }

    return {
      assetId: asset.id,
      url: asset.url,
      createdAssetId: null,
      uploadedUrl: null,
    };
  }

  if (media.mode === "external") {
    if (!media.url) {
      if (input.required) {
        throw new Error("Media URL is required.");
      }

      return {
        assetId: null,
        url: "",
        uploadedUrl: null,
      };
    }

    const asset = await createMediaAsset({
      source: MediaSource.EXTERNAL,
      kind: media.kind,
      url: media.url,
      fileName: getFileNameFromUrl(media.url),
      label: media.label || input.fallbackLabel,
      altText: media.label || input.fallbackLabel,
    });

    return {
      assetId: asset.id,
      url: asset.url,
      createdAssetId: asset.id,
      uploadedUrl: null,
    };
  }

  const uploadFile = input.uploadFile;

  if (!(uploadFile instanceof File) || uploadFile.size === 0) {
    if (input.required) {
      throw new Error("Upload file is required.");
    }

    return {
      assetId: null,
      url: "",
      createdAssetId: null,
      uploadedUrl: null,
    };
  }

  const savedFile = await saveMediaUpload(uploadFile, input.folder);

  if (!savedFile) {
    throw new Error("Unable to save upload.");
  }

  const asset = await createMediaAsset({
    source: MediaSource.UPLOAD,
    kind: media.kind,
    url: savedFile.url,
    fileName: savedFile.fileName,
    label: media.label || input.fallbackLabel,
    altText: media.label || input.fallbackLabel,
    mimeType: savedFile.mimeType,
    size: savedFile.size,
  });

  return {
    assetId: asset.id,
    url: asset.url,
    createdAssetId: asset.id,
    uploadedUrl: asset.url,
  };
}

export async function createStandaloneMediaAsset(input: {
  kind: MediaKind;
  label: string;
  uploadFile: FormDataEntryValue | null;
}) {
  if (input.uploadFile instanceof File && input.uploadFile.size > 0) {
    const savedFile = await saveMediaUpload(input.uploadFile, input.kind.toLowerCase());
    const derivedLabel = input.uploadFile.name.replace(/\.[^.]+$/, "").trim();
    const trimmedLabel = input.label.trim() || derivedLabel || "Media asset";

    if (!savedFile) {
      throw new Error("Unable to save upload.");
    }

    return createMediaAsset({
      source: MediaSource.UPLOAD,
      kind: input.kind,
      url: savedFile.url,
      fileName: savedFile.fileName,
      label: trimmedLabel,
      altText: trimmedLabel,
      mimeType: savedFile.mimeType,
      size: savedFile.size,
    });
  }

  throw new Error("Upload file is required.");
}

export async function deleteMediaAssetAndFile(input: {
  assetId: string;
  assetUrl: string;
}) {
  await removeManagedMediaFile(input.assetUrl);
}

export function inferMediaKindFromMimeType(mimeType: string | null | undefined): MediaKind {
  return mimeType?.startsWith("image/") || mimeType === "image/svg+xml"
    ? MediaKind.IMAGE
    : MediaKind.DOCUMENT;
}

export function inferMediaKindFromFileName(fileName: string): MediaKind {
  const extension = path.extname(fileName).toLowerCase();

  if ([".gif", ".jpg", ".jpeg", ".png", ".webp", ".svg"].includes(extension)) {
    return MediaKind.IMAGE;
  }

  return MediaKind.DOCUMENT;
}

export function getKindFromUploadFile(file: File) {
  const extension = getExtensionForMimeType(file.type);

  if (extension && [".gif", ".jpg", ".jpeg", ".png", ".webp", ".svg"].includes(extension)) {
    return MediaKind.IMAGE;
  }

  return MediaKind.DOCUMENT;
}
