"use client";

import Image from "next/image";
import { useEffect, useMemo, useRef, useState, useTransition } from "react";
import Link from "next/link";
import { addToCart } from "@/app/(store)/actions";
import WishlistButton from "./WishlistButton";
import { useRouter } from "next/navigation";

export type VariantView = {
  id: string; color: string | null; colorHex: string | null; size: string | null; price: number; priceLabel: string;
  mode: "READY_STOCK" | "PRE_ORDER"; purchasable: boolean; label: string; stockQty: number; maxQty: number;
  batch: null | {
    state: string; stateLabel: string; remaining: number; capacity: number; closes: string; opens: string; dispatch: string; paymentSummary: string;
    depositPerUnit: number | null; depositLabel: string; balanceDue: string | null; delivery: string | null; terms: string | null;
  };
};
export type ImageView = { id: string; url: string; alt: string; color: string | null; variantId: string | null };

type Props = {
  productId: string; name: string; shortDescription: string | null; images: ImageView[]; variants: VariantView[]; saved: boolean;
  sizeGuide: string | null; defaultTerms: string;
};

export default function ProductView({ productId, name, shortDescription, images, variants, saved, sizeGuide, defaultTerms }: Props) {
  const colours = useMemo(() => [...new Map(variants.filter((v) => v.color).map((v) => [v.color!, v.colorHex])).entries()], [variants]);
  const sizes = useMemo(() => [...new Set(variants.map((v) => v.size).filter(Boolean))] as string[], [variants]);
  const firstBuyable = variants.find((v) => v.purchasable) ?? variants[0];
  const [colour, setColour] = useState<string | null>(colours.length ? firstBuyable?.color ?? colours[0][0] : null);
  const [size, setSize] = useState<string | null>(null);
  const [qty, setQty] = useState(1);
  const [msg, setMsg] = useState<{ ok: boolean; text: string } | null>(null);
  const [pending, start] = useTransition();
  const [zoom, setZoom] = useState<number | null>(null);
  const [showGuide, setShowGuide] = useState(false);
  const router = useRouter();

  const shown = useMemo(() => {
    const byColour = images.filter((i) => !colour || !i.color || i.color === colour);
    return byColour.length ? byColour : images;
  }, [images, colour]);
  const [idx, setIdx] = useState(0);
  useEffect(() => setIdx(0), [colour]);

  const variant = useMemo(() => {
    const pool = variants.filter((v) => (!colours.length || v.color === colour));
    if (sizes.length) return pool.find((v) => v.size === size) ?? null;
    return pool[0] ?? null;
  }, [variants, colour, size, colours.length, sizes.length]);

  const sizeAvailable = (s: string) => variants.some((v) => v.color === colour && v.size === s && v.purchasable);
  const b = variant?.batch ?? null;
  const unit = variant?.price ?? firstBuyable?.price ?? 0;
  const fmt = (n: number) => `৳${n.toLocaleString("en-IN")}`;

  function add(go: boolean) {
    setMsg(null);
    if (sizes.length && !size) return setMsg({ ok: false, text: "Choose a size to continue." });
    if (!variant) return setMsg({ ok: false, text: "Choose an option to continue." });
    start(async () => {
      const r = await addToCart(variant.id, qty);
      setMsg({ ok: r.ok, text: r.message ?? "" });
      if (r.ok) { router.refresh(); if (go) router.push("/cart"); }
    });
  }

  return (
    <div className="wrap grid lg:grid-cols-12 gap-8 lg:gap-14 pb-16">
      {/* Gallery */}
      <div className="lg:col-span-7 grid grid-cols-[64px_1fr] md:grid-cols-[84px_1fr] gap-3 md:gap-5 items-start">
        <ul className="flex flex-col gap-2 md:gap-3" aria-label="Product images">
          {shown.map((im, i) => (
            <li key={im.id}>
              <button onClick={() => setIdx(i)} aria-label={`Show image ${i + 1}`} aria-current={i === idx} className={`block relative w-full aspect-portrait bg-linen border ${i === idx ? "border-ink" : "border-transparent"}`}>
                <Image src={im.url} alt="" fill sizes="84px" className="object-cover" />
              </button>
            </li>
          ))}
        </ul>
        <button onClick={() => setZoom(idx)} className="relative block aspect-portrait bg-linen cursor-zoom-in w-full" aria-label="Zoom image">
          {shown[idx] && <Image src={shown[idx].url} alt={shown[idx].alt || name} fill priority sizes="(min-width:1024px) 50vw, 85vw" className="object-cover" />}
        </button>
      </div>

      {/* Buy panel */}
      <div className="lg:col-span-5 lg:sticky lg:top-28 self-start">
        <h1 className="font-display text-[40px] md:text-[56px] leading-[1.05]">{name}</h1>
        <p className="mt-3 text-[20px]">{fmt(unit)}</p>
        {shortDescription && <p className="mt-4 text-stone max-w-[46ch]">{shortDescription}</p>}

        {colours.length > 0 && (
          <fieldset className="mt-8">
            <legend className="label">Colour: <span className="text-ink">{colour}</span></legend>
            <div className="flex gap-2.5 flex-wrap">
              {colours.map(([c, hex]) => (
                <button key={c} type="button" onClick={() => { setColour(c); setSize(null); setMsg(null); }} aria-pressed={colour === c} aria-label={c}
                  className={`w-9 h-9 rounded-full border-2 p-0.5 ${colour === c ? "border-ink" : "border-transparent hover:border-sand"}`}>
                  <span className="block w-full h-full rounded-full border border-black/10" style={{ background: hex ?? "#ddd" }} />
                </button>
              ))}
            </div>
          </fieldset>
        )}

        {sizes.length > 0 && (
          <fieldset className="mt-6">
            <legend className="label flex justify-between w-full"><span>Size</span>{sizeGuide && <button type="button" className="underline underline-offset-4 text-ink" onClick={() => setShowGuide(true)}>Size guide</button>}</legend>
            <div className="flex gap-2 flex-wrap">
              {sizes.map((s) => {
                const ok = sizeAvailable(s);
                return <button key={s} type="button" disabled={!ok} aria-pressed={size === s} onClick={() => { setSize(s); setMsg(null); }}
                  className={`min-w-[52px] h-11 px-4 border text-[14px] transition-colors ${size === s ? "bg-ink text-paper border-ink" : "border-sand hover:border-ink"} ${!ok ? "opacity-40 line-through cursor-not-allowed" : ""}`}>{s}</button>;
              })}
            </div>
          </fieldset>
        )}

        {/* Availability + pre-order panel */}
        <div className="mt-8 border-t border-sand pt-6" aria-live="polite">
          {variant ? (
            variant.mode === "PRE_ORDER" && b ? (
              <div className="space-y-2 text-[14px]">
                <p className="eyebrow-status">{b.stateLabel}</p>
                {b.state === "OPEN" && <p>{b.remaining} of {b.capacity} places left. Batch closes {b.closes}.</p>}
                {b.state === "SCHEDULED" && <p>Pre-order opens {b.opens}.</p>}
                {b.state === "CLOSED" && <p>This batch closed {b.closes}. Join the newsletter to hear about the next one.</p>}
                {b.state === "SOLD_OUT" && <p>All {b.capacity} places in this batch are reserved.</p>}
                <p><span className="text-stone">Estimated dispatch:</span> {b.dispatch} <span className="text-stone">(an estimate, not a guarantee)</span></p>
                {b.delivery && <p className="text-stone">{b.delivery}</p>}
                <p><span className="text-stone">Payment:</span> {b.paymentSummary}</p>
                {b.depositPerUnit != null && b.depositPerUnit < unit && b.state === "OPEN" && (
                  <p><span className="text-stone">Deposit today:</span> {fmt(b.depositPerUnit * qty)} · <span className="text-stone">balance</span> {fmt((unit - b.depositPerUnit) * qty)}{b.balanceDue ? ` due by ${b.balanceDue}` : ""}</p>
                )}
                <details className="pt-1"><summary className="cursor-pointer underline underline-offset-4">Pre-order terms</summary><p className="mt-2 text-stone leading-relaxed">{b.terms || defaultTerms}</p></details>
              </div>
            ) : (
              <p className={`text-[14px] ${variant.purchasable ? "" : "text-stone"}`}>{variant.label}{variant.purchasable && variant.mode === "READY_STOCK" ? ". Dispatched within two working days." : ""}</p>
            )
          ) : (
            <p className="text-stone text-[14px]">Select a size to see availability.</p>
          )}
        </div>

        <div className="mt-6 flex items-center gap-3">
          <div className="flex items-center border border-sand h-12" role="group" aria-label="Quantity">
            <button type="button" className="w-11 h-full" aria-label="Decrease quantity" onClick={() => setQty((q) => Math.max(1, q - 1))}>−</button>
            <span className="w-8 text-center" aria-live="polite">{qty}</span>
            <button type="button" className="w-11 h-full" aria-label="Increase quantity" onClick={() => setQty((q) => Math.min(variant?.maxQty ?? 10, q + 1))}>+</button>
          </div>
          <button className="btn-solid flex-1" disabled={pending || (!!variant && !variant.purchasable)} onClick={() => add(false)}>
            {variant && !variant.purchasable ? variant.label : pending ? "Adding…" : (variant ?? firstBuyable)?.mode === "PRE_ORDER" ? "Pre-order" : "Add to bag"}
          </button>
        </div>
        {msg && (
          <p role="alert" className={`mt-3 text-[14px] ${msg.ok ? "text-ink" : "text-rose"}`}>
            {msg.text} {msg.ok && <Link href="/cart" className="underline underline-offset-4 ml-1">View bag</Link>}
          </p>
        )}
        <div className="mt-5"><WishlistButton productId={productId} initial={saved} name={name} inline /></div>
      </div>

      {zoom !== null && <Lightbox images={shown} start={zoom} onClose={() => setZoom(null)} />}
      {showGuide && sizeGuide && <GuideDialog text={sizeGuide} onClose={() => setShowGuide(false)} />}
    </div>
  );
}

