const { useState, useEffect, useMemo } = React;

const TWEAK_DEFAULTS = /*EDITMODE-BEGIN*/{
  "accent": "#B23A2E",
  "displayFont": "Shippori Mincho",
  "showKanjiRail": true,
  "compactSchedule": false
}/*EDITMODE-END*/;

/* ----------------------------- DATA ------------------------------ */

const NIKKO_LEGS = [
  { time: "07:00", end: null,    type: "anchor",   title: "Depart Minami-Otsuka", desc: "Pickup at Ikisumi Apartment lobby. Driver shift begins.", chips: [] },
  { time: "07:00", end: "09:00", type: "drive",    title: "Drive — Tokyo → Hasuda SA", desc: "Tohoku Expressway northbound.", chips: [{ k:"dist", v:"~70 km" }, { k:"dur", v:"2h 00m", accent:false }] },
  { time: "09:00", end: "09:10", type: "stop",     title: "Hasuda SA — Service Area Stop", desc: "Restroom & stretch.", chips: [{ k:"dur", v:"10 min" }] },
  { time: "09:10", end: "09:55", type: "drive",    title: "Drive — Hasuda SA → Nikko IC", desc: "Continue Tohoku Expressway.", chips: [{ k:"dist", v:"~80 km" }, { k:"dur", v:"45 min" }] },
  { time: "09:55", end: "10:45", type: "drive",    title: "Drive — Irohazaka → Chuzenji-ko Parking", desc: "Switchback ascent (いろは坂).", chips: [{ k:"dist", v:"~25 km" }, { k:"dur", v:"50 min" }] },
  { time: "10:45", end: "10:55", type: "stop",     title: "Park · Walk to Pier · Buy Cruise Ticket", desc: "Short walk from parking to ferry terminal.", chips: [{ k:"dur", v:"10 min" }] },
  { time: "11:00", end: "11:55", type: "activity", title: "Lake Chuzenji Cruise", desc: "Full-loop scenic cruise. 中禅寺湖.", chips: [{ k:"dur", v:"55 min", accent:true }] },
  { time: "11:55", end: "12:05", type: "drive",    title: "Walk to Kegon Falls", desc: "Short walk to the falls observation building.", chips: [{ k:"dist", v:"0.4 km" }, { k:"dur", v:"10 min" }] },
  { time: "12:05", end: "12:45", type: "activity", title: "Kegon Falls", desc: "Observation deck + elevator down. 華厳の滝.", chips: [{ k:"dur", v:"40 min", accent:true }] },
  { time: "12:45", end: "13:00", type: "stop",     title: "Quick Lunch in Car", desc: "Onigiri / konbini-style on the move.", chips: [{ k:"dur", v:"15 min" }] },
  { time: "13:00", end: "13:40", type: "drive",    title: "Drive — Irohazaka Descent → Shinkyo", desc: "Down the mountain to Shinkyo Bridge.", chips: [{ k:"dist", v:"~20 km" }, { k:"dur", v:"40 min" }] },
  { time: "13:40", end: "13:50", type: "stop",     title: "Shinkyo Bridge — Photo Stop", desc: "神橋 vermillion bridge over Daiya River.", chips: [{ k:"dur", v:"10 min" }] },
  { time: "13:50", end: "14:10", type: "drive",    title: "Drive — Shinkyo → Nikko Strawberry Park", desc: "Short transfer.", chips: [{ k:"dist", v:"~11 km" }, { k:"dur", v:"20 min" }] },
  { time: "14:10", end: "14:55", type: "activity", title: "Nikko Strawberry Park", desc: "Reservation 14:00 · 30-min picking. いちご狩り.", chips: [{ k:"resv", v:"Resv 14:00", accent:true }, { k:"dur", v:"45 min" }] },
  { time: "14:55", end: "17:00", type: "drive",    title: "Drive — Strawberry Park → Minami-Otsuka", desc: "Return to Tokyo. Expressway southbound.", chips: [{ k:"dist", v:"~145 km" }, { k:"dur", v:"2h 05m" }] },
  { time: "17:00", end: null,    type: "anchor",   title: "Arrive Minami-Otsuka", desc: "Driver shift ends.", chips: [] }
];

const HOTELS = [
  { name: "Ikisumi Apartment", role: "Tokyo base — pickup & drop-off", addr: "1 Chome-33-8 Minamiotsuka, Toshima City, Tokyo 170-0005, Japan" },
  { name: "Mimaru Osaka Shinsaibashi North Hotel", role: "Osaka leg accommodation", addr: "2 Chome-4-18 Minamisenba, Chuo Ward, Osaka, 542-0081, Japan" }
];

