"use client";

import { AnimatePresence, motion } from "framer-motion";
import { Check, Coins, Lock, Sparkles, X } from "lucide-react";
import { useEffect, useState } from "react";
import { ScreenHeader, ScreenShell } from "@/components/online/ScreenHeader";
import { Sticker } from "@/components/online/Sticker";
import { CoinsPill } from "@/components/online/CoinsPill";
import { useSessionStore } from "@/lib/session-store";
import { useI18n } from "@/lib/i18n";
import { getService } from "@/lib/online/service";
import { sound } from "@/lib/sound";
import { achievementById, cardBackById } from "@/lib/online/gamification";
import { backVisualFromDef, cardBackMotif } from "@/lib/cardBack";
import { celebrate } from "@/lib/celebration-store";
import { AchievementUnlock, ShopItem } from "@/lib/online/types";
import { cn } from "@/lib/cn";

/** The product artwork, used on the card and (bigger) in the detail sheet. */
function Preview({ item, size }: { item: ShopItem; size: number }) {
  switch (item.kind) {
    case "stickerpack":
      return <Sticker id={item.preview} size={size} />;
    case "cardfront":
      return (
        <span
          className="rounded-md border flex items-center justify-center text-slate-900 font-black"
          style={{
            width: size * 0.72,
            height: size,
            fontSize: size * 0.4,
            background: `linear-gradient(160deg, #ffffff, ${item.preview})`,
            borderColor: "rgba(0,0,0,0.18)",
          }}
        >
          ♠
        </span>
      );
    case "cardback": {
      const back = cardBackById(item.id);
      return (
        <span
          className="rounded-md border grid place-items-center"
          style={{
            width: size * 0.72,
            height: size,
            borderColor: `${back.accent}80`,
            ...backVisualFromDef(back),
          }}
        >
          <span style={{ fontSize: size * 0.3, color: `${back.accent}dd`, textShadow: "0 1px 2px rgba(0,0,0,0.4)" }}>
            {cardBackMotif(back.pattern, back.motif)}
          </span>
        </span>
      );
    }
    case "title":
      return (
        <span
          className="rounded-full btn-gold px-2.5 py-1 font-black leading-none whitespace-nowrap"
          style={{ fontSize: Math.max(9, size * 0.22) }}
        >
          🏷️
        </span>
      );
    default: // avatar, reactionpack, xp → emoji glyph
      return <span style={{ fontSize: size * 0.82, lineHeight: 1 }}>{item.kind === "xp" ? "⚡" : item.preview}</span>;
  }
}

