// app.jsx — Ms.Brow Salon · single-page editorial premium
// Default palette: neutral mist · type: mixed serif/sans (set in CSS :root)

const { useState, useEffect, useRef } = React;
const LOGO_SRC = "assets/logo.svg";
const LINE_ID  = "@ms.brow";
const LINE_URL = "https://lin.ee/TKw4f1Z";
const IG_URL   = "https://www.instagram.com/ms.brow_tw/";

// ─── DATA ────────────────────────────────────────────────────────
const DATA = {
  lash: {
    groups: [
      {
        id: "popular",
        title: "人氣款式",
        en:    "Popular · Best Loved",
        meta:  "客人最常選擇的款式",
        items: [
          { zh: "嬰兒彎系列",     en: "Baby Curl",     desc: "柔和弧度，眼神更溫柔",       natural: 1599, dense: 1899 },
          { zh: "媽生感",         en: "Born Natural",  desc: "極細像天生自然的睫毛",       natural: 1599, dense: 1899 },
          { zh: "LC 野生漫畫風",  en: "LC Wild Manga", desc: "自然放大，同時帶一點個性感", natural: 1899, dense: 2099 },
          { zh: "超美狐系感",     en: "Fox Style",     desc: "上揚眼神，氣質拉長",         natural: 1899, dense: 2099 },
        ],
      },
      {
        id: "basic",
        title: "日常基礎",
        en:    "Basic · Daily Essentials",
        meta:  "自然乾淨　·　日常首選",
        items: [
          { zh: "日式單根系列", en: "Japanese · Single", desc: "自然微妝感，乾淨",   natural: 999,  dense: 1299 },
          { zh: "輕透少女風",   en: "Sheer Girl",        desc: "乾淨中帶一點精緻感", natural: 1599, dense: 1899 },
        ],
      },
      {
        id: "style",
        title: "風格設計",
        en:    "Style · By Mood",
        meta:  "依喜好挑選",
        items: [
          { zh: "元氣少女風",   en: "Vivid Girl",      desc: "長短層次分明，自然放大的效果", natural: 1899, dense: 2199 },
          { zh: "泰式淡顏風",   en: "Thai Soft Look",  desc: "低存在感，但眼神很有神",       natural: 1899, dense: 2199 },
          { zh: "小清新漫畫款", en: "Fresh Manga",     desc: "清爽乾淨，持久度超好",         natural: 1899, dense: 2199 },
          { zh: "網美睫毛膏款", en: "Mascara Look",    desc: "像刷過睫毛膏一樣精緻",         natural: 1599, dense: 1899 },
        ],
      },
    ],
  },

  custom: {
    eyebrow: "Custom Design",
    title:   "客製化系列",
    bodyZh:  "依眼型・氣質・日常妝感\n為您設計最適合的睫毛",
    quote:   "不是選款式\n而是找到適合妳的風格",
    keywords: ["清冷風", "富家千金感", "狐系", "媽生感", "歐美風"],
    closing: "最精緻的呈現",
  },

  lower: {
    title: "下睫毛",
    en:    "Lower Lash · Add-on",
    meta:  "細節延伸　·　完整眼神比例",
    items: [
      { zh: "30 根", note: "自然效果",   price: 300 },
      { zh: "40 根", note: "妝感層次",   price: 400 },
      { zh: "50 根", note: "濃妝感設計", price: 500 },
    ],
  },

  removal: {
    title: "卸睫",
    en:    "Removal · In-Salon & External",
    items: [
      { zh: "卸睫服務", note: "依狀況評估", price: 200, suffix: "起" },
    ],
  },

  semi: {
    eyebrow: "Semi-Permanent",
    title:   "半永久設計",
    sub:     "自然修飾｜長效精緻",
    items: [
      {
        en:    "Powder Brows",
        tc:    "霧眉",
        sub:   "柔霧邊界｜自然立體",
        body:  "以柔霧邊界打造自然立體的眉型線條，於恰到好處的層次中保留呼吸感。",
        price: 6999,
        ann:   "含一次補色",
      },
      {
        en:    "Lip Blush",
        tc:    "霧唇",
        sub:   "提升氣色｜日常不素顏",
        body:  "依膚色調整專屬色，讓唇色從根本提升氣色\n呈現乾淨｜柔和｜自然紅潤",
        price: 12800,
        ann:   "含一次補色",
      },
    ],
  },

  policy: {
    eyebrow: "Service Notes",
    title:   "消費介紹",
    intro:   "預約與服務說明",
    chapters: [
      { eyebrow: "Booking",   title: "預約流程",     body: "01｜加入官方 LINE 預約\n02｜選擇款式或由客服協助評估\n03｜確認時間，完成預約" },
      { eyebrow: "Service",   title: "施作流程",     body: "01｜現場溝通設計（依眼型｜氣質調整）\n02｜進行嫁接（約 1.5 ~ 2 小時）\n03｜完成後確認整體效果" },
      { eyebrow: "Aftercare", title: "施作後保養",   body: "｜ 6 小時內避免碰水與蒸氣\n｜ 避免油性產品接觸睫毛\n｜ 勿自行拉扯或卸除\n｜ 建議 2 ~ 3 週回來補接" },
      { eyebrow: "Notice",    title: "注意事項",     body: "｜ 如有遲到，可能影響施作內容\n｜ 眼睛較敏感或特殊狀況，請提前告知\n｜ 若有任何不適，請立即與我們聯繫" },
    ],
    closing: "每個人的眼型與條件不同\n我們會依當下狀況\n為妳調整最適合的設計",
  },

  member: {
    eyebrow: "Inner Circle",
    title:   "會員規則",
    sub:     "以細膩之約，回饋每一次相見",
    fee: 600,
    benefits: [
      { title: "會員價優惠",     body: "入會後，所有美睫服務皆享專屬會員價。" },
      { title: "集點兌換",       body: "每次美睫款式消費可集一點，集滿六點即可兌換 NT$500 抵用券。" },
      { title: "專屬會員禮",     body: "會員享預約時段優先排程，假日與熱門時段更從容。" },
      { title: "入會禮・生日禮", body: "入會當下即奉上一份小小心意；每年生辰之月，另有一份生日禮。" },
    ],
    notes: [
      "入會費 NT$600，會籍一年有效。",
      "抵用券限本人使用，不得兌換現金。",
    ],
  },
};

