// ============================================================
// Husky Paths — Sidebar (Explore panel) + Spotlight (city detail)
// ============================================================

// Count-up animation for big numbers (editorial magazine feel)
const CountUp = ({ value, dur = 700 }) => {
  const [n, setN] = useState(0);
  useEffect(() => {
    const start = performance.now();
    const from = 0, to = value;
    let raf;
    const tick = (t) => {
      const k = Math.min(1, (t - start) / dur);
      // ease-out cubic
      const e = 1 - Math.pow(1 - k, 3);
      setN(Math.round(from + (to - from) * e));
      if (k < 1) raf = requestAnimationFrame(tick);
    };
    raf = requestAnimationFrame(tick);
    return () => cancelAnimationFrame(raf);
  }, [value, dur]);
  return <span>{n}</span>;
};

// ── Shared bits ──────────────────────────────────────────────
const Overline = ({ en, zh, color }) => (
  <div className="hp-overline" style={color ? { color } : undefined}>
    {t(en, zh)}
  </div>
);

const PathTypeGlyph = ({ type }) => {
  const t = PATH_TYPES.find((p) => p.id === type);
  return <span className="hp-path-glyph">{t?.glyph || "·"}</span>;
};

// Compact profile row
const ProfileRow = ({ profile, onConnect, canViewContacts = false, density = "comfy" }) => {
  const isAnon = !profile.name || profile.name === "Anonymous";
  const initials = isAnon ? "?" : profile.name.split(" ").map((n) => n[0]).join("").slice(0, 2);

  return (
    <div className={`hp-profile-row ${density === "compact" ? "is-compact" : ""}`}>
      <div className="hp-profile-avatar" aria-hidden>
        {isAnon ? <span className="hp-anon-glyph">?</span> : <span>{initials}</span>}
      </div>
      <div className="hp-profile-body">
        <div className="hp-profile-top">
          <span className="hp-profile-name">{isAnon ? t("Anonymous Husky", "匿名校友") : profile.name}</span>
          <span className="hp-profile-year">'{profile.year.slice(-2)}</span>
        </div>
        <div className="hp-profile-org">
          <PathTypeGlyph type={profile.pathType} />
          <span>{profile.orgName}</span>
          {profile.roleDetail && <span className="hp-profile-role"> · {profile.roleDetail}</span>}
        </div>
        <div className="hp-profile-major">{profile.major}</div>
        {profile.foundingRank && (
          <div className="hp-founder-badge">{t(`Founding Husky #${profile.foundingRank}`, `冷启动校友 #${profile.foundingRank}`)}</div>
        )}
        {profile.isCommunity && (
          <div className="hp-community-badge">{t("Public info", "整理自公开来源")}</div>
        )}
        {profile.isDemo && (
          <div className="hp-demo-badge">{t("Preview path · no contact data", "示例路径 · 无联系方式")}</div>
        )}
        {profile.note && density !== "compact" && (
          <p className="hp-profile-note">{profile.note}</p>
        )}
        {profile.openToConnect && !isAnon && (
          <div className="hp-profile-actions">
            <button className="hp-chip-btn" onClick={() => onConnect(profile)}>
              <HPIcons.Mail /> {(canViewContacts || profile.isCommunity) ? t("Connect", "联系") : t("Verify to connect", "验证后可联系")}
            </button>
          </div>
        )}
        {profile.isCommunity && !profile.openToConnect && (
          <div className="hp-profile-private">
            <span className="hp-dot" /> {t("Destination only · no contact shared", "仅去向 · 未留联系方式")}
          </div>
        )}
        {!profile.openToConnect && !profile.isCommunity && !profile.isDemo && (
          <div className="hp-profile-private">
            <span className="hp-dot" /> {t("Private path", "私密路径")}
          </div>
        )}
      </div>
    </div>
  );
};

