// Card collection system — rarity tiers, drop evaluation, user collection store.
// Phase 2: collection persists in Supabase via /api/cards/me (was localStorage).

const RARITIES = {
  comun: { id: "comun", label: "COMÚN", order: 1, color: "#9aa0a8", glow: "rgba(154, 160, 168, 0.55)", inner: "linear-gradient(145deg, #2a2d33 0%, #4a4d55 100%)", weight: 100 },
  rara:  { id: "rara",  label: "RARA",  order: 2, color: "#5fb3ff", glow: "rgba(95, 179, 255, 0.7)",   inner: "linear-gradient(145deg, #1a3050 0%, #3a6dab 100%)", weight: 60 },
  epica: { id: "epica", label: "ÉPICA", order: 3, color: "#c96ad8", glow: "rgba(201, 106, 216, 0.75)", inner: "linear-gradient(145deg, #2a1230 0%, #6a2470 100%)", weight: 30 },
  legendaria: { id: "legendaria", label: "LEGENDARIA", order: 4, color: "#ffc04a", glow: "rgba(255, 192, 74, 0.8)",  inner: "linear-gradient(145deg, #3a2a08 0%, #8a6010 100%)", weight: 12 },
  mitica:     { id: "mitica",     label: "MÍTICA",     order: 5, color: "#ff5aa0", glow: "rgba(255, 90, 160, 0.9)",  inner: "linear-gradient(145deg, #3a0a2a 0%, #ff5aa0 50%, #5fb3ff 100%)", weight: 4 },
};

const RARITY_LIST = Object.values(RARITIES).sort((a, b) => a.order - b.order);

function getRarity(id) { return RARITIES[id] || RARITIES.comun; }

const CARDS_CACHE_KEY = "trooper_user_cards_cache_v3";

// Sanitiza el cache de localStorage. En la noche del 2026-04-26 hubo un bug
// donde novelStore.saveCache colisionaba en scope global con cardSystem.saveCache
// y escribía {arcs, characters, cards} sobre este storage. Si detectamos ese
// shape, lo descartamos (los keys legítimos son UUIDs de cards, nunca esos).
function isCardsMapValid(obj) {
  if (!obj || typeof obj !== "object" || Array.isArray(obj)) return false;
  for (const k of Object.keys(obj)) {
    if (k === "arcs" || k === "characters" || k === "cards") return false;
    const v = obj[k];
    if (!v || typeof v !== "object" || typeof v.count !== "number") return false;
  }
  return true;
}

function loadCardsCache() {
  try {
    const raw = localStorage.getItem(CARDS_CACHE_KEY);
    if (!raw) return {};
    const parsed = JSON.parse(raw);
    if (!isCardsMapValid(parsed)) {
      console.warn("[cardSystem] cache corrupto detectado, descartando:", parsed);
      try { localStorage.removeItem(CARDS_CACHE_KEY); } catch (e) {}
      return {};
    }
    return parsed;
  } catch (e) { return {}; }
}
function saveCardsCache(map) {
  try { localStorage.setItem(CARDS_CACHE_KEY, JSON.stringify(map)); } catch (e) {}
  window.dispatchEvent(new CustomEvent("trooper:cards-updated"));
}

async function fetchUserCards() {
  try {
    const r = await fetch("/api/cards/me", { credentials: "same-origin" });
    // 401 transitorio no debe borrar el cache local — solo limpiamos cuando
    // app.jsx detecta logout real (user → null) vía trooper:user-changed.
    if (r.status === 401) return loadCardsCache();
    if (!r.ok) throw new Error(`HTTP ${r.status}`);
    const map = await r.json();
    saveCardsCache(map);
    return map;
  } catch (e) {
    console.error("[cardSystem] fetch failed", e);
    return loadCardsCache();
  }
}

function loadUserCards() { return loadCardsCache(); }

async function addCardToCollection(cardId) {
  // Optimistic local update — instant UI feedback.
  const map = loadCardsCache();
  const existing = map[cardId];
  if (existing) {
    map[cardId] = { ...existing, count: existing.count + 1 };
  } else {
    map[cardId] = { count: 1, firstAt: Date.now() };
  }
  saveCardsCache(map);

  // Persist to server. Surface failures loudly so we don't silently lose drops.
  let errorMsg = null;
  try {
    const r = await fetch("/api/cards/me", {
      method: "POST",
      headers: { "Content-Type": "application/json" },
      credentials: "include",   // include cookies even from iframe-srcdoc contexts
      body: JSON.stringify({ cardId }),
    });
    if (!r.ok) {
      const data = await r.json().catch(() => ({}));
      errorMsg = `HTTP ${r.status} — ${data.error || "respuesta sin detalle"}`;
      console.error("[cardSystem] POST /api/cards/me falló:", errorMsg);
    }
  } catch (e) {
    errorMsg = e?.message || "network error";
    console.error("[cardSystem] POST /api/cards/me throw:", e);
  }

  // Always re-sync from server so client state matches DB truth (no permanent
  // optimistic ghost entries). If POST failed, this reverts the optimistic add.
  await fetchUserCards();

  // Show a visible toast if anything failed — the user deserves to know.
  if (errorMsg) {
    window.dispatchEvent(new CustomEvent("trooper:card-error", { detail: { cardId, errorMsg } }));
  }
  return loadCardsCache()[cardId];
}