// ─── Brand mark (top of page; no easter egg here — moved to footer) ──
function Brand({ hideTagline }) {
  return (
    <header className="brand">
      <p className="brand-eyebrow">Ms.Brow Studio · Taipei</p>
      <div className="brand-logo">
        <img src={LOGO_SRC} alt="Ms.Brow" draggable={false} />
      </div>
      <span className="brand-divider" />
      {!hideTagline && <p className="brand-tagline">以靜為禮　·　以細為意</p>}
    </header>
  );
}

// ─── Faint logo backdrop — fades in after brand scrolls off, ─────────
//      fades out as footer approaches viewport
function LogoBackdrop() {
  const [visible, setVisible] = useState(false);
  useEffect(() => {
    const update = () => {
      const brand = document.querySelector(".brand");
      const foot  = document.querySelector(".foot");
      const vh    = window.innerHeight;
      const brandBottom = brand ? brand.getBoundingClientRect().bottom : 0;
      const footTop     = foot  ? foot.getBoundingClientRect().top     : Infinity;
      // Show once brand mostly scrolled off, hide as soon as footer is about to enter view
      setVisible(brandBottom < 40 && footTop > vh * 0.9);
    };
    update();
    window.addEventListener("scroll", update, { passive: true });
    window.addEventListener("resize", update);
    return () => {
      window.removeEventListener("scroll", update);
      window.removeEventListener("resize", update);
    };
  }, []);
  return (
    <div className={"logo-backdrop " + (visible ? "visible" : "")} aria-hidden="true">
      <img src={LOGO_SRC} alt="" draggable={false} />
    </div>
  );
}

