"use client";
import { useState, useTransition } from "react";
import Link from "next/link";
import { useRouter } from "next/navigation";
import { Pencil, User, Star, Gem, Check } from "lucide-react";
import { ActressPortraitEditor } from "./ActressPortraitEditor";
import { CategoryIcon } from "./CategoryIcon";
import { useActressSelection } from "./ActressSelectionProvider";
import type { ActressCategory, ActressAllPortraits } from "@/lib/db/queries";
import { portraitUrl } from "@/lib/assetUrls";
import { toggleActressCategory } from "@/app/actions/actressCategories";
import { cn } from "@/lib/utils";

export interface ActressCardData {
  id: number;
  name: string;
  slug: string;
  count: number;
  portraitPath: string | null;
  portraitZoom: number;
  portraitOffsetX: number;
  portraitOffsetY: number;
  categories: ActressCategory[];
  portraits: ActressAllPortraits;
}

const PHI = 1.618;
const CARD_W = 240;
const CARD_H_PORTRAIT = Math.round(CARD_W * PHI);
const CARD_W_LANDSCAPE = Math.round(CARD_W * PHI);
const CARD_H_LANDSCAPE = CARD_W;
// Mirror the editor's canonical frame so cqw-based offsets line up.
const FRAME_H = 360;
const CANONICAL_PORTRAIT_W = Math.round(FRAME_H / PHI);
const CANONICAL_LANDSCAPE_W = Math.round(FRAME_H * PHI);

