/* LuckyDraw.jsx — 福利獎池 (Weekly Draw with LINE redemption)
   Flow:
     1. User types UID (must be exactly 11 digits).
     2. UID is matched against the alliance member roster.
     3. Only on a successful match does 主公 name display + 搖籤 button enable.
     4. Click 搖籤 → cylinder shakes 1.2s → random prize is picked from the
        pool of (enabled && stock > 0) items.
     5. Picked prize: stock auto -1 (persisted to sw_lottery_prizes_v2 → synced
        to Supabase by data-sync.js).
     6. Modal pops with the won prize + Screenshot button (uses html2canvas to
        download a PNG) + LINE redemption button.
     7. One draw per UID per weekly cycle. Cycle rolls Sunday 09:00. */

const LS_PRIZES_KEY  = "sw_lottery_prizes_v2";
const LS_CLAIMS_KEY  = "sw_welfare_lastdraw_v3";   // { [uid]: { date, prizeId, week } }
const LS_WEEK_KEY    = "sw_lottery_week_v1";
const MEMBERS_LS_KEY = "sw_alliance_members";

const LINE_INVITE_URL = "https://line.me/ti/g/acGDPGsBvP";
const UID_LENGTH = 11;

// === Image resolution (standalone bundle support) ===
const _R2 = (typeof window !== "undefined" && window.__resources) ? window.__resources : {};
const _imgMap = {
  "./assets/prize-1-wanshi.webp?v=2":   _R2.prize1,
  "./assets/prize-2-qianshi.webp?v=2":  _R2.prize2,
  "./assets/prize-3-jade60.webp?v=2":   _R2.prize3,
  "./assets/prize-4-jade300.webp?v=2":  _R2.prize4,
  "./assets/prize-5-jade980.webp?v=2":  _R2.prize5,
  "./assets/prize-6-jade1980.webp?v=2": _R2.prize6,
  "./assets/prize-7-jade3280.webp?v=2": _R2.prize7,
  "./assets/prize-8-jade6480.webp?v=2": _R2.prize8,
};
const _ldResolveImg = (p) => {
  if (!p) return "";
  if (p.startsWith("data:") || p.startsWith("blob:") || p.startsWith("http")) return p;
  return _imgMap[p] || p;
};

// === Time helpers ===
const todayKey = () => {
  const d = new Date();
  return `${d.getFullYear()}-${String(d.getMonth()+1).padStart(2,"0")}-${String(d.getDate()).padStart(2,"0")}`;
};
const lastSundayNineAm = () => {
  const now = new Date();
  const t = new Date(now);
  t.setHours(9, 0, 0, 0);
  const day = now.getDay();
  if (day === 0) {
    if (now.getHours() < 9) t.setDate(t.getDate() - 7);
  } else {
    t.setDate(t.getDate() - day);
  }
  return t.getTime();
};
const weekKey = () => {
  const d = new Date(lastSundayNineAm());
  return `${d.getFullYear()}-${String(d.getMonth()+1).padStart(2,"0")}-${String(d.getDate()).padStart(2,"0")}`;
};
const nextRefreshTime = () => {
  const now = new Date();
  const day = now.getDay();
  const target = new Date(now);
  target.setHours(9, 0, 0, 0);
  if (day === 0 && now.getHours() < 9) {
    // already today
  } else {
    const daysToSunday = (7 - day) % 7 || 7;
    target.setDate(now.getDate() + daysToSunday);
  }
  return target;
};
const formatCountdown = (ms) => {
  if (ms <= 0) return "即將更新";
  const totalSec = Math.floor(ms / 1000);
  const d = Math.floor(totalSec / 86400);
  const h = Math.floor((totalSec % 86400) / 3600);
  const m = Math.floor((totalSec % 3600) / 60);
  return `${d}日 ${String(h).padStart(2,"0")}時 ${String(m).padStart(2,"0")}分`;
};

// === Prize storage ===
const _migrate = (p) => ({
  id:       p.id,
  name:     p.name,
  tier:     p.tier || "common",
  maxStock: Number.isFinite(Number(p.maxStock)) ? Number(p.maxStock) : Number(p.stock) || 0,
  stock:    Number.isFinite(Number(p.stock))    ? Number(p.stock)    : Number(p.maxStock) || 0,
  enabled:  p.enabled === undefined ? true : !!p.enabled,
  img:      p.img || "",
});
const readPrizes = () => {
  try {
    const v = JSON.parse(localStorage.getItem(LS_PRIZES_KEY) || "null");
    if (Array.isArray(v) && v.length) return v.map(_migrate).filter((p) => p.id !== "luck");
  } catch {}
  return [];
};
const writePrizes = (p) => { try { localStorage.setItem(LS_PRIZES_KEY, JSON.stringify(p)); } catch {} };