// ─── Reusable pieces ─────────────────────────────────────────────
function PageHead({ eyebrow, title, sub }) {
  // For short titles (≤ 4 chars) spread with ideographic spaces for editorial feel.
  // Longer titles (5+) skip the spread so they fit on a single line at 375px width.
  const display = title.length <= 4 ? title.split("").join("　") : title;
  return (
    <div className="page-head">
      {eyebrow && <p className="eyebrow">{eyebrow}</p>}
      <h2 className="page-title">{display}</h2>
      {sub && <p className="page-sub ml">{sub}</p>}
    </div>
  );
}

function SectionHead({ title, en, meta }) {
  return (
    <>
      <div className="section-head">
        <h3 className="section-title">{title}</h3>
      </div>
      {en && <p className="section-en">{en}</p>}
      {meta && <p className="section-meta">{meta}</p>}
    </>
  );
}

function PriceAmount({ value, prefix = "NT$", suffix }) {
  return (
    <span className="price-amount">
      <span className="cur">{prefix}</span>
      <span className="num">{value.toLocaleString()}</span>
      {suffix && <span className="num-suffix">{suffix}</span>}
    </span>
  );
}

function PriceTiers({ natural, dense }) {
  return (
    <div className="price-tiers">
      <span className="price-tier">
        <span className="price-tier-label">淡妝感</span>
        <PriceAmount value={natural} />
      </span>
      <span className="price-tier">
        <span className="price-tier-label">濃妝感</span>
        <PriceAmount value={dense} />
      </span>
    </div>
  );
}

function Footer({ onUnlock }) {
  const clicksRef = useRef([]);
  const handle = () => {
    const now = Date.now();
    clicksRef.current = [...clicksRef.current, now].filter(t => now - t < 900);
    if (clicksRef.current.length >= 3) {
      clicksRef.current = [];
      onUnlock();
    }
  };
  return (
    <footer className="foot">
      <div className="foot-logo" onClick={handle} role="button" tabIndex={-1} aria-label="">
        <img src={LOGO_SRC} alt="Ms.Brow" draggable={false} />
      </div>
      <span className="foot-mark">Ms.Brow　·　Taipei</span>
    </footer>
  );
}

function IgIcon({ size = 28 }) {
  return (
    <svg
      viewBox="0 0 24 24"
      width={size}
      height={size}
      fill="currentColor"
      aria-hidden="true"
    >
      <path d="M12 2.163c3.204 0 3.584.012 4.85.07 3.252.148 4.771 1.691 4.919 4.919.058 1.265.069 1.645.069 4.849 0 3.205-.012 3.584-.069 4.849-.149 3.225-1.664 4.771-4.919 4.919-1.266.058-1.644.07-4.85.07-3.204 0-3.584-.012-4.849-.07-3.26-.149-4.771-1.699-4.919-4.92-.058-1.265-.07-1.644-.07-4.849 0-3.204.013-3.583.07-4.849.149-3.227 1.664-4.771 4.919-4.919 1.266-.057 1.645-.069 4.849-.069zM12 0C8.741 0 8.333.014 7.053.072 2.695.272.273 2.69.073 7.052.014 8.333 0 8.741 0 12c0 3.259.014 3.668.072 4.948.2 4.358 2.618 6.78 6.98 6.98C8.333 23.986 8.741 24 12 24c3.259 0 3.668-.014 4.948-.072 4.354-.2 6.782-2.618 6.979-6.98.059-1.28.073-1.689.073-4.948 0-3.259-.014-3.667-.072-4.947-.196-4.354-2.617-6.78-6.979-6.98C15.668.014 15.259 0 12 0zm0 5.838a6.162 6.162 0 100 12.324 6.162 6.162 0 000-12.324zM12 16a4 4 0 110-8 4 4 0 010 8zm6.406-11.845a1.44 1.44 0 100 2.881 1.44 1.44 0 000-2.881z"/>
    </svg>
  );
}