function Lightbox({ images, start, onClose }: { images: ImageView[]; start: number; onClose: () => void }) {
  const [i, setI] = useState(start);
  const [pos, setPos] = useState({ x: 50, y: 50 });
  const [zoomed, setZoomed] = useState(false);
  const ref = useRef<HTMLDivElement>(null);
  useEffect(() => {
    ref.current?.focus();
    const k = (e: KeyboardEvent) => { if (e.key === "Escape") onClose(); if (e.key === "ArrowRight") setI((x) => (x + 1) % images.length); if (e.key === "ArrowLeft") setI((x) => (x - 1 + images.length) % images.length); };
    window.addEventListener("keydown", k); document.body.style.overflow = "hidden";
    return () => { window.removeEventListener("keydown", k); document.body.style.overflow = ""; };
  }, [images.length, onClose]);
  const im = images[i];
  return (
    <div ref={ref} tabIndex={-1} role="dialog" aria-modal="true" aria-label="Zoomed image" className="fixed inset-0 z-50 bg-paper flex flex-col outline-none">
      <div className="flex justify-between items-center wrap h-14 shrink-0"><span className="text-stone text-sm">{i + 1} / {images.length}</span><button className="nav-type py-3" onClick={onClose}>Close</button></div>
      <div className="flex-1 min-h-0 flex items-center justify-center overflow-hidden px-4">
        <div className={`relative h-full aspect-portrait max-w-full overflow-hidden ${zoomed ? "cursor-zoom-out" : "cursor-zoom-in"}`}
          onClick={() => setZoomed((z) => !z)}
          onMouseMove={(e) => { const r = e.currentTarget.getBoundingClientRect(); setPos({ x: ((e.clientX - r.left) / r.width) * 100, y: ((e.clientY - r.top) / r.height) * 100 }); }}>
          <Image src={im.url} alt={im.alt} fill sizes="100vw" className="object-cover transition-transform duration-300" style={{ transform: zoomed ? "scale(2.4)" : "scale(1)", transformOrigin: `${pos.x}% ${pos.y}%` }} />
        </div>
      </div>
      {images.length > 1 && <div className="flex justify-center gap-8 py-4"><button className="nav-type" onClick={() => setI((x) => (x - 1 + images.length) % images.length)}>Previous</button><button className="nav-type" onClick={() => setI((x) => (x + 1) % images.length)}>Next</button></div>}
    </div>
  );
}