// Auto-refill once per weekly boundary (Sun 09:00).
const maybeAutoReset = () => {
  try {
    const stored = localStorage.getItem(LS_WEEK_KEY);
    if (stored === weekKey()) return readPrizes();
    const prizes = readPrizes().map((p) => ({ ...p, stock: p.maxStock }));
    writePrizes(prizes);
    localStorage.setItem(LS_WEEK_KEY, weekKey());
    return prizes;
  } catch { return readPrizes(); }
};

// Split "儲值 ×6480" → { base: "儲值", count: "×6480" }
const splitName = (full) => {
  const m = String(full || "").match(/^(.*?)\s*(×\d+|x\d+)?$/);
  return { base: (m && m[1]) ? m[1].trim() : full, count: (m && m[2]) ? m[2] : "" };
};

// === Members ===
const readMembers = () => {
  try { return JSON.parse(localStorage.getItem(MEMBERS_LS_KEY) || '{"members":[]}').members || []; }
  catch { return []; }
};

// === Claims (per-uid weekly limit) ===
const readClaims = () => {
  try { return JSON.parse(localStorage.getItem(LS_CLAIMS_KEY) || "{}"); } catch { return {}; }
};
const writeClaims = (c) => { try { localStorage.setItem(LS_CLAIMS_KEY, JSON.stringify(c)); } catch {} };

// Pick a random prize from the (enabled && stock > 0) pool. Equal-probability;
// stock count is consumed but does NOT bias selection (matches "all real, random").
const pickRandomPrize = (prizes) => {
  const pool = prizes.filter((p) => p.enabled && p.stock > 0);
  if (pool.length === 0) return null;
  return pool[Math.floor(Math.random() * pool.length)];
};