const SERVICES = [
  { name: "Kimono Experience",            jp: "着物体験",         price: "8,000",  unit: "per pax" },
  { name: "Kimono Photography",           jp: "着物撮影",         price: "15,000", unit: "8 hours" },
  { name: "Samurai Experience",           jp: "侍体験",           price: "15,000", unit: "per pax" },
  { name: "Sushi Making Experience",      jp: "寿司作り体験",     price: "12,000", unit: "per pax" },
  { name: "Japanese Tea Ceremony",        jp: "茶道体験",         price: "12,000", unit: "per pax" },
  { name: "Street Go-Kart Experience",    jp: "ストリートカート", price: "20,000", unit: "per pax" },
  { name: "Sumo Experience",              jp: "相撲体験",         price: "17,000", unit: "per pax" }
];

const NOTES = [
  { tag:"01", html: "<b>Vehicle Usage.</b> Vehicle available for 10 hours between 08:00 and 20:00. Any usage past 20:00, even if total under 10h, is charged as overtime." },
  { tag:"02", html: "<b>Overtime.</b> 10,000 JPY per hour, payable directly to the driver in cash." },
  { tag:"03", html: "<b>Language.</b> Drivers are primarily Chinese & Japanese-speaking with minimal English. Translation apps are used for communication with English-speaking guests." },
  { tag:"04", html: "<b>Exploration.</b> A tour guide add-on is recommended — the driver cannot leave the Coaster to escort guests at attractions." }
];

const DAYS = [
  {
    id: "nikko",
    date: "2026-05-16",
    label: "May 16",
    weekday: "Saturday",
    name: "Nikko",
    jp: "日光",
    summary: { distance: "~351 km", driving: "6h 40m", anchor: "07:00 — 17:00" },
    legs: NIKKO_LEGS,
    railText: "日光・中禅寺湖・華厳の滝・神橋"
  },
  {
    id: "kawagoe",
    date: "2026-05-17",
    label: "May 17",
    weekday: "Sunday",
    name: "Kawagoe",
    jp: "川越",
    summary: { distance: "—", driving: "—", anchor: "TBC" },
    legs: null,
    railText: "川越・小江戸・蔵造りの町"
  }
];

/* --------------------------- ICONS ------------------------------- */

const Icon = {
  dist: () => <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2"><path d="M3 12h18"/><path d="M7 8l-4 4 4 4"/><path d="M17 8l4 4-4 4"/></svg>,
  clock: () => <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2"><circle cx="12" cy="12" r="9"/><path d="M12 7v5l3 2"/></svg>,
  pin: () => <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2"><path d="M12 22s7-7.5 7-13a7 7 0 1 0-14 0c0 5.5 7 13 7 13z"/><circle cx="12" cy="9" r="2.5"/></svg>,
  ext: () => <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2"><path d="M14 4h6v6"/><path d="M20 4l-9 9"/><path d="M19 14v5a1 1 0 0 1-1 1H5a1 1 0 0 1-1-1V6a1 1 0 0 1 1-1h5"/></svg>,
  chev: () => <svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2"><path d="M6 9l6 6 6-6"/></svg>,
  copy: () => <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2"><rect x="9" y="9" width="11" height="11" rx="2"/><path d="M5 15V5a1 1 0 0 1 1-1h10"/></svg>
};

/* ------------------------- COMPONENTS --------------------------- */

function BrandMark(){
  return (
    <div className="brand">
      <div className="brand-mark">和</div>
      <div>
        <div className="brand-name">Wanasia</div>
      </div>
    </div>
  );
}

function Hero({ trip }){
  return (
    <div className="hero">
      <div className="eyebrow">Trip Manifest · 旅程表</div>
      <h1>Tuan Hj Khalidon &amp; Family</h1>
      <div className="jp">ハジ・ハリドン様御一行</div>
      <div className="hero-meta">
        <div>
          <div className="m-label">Dates</div>
          <div className="m-value">May 16 – 17<br/><small style={{color:"var(--ink-faint)",fontSize:"11px"}}>2 days · 2 destinations</small></div>
        </div>
        <div>
          <div className="m-label">Pax</div>
          <div className="m-value">Family of 6<br/><small style={{color:"var(--ink-faint)",fontSize:"11px"}}>Coaster · 1 driver</small></div>
        </div>
        <div>
          <div className="m-label">Lang</div>
          <div className="m-value">EN · MS<br/><small style={{color:"var(--ink-faint)",fontSize:"11px"}}>JP / ZH driver</small></div>
        </div>
      </div>
    </div>
  );
}