function evaluateChapterDrops(cards, arcId, chapterId) {
  const drops = [];
  for (const card of cards || []) {
    for (const rule of card.dropRules || []) {
      if (
        rule.trigger === "chapter" &&
        String(rule.arcId) === String(arcId) &&
        String(rule.chapterId) === String(chapterId)
      ) {
        const chance = Number(rule.chance ?? 100);
        if (Math.random() * 100 < chance) {
          drops.push(card);
          break;
        }
      }
    }
  }
  return drops;
}

function evaluateArcDrops(cards, arcId) {
  const drops = [];
  for (const card of cards || []) {
    for (const rule of card.dropRules || []) {
      if (rule.trigger === "arc" && String(rule.arcId) === String(arcId)) {
        const chance = Number(rule.chance ?? 100);
        if (Math.random() * 100 < chance) {
          drops.push(card);
          break;
        }
      }
    }
  }
  return drops;
}

function useUserCards() {
  const [map, setMap] = React.useState(() => loadCardsCache());
  React.useEffect(() => {
    let cancelled = false;
    fetchUserCards().then((m) => { if (!cancelled) setMap(m); });
    const refresh = () => setMap(loadCardsCache());
    // Re-fetch from server when login/logout happens or any tab pings us.
    const refetch = () => fetchUserCards().then((m) => { if (!cancelled) setMap(m); });
    window.addEventListener("trooper:cards-updated", refresh);
    window.addEventListener("trooper:user-changed", refetch);
    return () => {
      cancelled = true;
      window.removeEventListener("trooper:cards-updated", refresh);
      window.removeEventListener("trooper:user-changed", refetch);
    };
  }, []);
  return map;
}

async function downloadWallpaper(card) {
  const W = 1080, H = 1920;
  const canvas = document.createElement("canvas");
  canvas.width = W; canvas.height = H;
  const ctx = canvas.getContext("2d");

  ctx.fillStyle = "#000";
  ctx.fillRect(0, 0, W, H);

  if (card.image) {
    try {
      const img = new Image();
      img.crossOrigin = "anonymous";
      await new Promise((resolve, reject) => {
        img.onload = resolve;
        img.onerror = reject;
        img.src = card.image;
      });
      const imgRatio = img.width / img.height;
      const canvasRatio = W / H;
      let sx = 0, sy = 0, sw = img.width, sh = img.height;
      if (imgRatio > canvasRatio) {
        sw = img.height * canvasRatio;
        sx = (img.width - sw) / 2;
      } else {
        sh = img.width / canvasRatio;
        sy = (img.height - sh) / 2;
      }
      ctx.drawImage(img, sx, sy, sw, sh, 0, 0, W, H);
    } catch (e) {
      console.warn("Could not load card image for wallpaper", e);
    }
  }

  const grad = ctx.createLinearGradient(0, H - 320, 0, H);
  grad.addColorStop(0, "rgba(0,0,0,0)");
  grad.addColorStop(1, "rgba(0,0,0,0.85)");
  ctx.fillStyle = grad;
  ctx.fillRect(0, H - 320, W, 320);

  const rarity = getRarity(card.rarity);
  ctx.fillStyle = rarity.color;
  ctx.fillRect(80, H - 200, 60, 4);

  ctx.fillStyle = "#fff";
  ctx.font = "700 56px Montserrat, sans-serif";
  ctx.fillText((card.name || "TROOPER").toUpperCase(), 80, H - 130);

  ctx.fillStyle = rarity.color;
  ctx.font = "600 22px 'JetBrains Mono', monospace";
  ctx.fillText(rarity.label, 80, H - 90);

  ctx.fillStyle = "rgba(255,255,255,0.55)";
  ctx.font = "500 20px 'JetBrains Mono', monospace";
  ctx.fillText("TROOPER · " + (card.id || "").slice(-6).toUpperCase(), 80, H - 60);

  canvas.toBlob((blob) => {
    const url = URL.createObjectURL(blob);
    const a = document.createElement("a");
    a.href = url;
    a.download = `trooper-${(card.name || "card").toLowerCase().replace(/[^a-z0-9]/g, "-")}.png`;
    document.body.appendChild(a);
    a.click();
    document.body.removeChild(a);
    setTimeout(() => URL.revokeObjectURL(url), 1000);
  }, "image/png");
}

window.CardSystem = {
  RARITIES,
  RARITY_LIST,
  getRarity,
  loadUserCards,
  fetchUserCards,
  addCardToCollection,
  evaluateChapterDrops,
  evaluateArcDrops,
  useUserCards,
  downloadWallpaper,
};