export function ShopScreen() {
  const { t, locale } = useI18n();
  const profile = useSessionStore((s) => s.profile);
  const setProfile = useSessionStore((s) => s.setProfile);
  const [items, setItems] = useState<ShopItem[]>([]);
  const [msg, setMsg] = useState("");
  const [detail, setDetail] = useState<ShopItem | null>(null);

  useEffect(() => {
    getService().getShopItems().then(setItems);
  }, []);

  if (!profile) return null;

  const owns = (item: ShopItem) => {
    switch (item.kind) {
      case "avatar": return profile.ownedAvatars.includes(item.id);
      case "cardfront": return profile.ownedCardFronts.includes(item.id);
      case "cardback": return profile.ownedCardBacks.includes(item.id);
      case "reactionpack": return profile.ownedReactionPacks.includes(item.id);
      case "title": return profile.ownedTitles.includes(item.id);
      case "xp": return false; // consumable — always buyable
      default: return profile.ownedStickerPacks.includes(item.id);
    }
  };

  // Requirement gate: returns a label while LOCKED, else null.
  const lockLabel = (item: ShopItem): string | null => {
    if (item.reqLevel && profile.level < item.reqLevel) return `${t("shop.reqLevel")} ${item.reqLevel}`;
    if (item.reqRating && profile.rating < item.reqRating) return `${t("shop.reqRating")} ${item.reqRating}`;
    return null;
  };

  const buy = async (item: ShopItem) => {
    const before = profile;
    const res = await getService().buyItem(item.id);
    if (res.ok && res.profile) {
      const after = res.profile;
      setProfile(after);
      sound.play("purchase");
      setDetail(null);

      // newly-unlocked achievements (e.g. an XP pack crossing a level milestone)
      const newAch: AchievementUnlock[] = after.unlocked
        .filter((id) => !before.unlocked.includes(id))
        .map((id) => achievementById(id))
        .filter((d): d is NonNullable<typeof d> => !!d)
        .map((d) => ({ id: d.id, nameFa: d.nameFa, nameEn: d.nameEn, icon: d.icon, coinReward: d.coinReward }));

      if (item.kind === "xp") {
        celebrate({
          variant: "xp",
          icon: "⚡",
          title: locale === "fa" ? "امتیاز تجربه" : "Experience",
          xpGained: item.xp ?? 0,
          levelBefore: before.level,
          levelAfter: after.level,
          achievements: newAch.length ? newAch : undefined,
        });
      } else {
        celebrate({
          variant: "purchase",
          // avatar/reaction previews are emojis; others fall back to the default glyph
          icon: item.kind === "avatar" || item.kind === "reactionpack" ? item.preview : undefined,
          title: locale === "fa" ? item.nameFa : item.nameEn,
          achievements: newAch.length ? newAch : undefined,
        });
      }
    } else {
      setMsg(locale === "fa" ? res.messageFa : res.messageEn);
      setTimeout(() => setMsg(""), 1800);
    }
  };

  const sections: { title: string; kind: ShopItem["kind"]; hint?: string }[] = [
    { title: t("shop.avatars"), kind: "avatar" },
    { title: t("shop.cardfronts"), kind: "cardfront" },
    { title: t("shop.cardbacks"), kind: "cardback" },
    { title: t("shop.reactions"), kind: "reactionpack" },
    { title: t("shop.stickers"), kind: "stickerpack" },
    { title: t("shop.titles"), kind: "title", hint: t("shop.titlesHint") },
    { title: t("shop.xp"), kind: "xp", hint: t("shop.xpHint") },
  ];

  return (
    <ScreenShell>
      <ScreenHeader title={t("shop.title")} right={<CoinsPill />} />

      {msg && (
        <div className="mb-3 text-center text-rose-300 text-sm glass rounded-xl py-2">{msg}</div>
      )}

      {items.length === 0 && (
        <div className="space-y-5">
          {Array.from({ length: 2 }).map((_, s) => (
            <div key={s}>
              <div className="h-4 w-24 rounded bg-navy-800/80 animate-pulse mb-3" />
              <div className="grid grid-cols-3 gap-3">
                {Array.from({ length: 3 }).map((_, i) => (
                  <div key={i} className="glass rounded-2xl p-3 flex flex-col items-center gap-2 animate-pulse">
                    <div className="size-12 rounded-xl bg-navy-800/80" />
                    <div className="h-2.5 w-3/4 rounded bg-navy-800/80" />
                    <div className="h-6 w-full rounded-lg bg-navy-800/60" />
                  </div>
                ))}
              </div>
            </div>
          ))}
        </div>
      )}

      {sections.map((sec) => {
        const list = items.filter((i) => i.kind === sec.kind);
        if (!list.length) return null;
        return (
          <Section key={sec.kind} title={sec.title} hint={sec.hint}>
            <div className="grid grid-cols-3 gap-3">
              {list.map((item) => (
                <ItemCard key={item.id} item={item} owned={owns(item)} reqLabel={lockLabel(item)} onOpen={() => setDetail(item)} />
              ))}
            </div>
          </Section>
        );
      })}

      <AnimatePresence>
        {detail && (
          <DetailSheet
            item={detail}
            owned={owns(detail)}
            coins={profile.coins}
            reqLabel={lockLabel(detail)}
            onBuy={() => buy(detail)}
            onClose={() => setDetail(null)}
          />
        )}
      </AnimatePresence>
    </ScreenShell>
  );
}

function Section({ title, hint, children }: { title: string; hint?: string; children: React.ReactNode }) {
  return (
    <div className="mb-5">
      <h3 className="text-sm font-bold text-cream/80 mb-1">{title}</h3>
      {hint && <p className="text-[11px] text-cream/45 mb-2.5">{hint}</p>}
      {!hint && <div className="mb-1" />}
      {children}
    </div>
  );
}

function ItemCard({ item, owned, reqLabel, onOpen }: { item: ShopItem; owned: boolean; reqLabel: string | null; onOpen: () => void }) {
  const { locale, t } = useI18n();
  const count = item.contents?.length;
  const luxury = item.price >= 2000; // premium "luxury" tier
  const locked = !owned && !!reqLabel;
  return (
    <motion.button
      whileTap={{ scale: 0.96 }}
      onClick={onOpen}
      className={cn(
        "press-3d glass rounded-2xl p-3 flex flex-col items-center gap-2 relative",
        luxury && !owned && "ring-1 ring-gold-400/50"
      )}
    >
      {luxury && !owned && (
        <span className="absolute top-1.5 ltr:left-1.5 rtl:right-1.5 inline-flex items-center gap-0.5 rounded-full bg-gradient-to-r from-gold-500 to-gold-300 text-[#2a1f04] text-[8px] font-black px-1.5 py-0.5 shadow">
          ✦ {t("shop.luxury")}
        </span>
      )}
      {owned && (
        <span className="absolute top-1.5 ltr:right-1.5 rtl:left-1.5 grid size-5 place-items-center rounded-full bg-teal-500 text-navy-950">
          <Check className="size-3.5" strokeWidth={3} />
        </span>
      )}
      <div className={cn("h-12 flex items-center justify-center", locked && "opacity-40 grayscale")}>
        <Preview item={item} size={44} />
      </div>
      <span className="text-[11px] font-semibold text-cream/90 truncate max-w-full">
        {locale === "fa" ? item.nameFa : item.nameEn}
      </span>
      {/* quick detail hint */}
      <span className="text-[9px] text-cream/45 leading-none">
        {item.kind === "xp"
          ? `+${item.xp} XP`
          : count != null
          ? locale === "fa"
            ? `${count} مورد`
            : `${count} items`
          : " "}
      </span>
      <span
        className={cn(
          "w-full rounded-lg py-1.5 text-xs font-bold flex items-center justify-center gap-1",
          owned ? "bg-navy-900/60 text-teal-300" : locked ? "bg-navy-900/70 text-cream/55" : "btn-gold"
        )}
      >
        {owned ? (
          <Check className="size-3.5" />
        ) : locked ? (
          <>
            <Lock className="size-3" />
            <span className="text-[10px] truncate">{reqLabel}</span>
          </>
        ) : (
          <>
            <Coins className="size-3.5" />
            {item.price.toLocaleString()}
          </>
        )}
      </span>
    </motion.button>
  );
}