function DaySwitcher({ days, activeId, setActiveId, todayIso }){
  return (
    <div className="days" role="tablist">
      {days.map(d => {
        const isToday = d.date === todayIso;
        const sel = d.id === activeId;
        return (
          <button
            key={d.id}
            role="tab"
            aria-selected={sel}
            className="day-pill"
            onClick={() => setActiveId(d.id)}
          >
            <div className="dp-top">
              <span>Day {days.indexOf(d)+1} · {d.label}</span>
              {isToday && <span className="badge-today">Today</span>}
            </div>
            <div className="dp-name">{d.name}</div>
            <div className="dp-jp">{d.jp} · {d.weekday}</div>
          </button>
        );
      })}
    </div>
  );
}

function Chip({ c }){
  const icon = c.k === "dist" ? <Icon.dist/> : c.k === "resv" ? <Icon.pin/> : <Icon.clock/>;
  return <span className={"chip " + (c.accent ? "accent" : c.k === "dur" ? "dur" : "")}>{icon}{c.v}</span>;
}

function Leg({ leg, isNow, compact }){
  return (
    <div className={"leg " + (isNow ? "now " : "") + (compact ? "compact" : "")} data-type={leg.type}>
      <div className="time">
        <div>{leg.time}</div>
        {leg.end && <div className="end">↓ {leg.end}</div>}
      </div>
      <div className="body">
        <div className="title">
          {leg.title}
          {isNow && <span className="now-tag">Now</span>}
        </div>
        {leg.desc && <div className="desc">{leg.desc}</div>}
        {leg.chips && leg.chips.length > 0 && (
          <div className="meta">{leg.chips.map((c, i) => <Chip key={i} c={c}/>)}</div>
        )}
      </div>
    </div>
  );
}

function Timeline({ day, nowMinutes, showKanjiRail, compact }){
  // Determine which leg is "now" — only if today
  const isToday = day._isToday;
  let nowIdx = -1;
  if (isToday && nowMinutes != null && day.legs){
    for (let i = 0; i < day.legs.length; i++){
      const l = day.legs[i];
      const start = toMin(l.time);
      const end = l.end ? toMin(l.end) : start + 1;
      if (nowMinutes >= start && nowMinutes < end){ nowIdx = i; break; }
    }
  }
  return (
    <div className="timeline fade">
      {showKanjiRail && <div className="kanji-rail">{day.railText}</div>}
      {day.legs.map((l, i) => <Leg key={i} leg={l} isNow={i === nowIdx} compact={compact}/>)}
    </div>
  );
}

function toMin(t){ const [h,m] = t.split(":").map(Number); return h*60+m; }

function DaySummary({ s }){
  return (
    <div className="day-summary">
      <div>
        <div className="lbl">Distance</div>
        <div className="val">{s.distance}</div>
      </div>
      <div>
        <div className="lbl">Driving</div>
        <div className="val">{s.driving}</div>
      </div>
      <div>
        <div className="lbl">Shift</div>
        <div className="val">{s.anchor}</div>
      </div>
    </div>
  );
}

function TBC({ day }){
  return (
    <div className="tbc fade">
      <h3>{day.name} · {day.jp}</h3>
      <p>Itinerary is being finalised by the operations team.<br/>Confirmation expected by 18:00 (day prior).</p>
      <div className="jp">行程確定中</div>
    </div>
  );
}

function HotelCard({ h }){
  const mapsUrl = "https://maps.google.com/?q=" + encodeURIComponent(h.addr);
  return (
    <div className="row">
      <div className="label">{h.role}</div>
      <div className="val-title">{h.name}</div>
      <div className="val">{h.addr}</div>
      <div className="actions">
        <a className="pill-link" href={mapsUrl} target="_blank" rel="noreferrer"><Icon.pin/> Maps</a>
        <button className="pill-link" onClick={() => { navigator.clipboard?.writeText(h.addr); }}><Icon.copy/> Copy</button>
      </div>
    </div>
  );
}

/* --------------------------- APP --------------------------------- */