function LineCta({ note }) {
  return (
    <div className="cta-stack">
      <a className="cta-btn solid" href={LINE_URL} target="_blank" rel="noopener">LINE 預約</a>
      <a className="cta-btn ig" href={IG_URL} target="_blank" rel="noopener">
        <IgIcon size={22} />
        <span className="ig-label">instagram</span>
      </a>
      <span className="line-pill">{LINE_ID}</span>
      <span className="cta-note">{note || "By Appointment Only"}</span>
    </div>
  );
}

// ═══════════════════════════════════════════════════════════════
// QUICK-JUMP (頂部章節索引列)
// ═══════════════════════════════════════════════════════════════
const JUMPS = [
  { id: "popular", label: "人氣款式" },
  { id: "basic",   label: "日常基礎" },
  { id: "style",   label: "風格設計" },
  { id: "custom",  label: "客製化系列" },
  { id: "lower",   label: "下睫毛" },
  { id: "removal", label: "卸睫" },
  { id: "semi",    label: "半永久" },
  { id: "policy",  label: "消費介紹" },
];

function QuickJump({ active, setActive }) {
  useEffect(() => {
    const observer = new IntersectionObserver(
      (entries) => {
        const visible = entries
          .filter(e => e.isIntersecting)
          .sort((a, b) => a.target.offsetTop - b.target.offsetTop);
        if (visible.length > 0) {
          const id = visible[0].target.id.replace("sec-", "");
          setActive(id);
        }
      },
      { rootMargin: "-30% 0px -55% 0px", threshold: 0 }
    );
    JUMPS.forEach(it => {
      const el = document.getElementById("sec-" + it.id);
      if (el) observer.observe(el);
    });
    return () => observer.disconnect();
  }, []);

  const goto = (id) => {
    const el = document.getElementById("sec-" + id);
    if (el) {
      const rect = el.getBoundingClientRect();
      const offset = 110;
      window.scrollTo({ top: window.scrollY + rect.top - offset, behavior: "smooth" });
    }
    setActive(id);
  };

  return (
    <aside className="qjump" aria-label="快速跳轉">
      <ol>
        {JUMPS.map((it) => (
          <li key={it.id}>
            <button
              className={"qjump-item " + (active === it.id ? "on" : "")}
              onClick={() => goto(it.id)}
            >
              <span className="qjump-label">{it.label}</span>
            </button>
          </li>
        ))}
      </ol>
    </aside>
  );
}