function DetailSheet({
  item,
  owned,
  coins,
  reqLabel,
  onBuy,
  onClose,
}: {
  item: ShopItem;
  owned: boolean;
  coins: number;
  reqLabel: string | null;
  onBuy: () => void;
  onClose: () => void;
}) {
  const { t, locale } = useI18n();
  const name = locale === "fa" ? item.nameFa : item.nameEn;
  const desc = locale === "fa" ? item.descFa : item.descEn;
  const locked = !owned && !!reqLabel;
  const canAfford = coins >= item.price;

  return (
    <motion.div
      initial={{ opacity: 0 }}
      animate={{ opacity: 1 }}
      exit={{ opacity: 0 }}
      onClick={onClose}
      className="fixed inset-0 z-[70] flex items-end sm:items-center justify-center bg-navy-950/80 backdrop-blur-sm p-4"
    >
      <motion.div
        initial={{ y: 40, scale: 0.96, opacity: 0 }}
        animate={{ y: 0, scale: 1, opacity: 1 }}
        exit={{ y: 40, opacity: 0 }}
        transition={{ type: "spring", stiffness: 240, damping: 24 }}
        onClick={(e) => e.stopPropagation()}
        className="glass rounded-3xl p-6 w-full max-w-sm text-center relative"
      >
        <button onClick={onClose} className="absolute top-3 ltr:right-3 rtl:left-3 grid size-9 place-items-center rounded-full hover:bg-navy-800/80 transition">
          <X className="size-4 text-cream/60" />
        </button>

        <div className="mx-auto size-24 rounded-2xl bg-navy-900/70 gold-border grid place-items-center">
          <Preview item={item} size={item.kind === "xp" || item.kind === "avatar" || item.kind === "reactionpack" ? 64 : 72} />
        </div>
        <h2 className="gold-text text-xl font-black mt-3">{name}</h2>
        {desc && <p className="text-cream/65 text-sm mt-1">{desc}</p>}

        {/* what's included */}
        {item.contents && item.contents.length > 0 && (
          <div className="mt-4 text-start">
            <div className="text-[11px] font-bold text-cream/55 mb-2">
              {t("shop.includes")} ({item.contents.length})
            </div>
            <div className="flex flex-wrap gap-2 justify-center">
              {item.kind === "stickerpack"
                ? item.contents.map((s) => (
                    <div key={s} className="rounded-xl bg-navy-900/60 p-1.5">
                      <Sticker id={s} size={40} />
                    </div>
                  ))
                : item.contents.map((e, i) => (
                    <span key={i} className="rounded-xl bg-navy-900/60 size-11 grid place-items-center text-2xl">
                      {e}
                    </span>
                  ))}
            </div>
          </div>
        )}

        {item.kind === "xp" && (
          <div className="mt-4 inline-flex items-center gap-2 btn-gold rounded-full px-5 py-2 font-black">
            <Sparkles className="size-4" />
            +{item.xp?.toLocaleString()} XP
          </div>
        )}

        {/* buy */}
        <button
          onClick={onBuy}
          disabled={owned || locked || !canAfford}
          className={cn(
            "press-3d w-full rounded-2xl py-3.5 mt-6 font-black flex items-center justify-center gap-2",
            owned
              ? "bg-navy-900/60 text-teal-300"
              : locked
              ? "bg-navy-900/60 text-cream/60"
              : canAfford
              ? "btn-gold"
              : "bg-navy-900/60 text-rose-300"
          )}
        >
          {owned ? (
            <>
              <Check className="size-4" /> {t("shop.owned")}
            </>
          ) : locked ? (
            <>
              <Lock className="size-4" /> {reqLabel}
            </>
          ) : canAfford ? (
            <>
              <Coins className="size-4" /> {t("shop.buy")} · {item.price.toLocaleString()}
            </>
          ) : (
            t("lobby.needCoins")
          )}
        </button>
      </motion.div>
    </motion.div>
  );
}