function GuideDialog({ text, onClose }: { text: string; onClose: () => void }) {
  useEffect(() => { const k = (e: KeyboardEvent) => e.key === "Escape" && onClose(); window.addEventListener("keydown", k); return () => window.removeEventListener("keydown", k); }, [onClose]);
  const rows = text.split("\n").filter((l) => l.startsWith("|") && !/^\|[-\s|]+\|$/.test(l)).map((l) => l.split("|").slice(1, -1).map((c) => c.trim()));
  const intro = text.split("\n").filter((l) => !l.startsWith("|") && l.trim()).join(" ");
  return (
    <div role="dialog" aria-modal="true" aria-label="Size guide" className="fixed inset-0 z-50 bg-ink/40 grid place-items-center p-4" onClick={onClose}>
      <div className="bg-paper max-w-lg w-full p-6 md:p-8" onClick={(e) => e.stopPropagation()}>
        <div className="flex justify-between items-start"><h2 className="font-display text-[32px]">Size guide</h2><button className="nav-type py-1" onClick={onClose}>Close</button></div>
        <p className="text-stone mt-2">{intro}</p>
        {rows.length > 0 && <table className="size-guide mt-5"><thead><tr>{rows[0].map((h) => <th key={h}>{h}</th>)}</tr></thead><tbody>{rows.slice(1).map((r, i) => <tr key={i}>{r.map((c, j) => <td key={j}>{c}</td>)}</tr>)}</tbody></table>}
      </div>
    </div>
  );
}
