"use client";

import { createElement, useEffect, useId, useState } from "react";

let modelViewerScriptPromise: Promise<void> | null = null;

function loadModelViewerScript() {
  if (typeof window === "undefined") return Promise.resolve();
  if (customElements.get("model-viewer")) return Promise.resolve();
  if (modelViewerScriptPromise) return modelViewerScriptPromise;

  modelViewerScriptPromise = new Promise((resolve, reject) => {
    const existing = document.querySelector<HTMLScriptElement>(
      'script[data-archi-model-viewer="1"]',
    );
    if (existing) {
      existing.addEventListener("load", () => resolve());
      existing.addEventListener("error", () =>
        reject(new Error("Failed to load model-viewer")),
      );
      return;
    }

    const script = document.createElement("script");
    script.type = "module";
    script.src =
      "https://ajax.googleapis.com/ajax/libs/model-viewer/4.0.0/model-viewer.min.js";
    script.dataset.archiModelViewer = "1";
    script.onload = () => resolve();
    script.onerror = () => reject(new Error("Failed to load model-viewer"));
    document.head.appendChild(script);
  });

  return modelViewerScriptPromise;
}

export function ModelViewer({
  modelUrl,
  alt = "3D model",
  className,
}: {
  modelUrl?: string | null;
  alt?: string;
  className?: string;
}) {
  const reactId = useId();
  const [ready, setReady] = useState(false);
  const [failed, setFailed] = useState(false);
  const src = modelUrl?.trim() || "";
  const hasModel = Boolean(src);

  useEffect(() => {
    if (!hasModel) return;
    let cancelled = false;
    loadModelViewerScript()
      .then(() => {
        if (!cancelled) setReady(true);
      })
      .catch(() => {
        if (!cancelled) setFailed(true);
      });
    return () => {
      cancelled = true;
    };
  }, [hasModel]);

  const frameClass =
    className ??
    "aspect-[4/5] w-full sm:aspect-[16/10] lg:aspect-[16/9]";

  if (!hasModel) {
    return (
      <div
        className={`relative flex overflow-hidden bg-[var(--archi-dark)] ${frameClass}`}
        role="img"
        aria-label="3D model forthcoming"
      >
        <div
          aria-hidden
          className="absolute inset-0"
          style={{
            background:
              "radial-gradient(ellipse 70% 55% at 50% 45%, #2a2e35 0%, #101214 70%, #0a0b0d 100%)",
          }}
        />
        <div className="studio-grain absolute inset-0 opacity-30" />
        <div className="relative z-10 flex w-full flex-col items-center justify-center gap-4 px-6 py-16 text-center">
          <div className="h-px w-12 bg-gradient-to-r from-transparent via-[var(--archi-gold)] to-transparent" />
          <p className="text-[0.65rem] tracking-[0.28em] text-[var(--archi-gold)] uppercase">
            Spatial model
          </p>
          <p className="font-[family-name:var(--font-display)] text-2xl text-white/80 sm:text-3xl">
            Model forthcoming
          </p>
          <p className="max-w-sm text-sm leading-6 text-white/40">
            Interactive GLB models appear here when the studio publishes a
            featured 3D project.
          </p>
        </div>
      </div>
    );
  }

  return (
    <div
      className={`relative overflow-hidden bg-[var(--archi-dark)] ${frameClass}`}
      aria-busy={!ready && !failed}
    >
      {failed ? (
        <div className="flex h-full min-h-[18rem] flex-col items-center justify-center gap-3 px-6 text-center sm:min-h-[20rem]">
          <p className="font-[family-name:var(--font-display)] text-2xl text-white/70">
            3D viewer unavailable
          </p>
          <p className="max-w-sm text-sm text-white/40">
            The model file could not be displayed in this browser.
          </p>
        </div>
      ) : ready ? (
        createElement("model-viewer", {
          key: `${reactId}-${src}`,
          src,
          alt,
          "camera-controls": true,
          "auto-rotate": true,
          "shadow-intensity": "0.6",
          exposure: "1",
          "touch-action": "pan-y",
          "interaction-prompt": "auto",
          style: {
            width: "100%",
            height: "100%",
            minHeight: "min(70svh, 36rem)",
            background:
              "radial-gradient(ellipse 70% 55% at 50% 45%, #2a2e35 0%, #101214 70%, #0a0b0d 100%)",
          },
        })
      ) : (
        <div className="flex h-full min-h-[min(70svh,36rem)] flex-col items-center justify-center gap-3 sm:min-h-[20rem]">
          <div
            aria-hidden
            className="h-8 w-8 animate-pulse rounded-full border border-[var(--archi-gold)]/40 border-t-[var(--archi-gold)]"
          />
          <p className="text-sm tracking-[0.18em] text-white/35 uppercase">
            Loading model…
          </p>
        </div>
      )}
    </div>
  );
}