export function ActressCard({
  actress,
  builtins,
  orderedIds,
  view = "portrait",
}: {
  actress: ActressCardData;
  builtins: { favoriteId?: number; vipId?: number };
  orderedIds: number[];
  view?: "portrait" | "landscape";
}) {
  const [editing, setEditing] = useState(false);
  const router = useRouter();
  const [, start] = useTransition();
  const sel = useActressSelection();
  const selected = sel.has(actress.id);
  const anySelected = sel.ids.size > 0;

  const ringCat = actress.categories[0];
  const ringColor = ringCat?.color ?? (selected ? "var(--color-cyan)" : null);

  // Optimistic per-category overrides. Map<categoryId, on?>; presence in
  // `pending` disables the button while the server action is in flight.
  const [optimistic, setOptimistic] = useState<Map<number, boolean>>(new Map());
  const [pending, setPending] = useState<Set<number>>(new Set());
  const isOnInServer = (id: number) => actress.categories.some((c) => c.id === id);
  const isOn = (id: number) => optimistic.get(id) ?? isOnInServer(id);

  const isFavorite = builtins.favoriteId != null && isOn(builtins.favoriteId);
  const isVip = builtins.vipId != null && isOn(builtins.vipId);

  // Per-view portrait selection. Landscape uses the L slot strictly —
  // no fallback to P1, so missing L portraits surface as the empty
  // user-icon state and the user knows to upload one.
  const isLandscape = view === "landscape";
  const slotData = isLandscape
    ? {
        path: actress.portraits.ph.path,
        zoom: actress.portraits.ph.zoom,
        offsetX: actress.portraits.ph.offsetX,
        offsetY: actress.portraits.ph.offsetY,
        slot: "h" as const,
      }
    : {
        path: actress.portraitPath,
        zoom: actress.portraitZoom,
        offsetX: actress.portraitOffsetX,
        offsetY: actress.portraitOffsetY,
        slot: "1" as const,
      };
  // In landscape mode, cards fill their grid column instead of being a
  // fixed pixel width — the parent grid controls how many fit per row.
  const cardW = isLandscape ? "100%" : CARD_W;
  const cardH = isLandscape ? undefined : CARD_H_PORTRAIT;
  const hasImg = !!slotData.path;

  function toggleCat(e: React.MouseEvent, categoryId: number | undefined) {
    e.preventDefault();
    e.stopPropagation();
    if (categoryId == null) return;
    if (pending.has(categoryId)) return; // ignore double-clicks while in flight
    const next = !isOn(categoryId);
    setOptimistic((m) => new Map(m).set(categoryId, next));
    setPending((s) => new Set(s).add(categoryId));
    start(async () => {
      try {
        await toggleActressCategory(actress.id, categoryId);
        router.refresh();
      } catch (err) {
        // Revert the optimistic flip on failure.
        console.error("[toggleActressCategory] failed:", err);
        setOptimistic((m) => {
          const n = new Map(m);
          n.delete(categoryId);
          return n;
        });
      } finally {
        setPending((s) => {
          const n = new Set(s);
          n.delete(categoryId);
          return n;
        });
      }
    });
  }

  function handleCheckbox(e: React.MouseEvent) {
    e.preventDefault();
    e.stopPropagation();
    if (e.shiftKey) sel.selectRangeTo(actress.id, orderedIds);
    else sel.toggle(actress.id);
  }

  function handleCardClick(e: React.MouseEvent) {
    if (anySelected) {
      e.preventDefault();
      if (e.shiftKey) sel.selectRangeTo(actress.id, orderedIds);
      else sel.toggle(actress.id);
    }
  }

  return (
    <>
      <div
        className={cn(
          "cover-hero-frame group relative rounded-2xl overflow-hidden glass glass-hover",
          anySelected && !selected && "opacity-70 hover:opacity-100",
        )}
        style={{
          width: cardW,
          boxShadow: selected && ringColor
            ? `0 0 0 4px ${ringColor}, 0 0 24px -2px ${ringColor}`
            : undefined,
          border: "none",
        }}
      >
        <Link href={`/actress/${actress.slug}`} onClick={handleCardClick} className="block">
          <div
            className="cover-hero-hover relative bg-[var(--color-bg-1)] overflow-hidden"
            style={
              isLandscape
                ? { aspectRatio: `${PHI} / 1`, containerType: "inline-size" }   // 1.618 : 1
                : { height: cardH, containerType: "inline-size" }
            }
          >
            {hasImg ? (
              /* eslint-disable-next-line @next/next/no-img-element */
              <img
                src={portraitUrl({ path: slotData.path!, slug: actress.slug, slot: slotData.slot })}
                alt={actress.name}
                draggable={false}
                className="absolute top-1/2 left-1/2 max-w-none origin-center pointer-events-none"
                style={{
                  transform: `translate(-50%, -50%) translate(${slotData.offsetX / (isLandscape ? CANONICAL_LANDSCAPE_W : CANONICAL_PORTRAIT_W) * 100}cqw, ${slotData.offsetY / (isLandscape ? CANONICAL_LANDSCAPE_W : CANONICAL_PORTRAIT_W) * 100}cqw) scale(${slotData.zoom})`,
                  width: "100cqw",
                  height: "auto",
                }}
              />
            ) : (
              <div className="absolute inset-0 grid place-items-center">
                <User className="w-12 h-12 text-[var(--color-fg-muted)]" />
              </div>
            )}

            {actress.categories.length > 0 && (
              <div className="absolute top-2 left-2 z-10 flex flex-wrap gap-1 max-w-[60%]">
                {actress.categories.map((c) => (
                  <span
                    key={c.id}
                    className="flex items-center gap-1 text-[11px] uppercase tracking-wider font-mono font-semibold px-2.5 py-0.5 rounded-full bg-black/80 backdrop-blur-md shadow-md"
                    style={{
                      color: c.color ?? "#fff",
                      border: `1px solid ${c.color ?? "#888"}aa`,
                      textShadow: "0 1px 2px rgba(0,0,0,0.9)",
                    }}
                    title={c.name}
                  >
                    <CategoryIcon name={c.icon} className="w-3 h-3" />
                    {c.name}
                  </span>
                ))}
              </div>
            )}

            <div className="absolute inset-x-0 bottom-0 z-10 bg-gradient-to-t from-black/85 via-black/45 to-transparent p-3 pt-10">
              <div className="text-base font-medium text-white truncate">{actress.name}</div>
              <div className="text-[10px] uppercase tracking-wider font-mono text-[var(--color-cyan)]">
                {actress.count} cover{actress.count === 1 ? "" : "s"}
              </div>
            </div>
          </div>
        </Link>

        <button
          type="button"
          onClick={handleCheckbox}
          aria-label={selected ? "Deselect" : "Select"}
          title={selected ? "Deselect (Shift+click for range)" : "Select (Shift+click for range)"}
          className={cn(
            "absolute top-2 right-2 w-8 h-8 grid place-items-center rounded-md transition-all backdrop-blur-md border-2 z-10",
            selected
              ? "bg-[var(--color-cyan)] border-[var(--color-cyan)] text-black shadow-[var(--shadow-glow-cyan)]"
              : "bg-black/40 border-white/50 text-transparent",
            !selected && !anySelected && "opacity-0 group-hover:opacity-100",
          )}
        >
          <Check className="w-4 h-4" strokeWidth={3} />
        </button>

        <div className="absolute bottom-2 right-2 flex items-center gap-1 opacity-0 group-hover:opacity-100 transition-opacity z-10">
          {builtins.vipId != null && (
            <button
              type="button"
              onClick={(e) => toggleCat(e, builtins.vipId)}
              disabled={builtins.vipId != null && pending.has(builtins.vipId)}
              title={isVip ? "Unmark VIP" : "Mark VIP"}
              className={cn(
                "w-8 h-8 grid place-items-center rounded-md cursor-pointer transition-all duration-150",
                "hover:scale-110 hover:ring-2 hover:ring-cyan-300 hover:shadow-lg active:scale-95",
                isVip
                  ? "bg-cyan-400/40 text-cyan-200 hover:bg-cyan-400/60"
                  : "bg-black/70 text-white hover:bg-cyan-400/30 hover:text-cyan-200",
              )}
            >
              <Gem className="w-4 h-4" />
            </button>
          )}
          {builtins.favoriteId != null && (
            <button
              type="button"
              onClick={(e) => toggleCat(e, builtins.favoriteId)}
              disabled={builtins.favoriteId != null && pending.has(builtins.favoriteId)}
              title={isFavorite ? "Unmark Favorite" : "Mark Favorite"}
              className={cn(
                "w-8 h-8 grid place-items-center rounded-md cursor-pointer transition-all duration-150",
                "hover:scale-110 hover:ring-2 hover:ring-amber-300 hover:shadow-lg active:scale-95",
                isFavorite
                  ? "bg-amber-400/40 text-amber-200 hover:bg-amber-400/60"
                  : "bg-black/70 text-white hover:bg-amber-400/30 hover:text-amber-200",
              )}
            >
              <Star className={cn("w-4 h-4", isFavorite && "fill-amber-200")} />
            </button>
          )}
          <button
            type="button"
            onClick={(e) => { e.preventDefault(); e.stopPropagation(); setEditing(true); }}
            title="Edit portrait"
            className={cn(
              "w-8 h-8 grid place-items-center rounded-md cursor-pointer transition-all duration-150",
              "bg-black/70 text-white",
              "hover:scale-110 hover:ring-2 hover:ring-[var(--color-cyan)] hover:bg-[var(--color-cyan)]/30 hover:text-[var(--color-cyan)] hover:shadow-lg active:scale-95",
            )}
          >
            <Pencil className="w-4 h-4" />
          </button>
        </div>
      </div>

      {editing && (
        <ActressPortraitEditor
          actressId={actress.id}
          actressName={actress.name}
          initial={actress.portraits}
          onClose={() => setEditing(false)}
        />
      )}
    </>
  );
}
