"use client";

import * as React from "react";
import {
  apiBaseUrl,
  getNoteImageDisplayUrl,
  isContaboObjectUrl,
  isContaboPublicUploadUrl,
  isDirectBrowserAssetUrl,
  isPublicAssetUrl,
} from "@/api/client";
import { getCachedSession } from "@/api/session-cache";
import { logNoteImage, logNoteImageEnvOnce } from "@/lib/note-image-debug";
import { cn } from "@/lib/utils";

export function isPrivateMediaContentUrl(url: string) {
  if (isDirectBrowserAssetUrl(url)) return false;
  if (isContaboPublicUploadUrl(url)) return false;
  if (isContaboObjectUrl(url) && isPublicAssetUrl(url)) return false;
  if (isContaboObjectUrl(url)) return true;
  return /\/media\/[^/]+\/content(?:\?|$)/.test(url);
}

/** API-served legacy disk path only — not Contabo/S3 absolute URLs. */
function isApiRelativePublicUpload(url: string) {
  return (
    url.includes("/public/uploads/") &&
    !url.startsWith("http://") &&
    !url.startsWith("https://")
  );
}

function shouldAuthenticateMediaFetch(resolved: string) {
  if (!resolved || resolved.startsWith("blob:") || resolved.startsWith("data:")) {
    return false;
  }
  if (isApiRelativePublicUpload(resolved)) return false;
  if (isPrivateMediaContentUrl(resolved)) return true;
  const base = apiBaseUrl.replace(/\/+$/, "");
  if (resolved.startsWith(base) && resolved.includes("/media/")) {
    return (
      !resolved.includes("/public/uploads/")
    );
  }
  return false;
}

/** Fetch private `/media/:id/content` with session auth; returns a blob: URL for img/Fancybox. */
export async function fetchAuthenticatedMediaDisplayUrl(
  src: string,
): Promise<string> {
  const resolved = getNoteImageDisplayUrl(src);
  if (!resolved?.trim()) {
    throw new Error("Empty media URL");
  }
  if (resolved.startsWith("blob:") || resolved.startsWith("data:")) {
    return resolved;
  }
  const needsAuth = shouldAuthenticateMediaFetch(resolved);
  logNoteImage("media-load-start", {
    src,
    resolved,
    needsAuth,
    isPublic: isDirectBrowserAssetUrl(resolved),
  });
  if (!needsAuth) {
    logNoteImage("media-load-ok", { resolved, via: "direct-url" });
    return resolved;
  }

  const session = await getCachedSession();
  const token = session?.accessToken as string | undefined;
  const headers = new Headers();
  if (token) headers.set("Authorization", `Bearer ${token}`);

  const credentials: RequestCredentials =
    typeof window !== "undefined" &&
    (resolved.startsWith("http://") || resolved.startsWith("https://")) &&
    new URL(resolved).origin !== window.location.origin
      ? "omit"
      : "include";

  const res = await fetch(resolved, {
    headers,
    credentials,
  });
  if (!res.ok) {
    logNoteImage("media-load-fail", {
      resolved,
      status: res.status,
      via: "authenticated-fetch",
    });
    throw new Error(`Media fetch failed: ${res.status}`);
  }
  const blob = await res.blob();
  const blobUrl = URL.createObjectURL(blob);
  logNoteImage("media-load-ok", { resolved, via: "blob-url" });
  return blobUrl;
}

export interface MediaContentImageProps {
  src: string;
  alt?: string;
  className?: string;
  fill?: boolean;
  sizes?: string;
  loading?: "lazy" | "eager";
}

/**
 * Loads private Contabo/S3 media via GET /media/:id/content with the session token.
 * Plain <img src> cannot send Authorization on cross-origin API URLs.
 */
export function MediaContentImage({
  src,
  alt = "",
  className,
  fill,
  sizes: _sizes,
  loading = "lazy",
}: MediaContentImageProps) {
  const resolved = getNoteImageDisplayUrl(src);
  const canUseDirectImg =
    resolved.startsWith("blob:") ||
    resolved.startsWith("data:") ||
    isApiRelativePublicUpload(resolved) ||
    isDirectBrowserAssetUrl(resolved);
  const [displaySrc, setDisplaySrc] = React.useState<string | null>(
    canUseDirectImg ? resolved : null,
  );
  const [failed, setFailed] = React.useState(false);

  React.useEffect(() => {
    logNoteImageEnvOnce();
  }, []);

  React.useEffect(() => {
    if (canUseDirectImg) {
      setDisplaySrc(resolved);
      setFailed(false);
      return;
    }

    let blobUrl: string | null = null;
    let cancelled = false;

    async function load() {
      if (!resolved?.trim()) {
        setDisplaySrc(null);
        setFailed(false);
        return;
      }

      try {
        const displayUrl = await fetchAuthenticatedMediaDisplayUrl(resolved);
        if (cancelled) return;
        if (displayUrl.startsWith("blob:")) {
          blobUrl = displayUrl;
        }
        setDisplaySrc(displayUrl);
        setFailed(false);
      } catch (err) {
        if (!cancelled) {
          logNoteImage("media-load-fail", {
            resolved,
            error: err instanceof Error ? err.message : String(err),
          });
          setFailed(true);
          setDisplaySrc(null);
        }
      }
    }

    setDisplaySrc(null);
    setFailed(false);
    void load();

    return () => {
      cancelled = true;
      if (blobUrl) URL.revokeObjectURL(blobUrl);
    };
  }, [resolved, canUseDirectImg]);

  if (failed) {
    return (
      <div
        className={cn(
          "flex items-center justify-center bg-gray-100 text-[10px] text-gray-400",
          fill && "absolute inset-0",
          className,
        )}
      >
        Image unavailable
      </div>
    );
  }

  if (!displaySrc) {
    return (
      <div
        className={cn(
          "animate-pulse bg-gray-200",
          fill && "absolute inset-0",
          className,
        )}
        aria-hidden
      />
    );
  }

  return (
    <img
      src={displaySrc}
      alt={alt}
      loading={loading}
      onError={() => {
        logNoteImage("media-img-error", { displaySrc, originalSrc: src });
        setFailed(true);
      }}
      className={cn(
        fill && "absolute inset-0 h-full w-full object-cover",
        className,
      )}
    />
  );
}