// ═══════════════════════════════════════════════════════════════
// PAGE · 服務總覽 (single-page)
// ═══════════════════════════════════════════════════════════════
function ServicePage({ onUnlock }) {
  const dl = DATA.lash;
  const ds = DATA.semi;
  const dp = DATA.policy;
  const [active, setActive] = useState("popular");

  return (
    <div className="page" key="service">
      <QuickJump active={active} setActive={setActive} />

      <p className="price-disclaimer">價格均為新客體驗價</p>

      {dl.groups.map(g => (
        <section className="section" key={g.id} id={"sec-" + g.id}>
          <SectionHead title={g.title} en={g.en} meta={g.meta} />
          <ul className="price-list">
            {g.items.map((it) => (
              <li className="price-row lash" key={it.zh}>
                <div className="price-name">
                  <span className="price-name-zh">{it.zh}</span>
                  {it.en && <span className="price-name-en">{it.en}</span>}
                  {it.desc && <span className="price-name-note">{it.desc}</span>}
                </div>
                <PriceTiers natural={it.natural} dense={it.dense} />
              </li>
            ))}
          </ul>
        </section>
      ))}

      {/* CUSTOM block */}
      <section className="custom-block" id="sec-custom">
        <p className="eyebrow">{DATA.custom.eyebrow}</p>
        <h3 className="custom-title">{DATA.custom.title}</h3>
        <p className="body-zh ml" style={{ marginTop: 28 }}>{DATA.custom.bodyZh}</p>
        <p className="quote ml">{DATA.custom.quote}</p>
        <div className="keywords">
          {DATA.custom.keywords.map(k => <span key={k}>{k}</span>)}
        </div>
        {DATA.custom.closing && <p className="custom-closing">{DATA.custom.closing}</p>}
      </section>

      {/* LOWER LASH */}
      <section className="section" id="sec-lower">
        <SectionHead title={DATA.lower.title} en={DATA.lower.en} meta={DATA.lower.meta} />
        <ul className="price-list">
          {DATA.lower.items.map(it => (
            <li className="price-row" key={it.zh}>
              <div className="price-name">
                <span className="price-name-zh">{it.zh}</span>
                {it.note && <span className="price-name-note">{it.note}</span>}
              </div>
              <PriceAmount value={it.price} />
            </li>
          ))}
        </ul>
      </section>

      {/* REMOVAL */}
      <section className="section" id="sec-removal">
        <SectionHead title={DATA.removal.title} en={DATA.removal.en} />
        <ul className="price-list">
          {DATA.removal.items.map((it, i) => (
            <li className="price-row" key={i}>
              <div className="price-name">
                <span className="price-name-zh">{it.zh}</span>
                {it.note && <span className="price-name-note">{it.note}</span>}
              </div>
              <PriceAmount value={it.price} suffix={it.suffix} />
            </li>
          ))}
        </ul>
      </section>

      {/* ── SEMI-PERMANENT chapter ──────────────────────────────── */}
      <div className="chapter-divider" id="sec-semi">
        <PageHead eyebrow={ds.eyebrow} title={ds.title} sub={ds.sub} />
      </div>

      {ds.items.map((it, i) => (
        <article className="semi-card" key={it.en}>
          <h3 className="en">{it.en}</h3>
          <p className="tc">{it.tc.split("").join("　")}</p>
          <p className="sub">{it.sub}</p>
          <p className="body ml">{it.body}</p>
          <div className="pricing">
            <PriceAmount value={it.price} />
            <span className="ann">{it.ann}</span>
          </div>
        </article>
      ))}

      {/* ── POLICY chapter ──────────────────────────────────────── */}
      <div className="chapter-divider" id="sec-policy">
        <PageHead eyebrow={dp.eyebrow} title={dp.title} sub={null} />
      </div>
      <p className="page-sub ml" style={{ textAlign: "center", maxWidth: 320, margin: "-12px auto 0" }}>{dp.intro}</p>

      <div className="policy-list">
        {dp.chapters.map((ch, i) => (
          <article className="policy-chapter" key={i}>
            <div className="policy-marker">
              <span className="policy-num">{String(i + 1).padStart(2, "0")}</span>
              <span className="policy-eyebrow">{ch.eyebrow}</span>
            </div>
            <h3 className="policy-title">{ch.title}</h3>
            <p className="policy-body ml">{ch.body}</p>
          </article>
        ))}
      </div>

      <div className="policy-closing">
        <span className="policy-closing-line" aria-hidden="true" />
        <p className="policy-closing-text ml">{dp.closing}</p>
        <span className="policy-closing-line" aria-hidden="true" />
      </div>

      <LineCta />
      <Footer onUnlock={onUnlock} />
    </div>
  );
}