// ─── Component ──────────────────────────────────────────────────────────────
const LuckyDraw = () => {
  const [prizes, setPrizes]       = React.useState(() => maybeAutoReset());
  const [uid, setUid]             = React.useState("");
  const [memberName, setMemberName] = React.useState("");
  const [phase, setPhase]         = React.useState("idle");  // idle | shaking | revealed | locked
  const [result, setResult]       = React.useState(null);
  const [err, setErr]             = React.useState("");
  const [myClaim, setMyClaim]     = React.useState(null);    // { week, prizeId, date } | null
  const [countdown, setCountdown] = React.useState(formatCountdown(nextRefreshTime() - new Date()));

  // Sync prize config from storage / other tabs / admin pane
  React.useEffect(() => {
    const refresh = () => setPrizes(maybeAutoReset());
    const onStorage = (e) => { if (e.key === LS_PRIZES_KEY || e.key === LS_WEEK_KEY || e.key === LS_CLAIMS_KEY) refresh(); };
    window.addEventListener("storage", onStorage);
    const t = setInterval(refresh, 8000);
    return () => { window.removeEventListener("storage", onStorage); clearInterval(t); };
  }, []);

  // Countdown ticker
  React.useEffect(() => {
    const tick = () => setCountdown(formatCountdown(nextRefreshTime() - new Date()));
    const t = setInterval(tick, 60000);
    return () => clearInterval(t);
  }, []);

  // Only resolve 主公 name when UID is exactly 11 digits AND matches a member.
  const uidDigits = uid.replace(/\D/g, "");
  const uidValid  = uidDigits.length === UID_LENGTH;

  React.useEffect(() => {
    if (!uidValid) { setMemberName(""); setMyClaim(null); return; }
    const m = readMembers().find((x) => x.uid === uidDigits);
    if (!m) { setMemberName(""); setMyClaim(null); return; }
    setMemberName(m.name || "");
    const c = readClaims()[uidDigits];
    setMyClaim(c && c.week === weekKey() ? c : null);
  }, [uidDigits, uidValid]);

  const canDraw = uidValid && memberName && !myClaim && phase === "idle";

  const onDraw = () => {
    if (!canDraw) return;
    setErr("");

    // Re-pull latest prizes (in case another tab just decremented)
    const live = maybeAutoReset();
    const winnerPreview = pickRandomPrize(live);
    if (!winnerPreview) {
      setErr("獎池已抽乾 · 請等待週日補貨。");
      return;
    }

    setPhase("shaking");
    setResult(null);

    // Shake animation lasts ~1.2s
    setTimeout(() => {
      // Re-pick fresh in case state changed during the shake
      const after = maybeAutoReset();
      const winner = pickRandomPrize(after);
      if (!winner) {
        setErr("獎池剛剛被抽乾 · 請等待週日補貨。");
        setPhase("idle");
        return;
      }
      // Decrement winner stock and persist
      const next = after.map((p) => p.id === winner.id ? { ...p, stock: Math.max(0, p.stock - 1) } : p);
      writePrizes(next);
      setPrizes(next);

      // Mark this UID as claimed for the week
      const claims = readClaims();
      const rec = { date: todayKey(), prizeId: winner.id, week: weekKey() };
      claims[uidDigits] = rec;
      writeClaims(claims);
      setMyClaim(rec);

      setResult(winner);
      setPhase("revealed");
    }, 1200);
  };

  const onCloseModal = () => setPhase("idle");

  // Real screenshot via html2canvas (lazy-loaded on first use)
  const onScreenshot = async () => {
    const card = document.getElementById("prize-modal-card");
    if (!card) return;
    if (typeof window.html2canvas !== "function") {
      try {
        await new Promise((resolve, reject) => {
          const s = document.createElement("script");
          s.src = "https://cdn.jsdelivr.net/npm/html2canvas@1.4.1/dist/html2canvas.min.js";
          s.onload = resolve;
          s.onerror = () => reject(new Error("html2canvas load failed"));
          document.head.appendChild(s);
        });
      } catch (e) {
        window.alert("截圖工具載入失敗 · 請檢查網路後重試。");
        return;
      }
    }
    try {
      // brief flash for UX feedback
      card.classList.add("prize-modal__card--flash");
      setTimeout(() => card.classList.remove("prize-modal__card--flash"), 600);

      const canvas = await window.html2canvas(card, {
        backgroundColor: null,
        scale: 2,
        useCORS: true,
        allowTaint: true,
        logging: false,
      });
      const dataUrl = canvas.toDataURL("image/png");
      const a = document.createElement("a");
      a.href = dataUrl;
      a.download = `福利獎池-${memberName || uidDigits}-${todayKey()}.png`;
      document.body.appendChild(a);
      a.click();
      document.body.removeChild(a);
    } catch (e) {
      console.error("[LuckyDraw] screenshot failed:", e);
      window.alert("截圖失敗 · 請手動截圖或重試。");
    }
  };

  const visible = prizes.filter((p) => p.enabled);

  // Determine what to render for the "right" face of the modal frame
  const resultImg = result ? _ldResolveImg(result.img) : "";

  // Member-name display text logic
  let nameDisplay = "—";
  let nameColor = "var(--fg-dim)";
  if (uidValid && memberName) {
    nameDisplay = memberName;
    nameColor = "var(--paper-100)";
  } else if (uidValid && !memberName) {
    nameDisplay = "UID 未登錄於同盟名冊";
    nameColor = "#e07a6a";
  }

  return (
    <div className="wrap">
      <div className="welfare">
        <span className="welfare__ghost">福</span>

        <div className="welfare__inner">
          {/* LEFT — UID + draw button + status */}
          <div>
            <div className="welfare__cap">
              <span className="seal">福利</span>
              <span className="welfare__cap-title" style={{fontSize: "12pt"}}>WEEKLY POOL · 福利獎池</span>
            </div>
            <div className="welfare__lead" style={{fontSize: "60px"}}>
              福利獎池
            </div>

            <div className="welfare__form">
              <div className="welfare__field">
                <label htmlFor="welfare-uid">IN-GAME UID · 遊戲編號 (11位)</label>
                <input
                  id="welfare-uid"
                  className="welfare__input"
                  type="text"
                  inputMode="numeric"
                  maxLength={UID_LENGTH}
                  placeholder="請輸入 11 位數字 UID"
                  value={uid}
                  onChange={(e) => { setUid(e.target.value.replace(/\D/g, "").slice(0, UID_LENGTH)); if (err) setErr(""); }}
                  onKeyDown={(e) => { if (e.key === "Enter" && canDraw) onDraw(); }}
                  autoComplete="off"
                  disabled={phase === "shaking"}
                />
              </div>
              <button
                className="btn btn--primary"
                style={{padding: "12px 36px", whiteSpace: "nowrap", letterSpacing: "0.12em", alignSelf: "flex-end"}}
                onClick={onDraw}
                disabled={!canDraw}
                title={
                  !uidValid ? "請先輸入 11 位 UID" :
                  !memberName ? "UID 未登錄於同盟名冊" :
                  myClaim ? "本週已搖過籤 · 下週日 09:00 重置" :
                  ""
                }
              >
                {phase === "shaking" ? "搖籤中…"
                  : myClaim ? "本週已搖"
                  : "搖 籤"}
              </button>
            </div>

            <div style={{
              marginTop: 8, minHeight: "1.4em",
              fontFamily: "var(--font-display)", fontWeight: 700,
              fontSize: "13pt", letterSpacing: "0.18em",
              color: nameColor,
            }}>
              {uidValid && (
                <span>
                  <span style={{fontFamily: "var(--font-latin-display)", fontSize: "11pt", letterSpacing: "0.32em", color: "var(--bronze-200)", textTransform: "uppercase", marginRight: 10}}>MEMBER · 主公</span>
                  {nameDisplay}
                </span>
              )}
            </div>

            {err && <div className="welfare__err">{err}</div>}

            <div className="welfare__status">
              <div className="welfare__status-item">
                <div className="welfare__status-label">POOL REFRESH · 補貨倒數</div>
                <div className="welfare__status-val">
                  <span className="welfare__refresh">{countdown}</span>
                </div>
              </div>
              <div className="welfare__status-item">
                <div className="welfare__status-label">YOUR STATUS · 本週狀態</div>
                <div className="welfare__status-val">
                  {myClaim ? (
                    <span style={{color: "#a8cd9e", fontSize: "16pt", letterSpacing: "0.18em"}}>已搖過</span>
                  ) : uidValid && memberName ? (
                    <span style={{color: "#f3c370", fontSize: "16pt", letterSpacing: "0.18em"}}>可搖籤</span>
                  ) : (
                    <span style={{color: "var(--fg-dim)", fontSize: "14pt", letterSpacing: "0.18em"}}>請輸入 UID</span>
                  )}
                </div>
              </div>
            </div>

            <div style={{marginTop: 14, fontFamily: "var(--font-body)", fontSize: "12pt", color: "var(--fg-dim)", letterSpacing: "0.1em", lineHeight: 1.8}}>
              每位主公每週限搖一次 · 每週日 09:00 獎池補貨 · 兌獎請加入 LINE 群
            </div>
          </div>

          {/* RIGHT — qian cylinder (idle / shaking based on phase) */}
          <div style={{position: "relative", display: "flex", alignItems: "center", justifyContent: "center", minHeight: 480}}>
            <div className={`qian2 qian2--${phase}`}>
              <img src={_R2.qianCylinder || "./assets/qian-cylinder.webp?v=2"} alt="籤筒" className="qian2__img" draggable="false" />
              <div className="qian2__glow" />
              <div className="qian2__shadow" />
            </div>
          </div>
        </div>

        {/* PRIZE REVEAL MODAL */}
        {phase === "revealed" && result && (
          <div className="prize-modal" onClick={onCloseModal}>
            <div
              className={`prize-modal__card prize-modal__card--${result.tier}`}
              onClick={(e) => e.stopPropagation()}
              id="prize-modal-card"
            >
              <div className="prize-modal__close" onClick={onCloseModal}>×</div>
              <div className="prize-modal__eyebrow">
                {result.tier === "legend" ? "天命所歸 · 大吉"
                 : result.tier === "epic"   ? "中吉之兆"
                 : result.tier === "rare"   ? "小吉之兆"
                 : "再接再厲"}
              </div>
              <div className="prize-modal__title">恭喜獲得</div>
              <div className="prize-modal__frame">
                {resultImg
                  ? <img src={resultImg} alt={result.name} className="prize-modal__img" crossOrigin="anonymous" />
                  : <div style={{padding: "40px 20px", color: "var(--bronze-200)", fontFamily: "var(--font-display)", fontSize: "18pt", letterSpacing: "0.2em"}}>{result.name}</div>}
              </div>
              {(() => { const { base, count } = splitName(result.name); return (
                <React.Fragment>
                  <div className="prize-modal__name">{base}</div>
                  {count && <div className="prize-modal__count">{count}</div>}
                </React.Fragment>
              ); })()}
              <div className="prize-modal__uid">
                <span className="prize-modal__uid-label">MEMBER</span>
                <span className="prize-modal__uid-val">{memberName} ({uidDigits})</span>
              </div>
              <div className="prize-modal__detail">截圖此頁面 · 加入 LINE 群兌換獎品</div>

              <div className="prize-modal__btn-row">
                <button className="btn-redeem btn-redeem--shot" onClick={onScreenshot}>
                  <span className="btn-redeem__icon" aria-hidden="true">
                    <svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round">
                      <path d="M23 19a2 2 0 0 1-2 2H3a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h4l2-3h6l2 3h4a2 2 0 0 1 2 2z"/>
                      <circle cx="12" cy="13" r="4"/>
                    </svg>
                  </span>
                  <span>
                    <div className="btn-redeem__lbl">SCREENSHOT</div>
                    <div className="btn-redeem__cn">截 圖</div>
                  </span>
                </button>
                <a
                  className="btn-redeem btn-redeem--line"
                  href={LINE_INVITE_URL}
                  target="_blank"
                  rel="noopener noreferrer"
                >
                  <span className="btn-redeem__icon" aria-hidden="true">
                    <svg width="20" height="20" viewBox="0 0 24 24" fill="currentColor" xmlns="http://www.w3.org/2000/svg">
                      <path d="M12 2C6.48 2 2 5.96 2 10.83c0 4.36 3.69 8.02 8.67 8.71.34.07.8.22.92.51.1.27.07.69.03.97l-.15.9c-.05.27-.21 1.05.92.57s6.11-3.6 8.34-6.16c1.54-1.69 2.27-3.41 2.27-5.5C23 5.96 18.52 2 12 2zM8.16 13.62H6.18c-.27 0-.49-.22-.49-.49V9.18c0-.27.22-.49.49-.49s.49.22.49.49v3.46h1.49c.27 0 .49.22.49.49s-.22.49-.49.49zm1.97-.49c0 .27-.22.49-.49.49s-.49-.22-.49-.49V9.18c0-.27.22-.49.49-.49s.49.22.49.49v3.95zm4.66 0c0 .21-.14.4-.34.46-.05.02-.1.03-.15.03-.16 0-.31-.07-.39-.2l-2.03-2.76v2.47c0 .27-.22.49-.49.49s-.49-.22-.49-.49V9.18c0-.21.14-.4.34-.47.05-.02.1-.02.15-.02.15 0 .31.08.39.2l2.03 2.76V9.18c0-.27.22-.49.49-.49s.49.22.49.49v3.95zm3.13-2.46c.27 0 .49.22.49.49 0 .27-.22.49-.49.49h-1.49v1H17.92c.27 0 .49.22.49.49 0 .27-.22.49-.49.49h-1.97c-.27 0-.49-.22-.49-.49V9.18c0-.27.22-.49.49-.49h1.97c.27 0 .49.22.49.49s-.22.49-.49.49h-1.49v1h1.49z"/>
                    </svg>
                  </span>
                  <span>
                    <div className="btn-redeem__lbl">LINE GROUP</div>
                    <div className="btn-redeem__cn">兌 換</div>
                  </span>
                </a>
              </div>
            </div>
          </div>
        )}

        {/* PRIZE GRID — showcase below */}
        <div className="welfare__grabgrid">
          <div className="welfare__marquee-label">PRIZE POOL · 獎品列表</div>
          <div className="grab-grid">
            {visible.length === 0 && (
              <div className="dim" style={{padding: "32px", gridColumn: "1/-1", textAlign: "center", fontFamily: "var(--font-body)", fontSize: "13pt"}}>
                獎池尚未配置，請聯絡管理員。
              </div>
            )}
            {visible.map((p) => {
              const { base, count } = splitName(p.name);
              const tierKey = (p.tier || "common").toLowerCase();
              return (
                <div
                  key={p.id}
                  className={`grab-card grab-card--${tierKey}`}
                >
                  <div className="grab-card__frame">
                    {p.img
                      ? <img src={_ldResolveImg(p.img)} alt={p.name} className="grab-card__img" />
                      : <div className="grab-card__placeholder">{base}</div>}
                  </div>
                  <div className="grab-card__name">{base}</div>
                  {count && <div className="grab-card__count">{count}</div>}
                </div>
              );
            })}
          </div>
        </div>
      </div>
    </div>
  );
};

window.LuckyDraw = LuckyDraw;