function App(){
  const [t, setTweak] = useTweaks(TWEAK_DEFAULTS);

  // For demo / "now" highlight — pretend we're on 05/16 at 11:30
  const FAKE_NOW = useMemo(() => ({ date: "2026-05-16", minutes: 11*60 + 30 }), []);
  const todayIso = FAKE_NOW.date;

  const [activeId, setActiveId] = useState(() => {
    // Start on today if it's in the list, else first day
    const todayDay = DAYS.find(d => d.date === todayIso);
    return todayDay ? todayDay.id : DAYS[0].id;
  });

  // Apply tweaks
  useEffect(() => {
    document.documentElement.style.setProperty("--accent", t.accent);
    document.documentElement.style.setProperty("--display", `"${t.displayFont}", "Noto Serif JP", serif`);
  }, [t.accent, t.displayFont]);

  const active = DAYS.find(d => d.id === activeId);
  active._isToday = active.date === todayIso;

  return (
    <>
      <div className="shell">
        <div className="topbar">
          <BrandMark/>
          <div className="top-meta">
            <div><b>Trip Display</b></div>
            <div>v.2026.05.15 · 22:14 JST</div>
          </div>
        </div>

        <Hero/>

        <div className="sec-head">
          <h2>Itinerary <span className="jp">行程</span></h2>
          <div className="right">2 Days</div>
        </div>

        <DaySwitcher days={DAYS} activeId={activeId} setActiveId={setActiveId} todayIso={todayIso}/>

        <div className="sec-head" style={{marginTop: 22}}>
          <h2>
            {active.name} <span className="jp">{active.jp}</span>
          </h2>
          <div className="right">{active.weekday} · {active.label}</div>
        </div>

        {active.legs
          ? <>
              <Timeline day={active} nowMinutes={FAKE_NOW.minutes} showKanjiRail={t.showKanjiRail} compact={t.compactSchedule}/>
              <DaySummary s={active.summary}/>
            </>
          : <TBC day={active}/>
        }

        <div className="sec-head"><h2>Accommodation <span className="jp">宿泊</span></h2></div>
        <div className="card">
          {HOTELS.map((h, i) => <HotelCard key={i} h={h}/>)}
        </div>

        <div className="sec-head"><h2>Add-on Experiences <span className="jp">体験オプション</span></h2></div>
        <div className="card">
          <details className="acc" open>
            <summary>
              <div className="s-left">
                <span className="s-title">Available on request</span>
                <span className="s-jp">追加料金</span>
              </div>
              <span className="chev"><Icon.chev/></span>
            </summary>
            <div className="acc-body">
              {SERVICES.map((s, i) => (
                <div className="svc" key={i}>
                  <div className="s-name">
                    {s.name}
                    <small>{s.jp}</small>
                  </div>
                  <div className="s-price"><b>¥{s.price}</b> / {s.unit}</div>
                </div>
              ))}
              <div style={{fontFamily:"var(--mono)", fontSize:10, color:"var(--ink-faint)", letterSpacing:"0.1em", marginTop:10, paddingTop:10, borderTop:"1px dashed var(--line-soft)"}}>
                * Reservations require 24h advance notice.
              </div>
            </div>
          </details>
        </div>

        <div className="sec-head"><h2>Notes <span className="jp">ご案内</span></h2></div>
        <div className="card" style={{padding:"14px 16px"}}>
          <ul className="notes-list">
            {NOTES.map((n, i) => (
              <li key={i}>
                <span className="ni">{n.tag}</span>
                <span dangerouslySetInnerHTML={{__html: n.html}}/>
              </li>
            ))}
          </ul>
        </div>

        <div className="footer-note">
          <div className="logo-sm"><i/>Wanasia</div>
          <div>Operations · <a href="tel:+601110139181" style={{color:"inherit",textDecoration:"none"}}>+6011-1013 9181</a></div>
        </div>
      </div>

      <TweaksPanel title="Tweaks">
        <TweakSection label="Theme">
          <TweakColor
            label="Accent (朱)"
            value={t.accent}
            options={["#B23A2E", "#1F4E79", "#2F5D3A", "#7C5A19", "#1F1F1F"]}
            onChange={(v) => setTweak("accent", v)}
          />
          <TweakSelect
            label="Display font"
            value={t.displayFont}
            options={["Shippori Mincho", "Noto Serif JP", "Noto Sans JP"]}
            onChange={(v) => setTweak("displayFont", v)}
          />
        </TweakSection>
        <TweakSection label="Schedule">
          <TweakToggle
            label="Kanji rail"
            value={t.showKanjiRail}
            onChange={(v) => setTweak("showKanjiRail", v)}
          />
          <TweakToggle
            label="Compact schedule"
            value={t.compactSchedule}
            onChange={(v) => setTweak("compactSchedule", v)}
          />
        </TweakSection>
      </TweaksPanel>
    </>
  );
}

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