// ═══════════════════════════════════════════════════════════════
// PAGE · 會員規則 (hidden — unlocked via triple-click)
// ═══════════════════════════════════════════════════════════════
function MemberPage({ onBack, onUnlock }) {
  const d = DATA.member;
  return (
    <div className="page" key="member">
      <PageHead eyebrow={d.eyebrow} title={d.title} sub={d.sub} />

      <div className="member-card">
        <div className="fee-block">
          <p className="fee-label">入會費</p>
          <p className="fee-amount">
            <span className="cur">NT$</span>
            <span className="num">{d.fee}</span>
          </p>
        </div>

        <div className="benefits">
          <p className="benefits-title">會員權益</p>
          <ul className="benefits-list">
            {d.benefits.map((b, i) => (
              <li className="benefit" key={i}>
                <span className="benefit-num">{String(i + 1).padStart(2, "0")}</span>
                <p className="benefit-body">
                  <b>{b.title}</b>
                  <br />
                  {b.body}
                </p>
              </li>
            ))}
          </ul>
        </div>
      </div>

      <section className="section" style={{ marginTop: 40 }}>
        <SectionHead title="注意事項" en="Notes" />
        <ul className="price-list" style={{ borderTop: "1px solid var(--hairline-soft)" }}>
          {d.notes.map((n, i) => (
            <li className="price-row" key={i} style={{ gridTemplateColumns: "auto 1fr", gap: 16, alignItems: "start" }}>
              <span className="price-name-en" style={{ paddingTop: 2 }}>
                {String(i + 1).padStart(2, "0")}
              </span>
              <span className="benefit-body">{n}</span>
            </li>
          ))}
        </ul>
      </section>

      <div style={{ textAlign: "center", marginTop: 40 }}>
        <button className="member-back" onClick={onBack}>返回首頁</button>
      </div>

      <Footer onUnlock={onUnlock} />
    </div>
  );
}

// ═══════════════════════════════════════════════════════════════
// APP
// ═══════════════════════════════════════════════════════════════
// URL hash routing — share /#member to land directly on the member page
const HASH_MEMBER = "member";
const readPageFromHash = () =>
  window.location.hash.replace(/^#\/?/, "") === HASH_MEMBER ? "member" : "service";

// Apply ?theme=<variant> to <html data-theme>. Default (no param) = A version.
//   ?theme=snow   → B version (cool snow palette)
//   ?theme=bubbel → C version (warm cream/champagne palette)
const THEMES = new Set(["snow", "bubbel"]);
const applyThemeFromUrl = () => {
  const theme = new URLSearchParams(window.location.search).get("theme");
  const root = document.documentElement;
  if (theme && THEMES.has(theme)) root.setAttribute("data-theme", theme);
  else root.removeAttribute("data-theme");
};
applyThemeFromUrl();

function App() {
  const [page, setPage] = useState(readPageFromHash);
  const [toastOn, setToastOn] = useState(false);
  const [toastText, setToastText] = useState("");

  // Snap to top whenever the page swaps (member ↔ service).
  // Runs after React commits the new DOM, so document height has already
  // shrunk to the new page's size — clamping issues are avoided.
  useEffect(() => {
    window.scrollTo({ top: 0, behavior: "instant" });
  }, [page]);

  // Keep URL hash in sync with page state so the member page is shareable.
  useEffect(() => {
    const want = page === "member" ? "#" + HASH_MEMBER : "";
    if (window.location.hash !== want) {
      const base = window.location.pathname + window.location.search;
      window.history.replaceState(null, "", want ? base + want : base);
    }
  }, [page]);

  // React to browser back/forward (or manual hash edits).
  useEffect(() => {
    const onHashChange = () => setPage(readPageFromHash());
    window.addEventListener("hashchange", onHashChange);
    return () => window.removeEventListener("hashchange", onHashChange);
  }, []);

  const showToast = (txt) => {
    setToastText(txt);
    setToastOn(true);
    setTimeout(() => setToastOn(false), 2600);
  };

  const onUnlock = () => {
    if (page === "member") return;
    showToast("Inner Circle · Unlocked");
    setTimeout(() => {
      setPage("member");
    }, 700);
  };

  return (
    <div className="app">
      <Brand hideTagline={page === "member"} />
      <LogoBackdrop />
      <main>
        {page === "member"
          ? <MemberPage onUnlock={onUnlock} onBack={() => setPage("service")} />
          : <ServicePage onUnlock={onUnlock} />}
      </main>

      <div className={"toast " + (toastOn ? "on" : "")}>{toastText}</div>
    </div>
  );
}

const root = ReactDOM.createRoot(document.getElementById("root"));
root.render(<App />);