// ============================================================
// ExplorePanel — left rail
// ============================================================
const ExplorePanel = ({
  profiles,
  filteredProfiles,
  clearFilters,
  onCityClick,
  onConnect,
  canViewContacts,
  onAddPath,
  tweaks,
  collapsed,
  onToggleCollapse,
}) => {
  const total = profiles.length;
  const filteredCount = filteredProfiles.length;
  const foundingRemaining = Math.max(0, 50 - total);

  // Top cities by alumni count
  const topCities = useMemo(() => {
    const m = {};
    for (const p of filteredProfiles) m[p.city] = (m[p.city] || 0) + 1;
    return Object.entries(m).sort((a, b) => b[1] - a[1]).slice(0, 6);
  }, [filteredProfiles]);

  // Eyebrow 跟随当前筛选结果的毕业年份范围(年份筛选/任何筛选都会更新)
  const classLabel = useMemo(() => {
    const years = filteredProfiles
      .map((p) => parseInt(p.year, 10))
      .filter((y) => Number.isFinite(y) && y > 1900);
    if (!years.length) return { en: "UW alumni", zh: "UW 校友" };
    const min = Math.min(...years), max = Math.max(...years);
    const yy = (y) => String(y).slice(-2);
    if (min === max) return { en: `Class of '${yy(min)}`, zh: `${min}届` };
    return { en: `Classes of '${yy(min)}–'${yy(max)}`, zh: `${min}–${max}届` };
  }, [filteredProfiles]);

  if (collapsed) {
    return (
      <button className="hp-rail-collapsed" onClick={onToggleCollapse} title="Open explore panel">
        <HPIcons.Search />
        <span className="hp-rail-collapsed-count">{filteredCount}</span>
      </button>
    );
  }

  return (
    <aside className="hp-rail">
      {/* Header — wordmark */}
      <div className="hp-rail-head">
        <div className="hp-brand">
          <div className="hp-brand-mark">
            <HPIcons.ScanMark size={28} color="var(--accent-coral)" />
          </div>
          <div className="hp-brand-text">
            <div className="hp-brand-title">Husky Paths</div>
            <div className="hp-brand-sub">{t("UW alumni · atlas", "UW 校友足迹地图")}</div>
          </div>
        </div>
        <button className="hp-rail-collapse-btn" onClick={onToggleCollapse} title="Collapse">‹</button>
      </div>

      {/* Hero copy */}
      <div className="hp-rail-hero">
        <div className="hp-rail-hero-eyebrow">
          <Overline en={classLabel.en} zh={classLabel.zh} color="var(--accent-coral)" />
        </div>
        <h1 className="hp-rail-headline">
          {window.__HP_LANG === "zh"
            ? <>Husky 们<br/>都去哪了,<br/><em>为什么。</em></>
            : <>Where the<br/>Huskies went,<br/><em>and why.</em></>}
        </h1>
        <p className="hp-rail-lede">
          {t(
            "A living atlas of post-grad destinations — companies, grad schools, gap years — with the people behind each pin.",
            "一张不断生长的毕业去向地图——公司、研究生院、间隔年——每个图钉背后都是真实的人。"
          )}
        </p>
      </div>

      {/* Search + 路径类型筛选已移到顶部 FilterBar */}

      {/* Stats strip */}
      <div className="hp-stats">
        <div className="hp-stat">
          <div className="hp-stat-num">{filteredCount}</div>
          <div className="hp-stat-label">
            <Overline en="Paths" zh="路径" />
          </div>
        </div>
        <div className="hp-stat-divider" />
        <div className="hp-stat">
          <div className="hp-stat-num">{new Set(filteredProfiles.map(p=>p.city)).size}</div>
          <div className="hp-stat-label">
            <Overline en="Cities" zh="城市" />
          </div>
        </div>
        <div className="hp-stat-divider" />
        <div className="hp-stat">
          <div className="hp-stat-num">{new Set(filteredProfiles.map(p=>p.orgName)).size}</div>
          <div className="hp-stat-label">
            <Overline en="Orgs" zh="机构" />
          </div>
        </div>
      </div>

      <div className="hp-founder-card">
        <div>
          <Overline en="Founding Huskies" zh="冷启动成员" color="var(--accent-coral)" />
          <h3>{foundingRemaining > 0
            ? t(`${foundingRemaining} founding spots left`, `还剩 ${foundingRemaining} 个冷启动名额`)
            : t("Founding cohort filled", "冷启动名额已满")}</h3>
          <p>{t("Early submitters help make the map useful for the next class.", "早期提交者让这张地图对下一届更有用。")}</p>
        </div>
        <button className="hp-link-btn" onClick={onAddPath}>{t("Claim a spot", "占个位")}</button>
      </div>

      {/* Top destinations list */}
      <div className="hp-section">
        <div className="hp-section-head">
          <Overline en="Top destinations" zh="热门去向" color="var(--accent-coral)" />
          <span className="hp-section-meta">{t(`${topCities.length} cities`, `${topCities.length} 个城市`)}</span>
        </div>
        <div className="hp-top-list">
          {topCities.length === 0 && (
            <div className="hp-empty-mini">
              <p className="hp-italic">{t("No paths match this filter.", "没有符合筛选的路径。")} <button className="hp-link-btn" onClick={clearFilters}>{t("Clear filters", "清除筛选")}</button></p>
            </div>
          )}
          {topCities.map(([city, count]) => {
            const cityInfo = CITIES.find((c) => c.name === city);
            return (
              <button key={city} className="hp-top-row" onClick={() => onCityClick(city)}>
                <div className="hp-top-row-left">
                  <span className="hp-top-rank-pin">
                    <HPIcons.ScanMark size={16} color="var(--accent-coral)" />
                  </span>
                  <div>
                    <div className="hp-top-name">{city}</div>
                    <div className="hp-top-sub">
                      {window.__HP_LANG === "zh" && cityInfo?.zh ? cityInfo.zh : cityInfo?.country}
                    </div>
                  </div>
                </div>
                <div className="hp-top-right">
                  <span className="hp-top-count">{count}</span>
                  <span className="hp-top-arrow">→</span>
                </div>
              </button>
            );
          })}
        </div>
      </div>

      {/* Tip footer */}
      <div className="hp-rail-tip">
        <p className="hp-italic">
          <span className="hp-sparkle">✦</span> {t("Click any pin on the map to see who landed where.", "点击地图上的任意图钉,看看谁去了哪里。")}
        </p>
      </div>

      {/* Add CTA */}
      <button className="hp-cta-primary" onClick={onAddPath}>
        ＋ {t("Add my path", "添加我的路径")}
      </button>
    </aside>
  );
};

// ============================================================
// DestinationSpotlight — right slide-in panel
// ============================================================
const DestinationSpotlight = ({ city, profiles, onClose, onConnect, canViewContacts, tweaks }) => {
  if (!city) return null;
  const cityInfo = CITIES.find((c) => c.name === city);

  // Stats for this city
  const grouped = useMemo(() => {
    const byType = {};
    for (const p of profiles) byType[p.pathType] = (byType[p.pathType] || 0) + 1;
    return byType;
  }, [profiles]);

  const isSeattle = city === "Seattle";

  return (
    <div className="hp-spotlight">
      <div className="hp-spotlight-head">
        <div>
          <Overline
            en={isSeattle ? "Origin · Seattle" : "Destination"}
            zh={isSeattle ? "起点 · 母校所在地" : "目的地"}
            color="var(--accent-coral)"
          />
          <h2 className="hp-spot-title">
            {window.__HP_LANG === "zh" && cityInfo?.zh ? cityInfo.zh : city}
          </h2>
          <p className="hp-spot-sub">
            {cityInfo?.country}{cityInfo?.region ? ` · ${cityInfo.region}` : ""}
          </p>
        </div>
        <button className="hp-close-btn" onClick={onClose} title="Close">
          <HPIcons.X />
        </button>
      </div>

      {isSeattle && profiles.length === 0 && (
        <div className="hp-spot-origin-empty">
          <div className="hp-spot-mark">
            <HPIcons.ScanMark size={56} color="var(--brand-primary)" />
          </div>
          <h3 className="hp-card-h">{t("Where every Husky path begins.", "每条 Husky 之路的起点。")}</h3>
          <p className="hp-italic">
            {t(
              `University of Washington. The Ave, Drumheller Fountain, all-nighters at OUGL. From here, paths fan out to ${new Set(PROFILES.map((p) => p.city).filter((c) => c !== "Seattle")).size}+ cities worldwide.`,
              `华盛顿大学。The Ave、Drumheller 喷泉、OUGL 通宵自习。从这里出发,足迹延伸到全球 ${new Set(PROFILES.map((p) => p.city).filter((c) => c !== "Seattle")).size}+ 座城市。`
            )}
          </p>
        </div>
      )}

      {!isSeattle && (
        <>
          <div className="hp-spot-stats">
            <div className="hp-spot-stat-big">
              <div className="hp-spot-num"><CountUp value={profiles.length} /></div>
              <div className="hp-spot-num-label">
                {t(profiles.length === 1 ? "Husky" : "Huskies", "位校友")}
              </div>
            </div>
            <div className="hp-spot-stat-breakdown">
              {PATH_TYPES.map((pt) => {
                const c = grouped[pt.id] || 0;
                if (c === 0) return null;
                return (
                  <div key={pt.id} className="hp-spot-breakdown-row">
                    <span className="hp-path-glyph">{pt.glyph}</span>
                    <span className="hp-spot-breakdown-name">{t(pt.en, pt.zh)}</span>
                    <span className="hp-spot-breakdown-count">{c}</span>
                  </div>
                );
              })}
            </div>
          </div>

          <div className="hp-spot-divider" />

          <div className="hp-spot-list-head">
            <Overline en="Who landed here" zh="去到这里的校友" />
            <span className="hp-spot-list-meta">{t("Sorted by year", "按年份排序")}</span>
          </div>
        </>
      )}

      <div className="hp-spot-list">
        {[...profiles].sort((a, b) => Number(b.year) - Number(a.year)).map((p) => (
          <ProfileRow key={p.id} profile={p} onConnect={onConnect} canViewContacts={canViewContacts} density={tweaks.density} />
        ))}
      </div>

      {!isSeattle && profiles.length > 0 && (
        <div className="hp-spot-foot">
          <p className="hp-italic">
            <span className="hp-sparkle">✦</span> Showing {profiles.length} paths matching your current filters.
          </p>
        </div>
      )}
    </div>
  );
};

window.ExplorePanel = ExplorePanel;
window.DestinationSpotlight = DestinationSpotlight;
window.ProfileRow = ProfileRow;
window.Overline = Overline;
