// 高雄旅行の栞 — メインアプリ
const { useState, useEffect, useMemo } = React;

const TWEAK_DEFAULTS = /*EDITMODE-BEGIN*/{
  "theme": "tropical",
  "font": "sans"
}/*EDITMODE-END*/;

const TAG_LABEL = {
  flight: "フライト",
  move: "移動",
  hotel: "ホテル",
  sight: "観光",
  food: "グルメ",
  rest: "休憩",
  shop: "ショッピング",
};

const TAG_DOT = {
  flight: "var(--c3)",
  move: "var(--c5)",
  hotel: "var(--c6)",
  sight: "var(--c4)",
  food: "var(--c2)",
  rest: "var(--ink-soft)",
  shop: "var(--c6)",
};

const TAG_HEX = {
  flight: "#ffd43b",
  move:   "#22b8cf",
  hotel:  "#cc5de8",
  sight:  "#51cf66",
  food:   "#ffa94d",
  rest:   "#8a7e74",
  shop:   "#cc5de8",
};

function Cover({ data }) {
  return (
    <header className="cover">
      <div className="eyebrow">KAOHSIUNG · TAIWAN</div>
      <h1>GW高雄<span className="accent">の</span><br/>旅<span className="accent">の</span>栞</h1>
      <div className="sub">{data.dates} ／ {data.subtitle} ／ {data.party}</div>
      <div className="meta">
        <span className="chip">5泊6日</span>
        <span className="chip">高雄＋台南</span>
        <span className="chip">MRT・バス</span>
      </div>
    </header>
  );
}

function Tabs({ tabs, active, onChange }) {
  useEffect(() => {
    const el = document.querySelector(`.tab[data-key="${active}"]`);
    if (el && el.scrollIntoViewIfNeeded) el.scrollIntoViewIfNeeded({ block: "nearest" });
  }, [active]);
  return (
    <nav className="tabs" role="tablist">
      {tabs.map((t, i) => (
        <button
          key={t.key}
          data-key={t.key}
          className={`tab ${active === t.key ? "active" : ""}`}
          onClick={() => onChange(t.key)}
          role="tab"
        >
          {t.num != null && <span className="tab-num">{String(t.num).padStart(2,"0")}</span>}
          <span>{t.label}</span>
        </button>
      ))}
    </nav>
  );
}

function Weather({ w }) {
  if (!w) return null;
  return (
    <div className="weather">
      <div className="icon">{w.icon}</div>
      <div className="desc">{w.desc}</div>
      <div className="temp">{w.temp}</div>
      <div className="rain">☔ {w.rain}</div>
    </div>
  );
}

function Event({ ev, idx }) {
  return (
    <div className="event" data-tag={ev.tag} data-screen-label={`${ev.time} ${ev.title}`}>
      <div className="time">{ev.time}</div>
      <span className="marker">{idx ? <span className="marker-num">{idx}</span> : null}</span>
      <div className="card">
        <div className="title-row">
          <h3>{ev.title}</h3>
          <span className="tag-pill">{TAG_LABEL[ev.tag] || ""}</span>
        </div>
        {ev.note && <div className="note">{ev.note}</div>}
        {ev.mapQuery && (
          <a className="map-link" target="_blank" rel="noopener"
             href={`https://www.google.com/maps/search/?api=1&query=${encodeURIComponent(ev.mapQuery)}`}>
            Googleマップで開く
          </a>
        )}
      </div>
    </div>
  );
}

function DayMap({ day }) {
  const id = React.useMemo(() => `map-${Math.random().toString(36).slice(2, 8)}`, [day]);
  const events = day.events.filter(e => e.lat && e.lng);
  useEffect(() => {
    if (!events.length || !window.L) return;
    const map = L.map(id, { zoomControl: true, scrollWheelZoom: false });
    L.tileLayer('https://{s}.basemaps.cartocdn.com/rastertiles/voyager/{z}/{x}/{y}.png', {
      attribution: '&copy; OpenStreetMap &copy; CARTO',
      maxZoom: 19,
    }).addTo(map);
    const bounds = L.latLngBounds(events.map(e => [e.lat, e.lng]));
    const polyline = L.polyline(events.map(e => [e.lat, e.lng]), {
      color: '#2a1f1a', weight: 2, opacity: .35, dashArray: '4,6',
    }).addTo(map);
    events.forEach((e, i) => {
      const color = TAG_HEX[e.tag] || '#ff6b6b';
      const icon = L.divIcon({
        className: '',
        html: `<div class="pin" style="background:${color}"><span>${i + 1}</span></div>`,
        iconSize: [30, 30],
        iconAnchor: [15, 28],
        popupAnchor: [0, -26],
      });
      L.marker([e.lat, e.lng], { icon }).addTo(map)
        .bindPopup(`<div class="pin-popup"><div class="pp-time">${e.time}</div>${e.title}</div>`);
    });
    if (events.length > 1) {
      map.fitBounds(bounds, { padding: [40, 40] });
    } else {
      map.setView([events[0].lat, events[0].lng], 14);
    }
    return () => map.remove();
  }, [day, id]);
  if (!events.length) return null;
  return (
    <div className="map-wrap">
      <div id={id} className="leaflet-map"></div>
      <div className="map-caption">
        <span>📍 {day.label} エリア　ピン {events.length} 個</span>
        <a target="_blank" rel="noopener"
           href={`https://www.google.com/maps/search/?api=1&query=${encodeURIComponent(events[0].mapQuery || day.label)}`}>
           Googleマップ →
        </a>
      </div>
    </div>
  );
}

function Legend() {
  const items = [
    { k: "sight", n: "観光" },
    { k: "food", n: "グルメ" },
    { k: "move", n: "移動" },
    { k: "hotel", n: "ホテル" },
    { k: "flight", n: "フライト" },
    { k: "rest", n: "休憩" },
  ];
  return (
    <div className="legend">
      {items.map(i => (
        <span className="l" key={i.k}>
          <span className="ldot" style={{background: TAG_DOT[i.k]}}></span>{i.n}
        </span>
      ))}
    </div>
  );
}

function HolidayBadge({ holiday }) {
  if (!holiday) return null;
  const isWeekend = holiday === "週末";
  return <span className={`holiday-badge ${isWeekend ? "weekend" : ""}`}>{holiday}</span>;
}

function DayView({ day, dayNum }) {
  return (
    <section data-screen-label={`Day ${dayNum} ${day.date}`}>
      <div className="day-head">
        <div className="row">
          <div className="date-block">
            <div className="date-num">
              {day.date.split("/")[0]}<span className="sep">/</span>{day.date.split("/")[1]}
              <HolidayBadge holiday={day.holiday} />
            </div>
            <div className="dow">{day.dow.toUpperCase()}DAY · DAY {dayNum}</div>
            <span className="label">{day.label}</span>
            <div className="theme">{day.theme}</div>
            {day.note && <div className="day-note">{day.note}</div>}
          </div>
          <Weather w={day.weather} />
        </div>
      </div>
      <DayMap day={day} />
      <Legend />
      <div className="timeline">
        {day.events.map((ev, i) => <Event key={i} ev={ev} idx={i + 1} />)}
      </div>
    </section>
  );
}

function HotelTab({ data }) {
  return (
    <section data-screen-label="Hotel">
      <div className="section">
        <div className="section-title">
          <h2>滞在ホテル</h2>
          <div className="stripe"></div>
        </div>
      </div>
      <div className="hotel-card">
        <div className="hk">YOUR STAY</div>
        <h3>{data.hotel.name}</h3>
        <div className="name-jp">{data.hotel.nameJp}</div>
        <dl className="info">
          <dt>住所</dt><dd>{data.hotel.address}</dd>
          <dt>滞在</dt><dd>{data.hotel.nights}</dd>
        </dl>
      </div>
      <div className="map-wrap" style={{marginTop: 16}}>
        <div id="hotel-map" className="leaflet-map" ref={(el) => {
          if (!el || el.dataset.init) return;
          el.dataset.init = "1";
          const map = L.map(el).setView([data.hotel.lat, data.hotel.lng], 15);
          L.tileLayer('https://{s}.basemaps.cartocdn.com/rastertiles/voyager/{z}/{x}/{y}.png', {
            attribution: '&copy; OpenStreetMap &copy; CARTO', maxZoom: 19,
          }).addTo(map);
          const icon = L.divIcon({
            className: '',
            html: `<div class="pin" style="background:#cc5de8"><span>H</span></div>`,
            iconSize: [30, 30], iconAnchor: [15, 28], popupAnchor: [0, -26],
          });
          L.marker([data.hotel.lat, data.hotel.lng], { icon }).addTo(map)
            .bindPopup(`<div class="pin-popup">${data.hotel.name}</div>`).openPopup();
        }}></div>
        <div className="map-caption">
          <span>📍 新興区</span>
          <a target="_blank" rel="noopener" href={data.hotel.mapLink}>Googleマップ →</a>
        </div>
      </div>

      <div className="section">
        <div className="section-title">
          <h2>フライト</h2>
          <div className="stripe"></div>
        </div>
      </div>
      <div className="flights">
        {[data.flights.out, data.flights.ret].map((f, i) => (
          <div className="flight" key={i}>
            <span className="code">{f.code}</span>
            <div className="from">
              <span className="iata">{f.from}</span>
              <span className="time">{f.dep}</span>
            </div>
            <span className="arrow">→</span>
            <div className="to">
              <span className="iata">{f.to}</span>
              <span className="time">{f.arr}</span>
            </div>
          </div>
        ))}
      </div>

      <div className="section">
        <div className="section-title">
          <h2>旅のメモ</h2>
          <div className="stripe"></div>
        </div>
      </div>
      <div className="tips">
        <dl>
          {data.tips.map((t,i) => (
            <React.Fragment key={i}>
              <dt>{t.k}</dt><dd>{t.v}</dd>
            </React.Fragment>
          ))}
        </dl>
      </div>
    </section>
  );
}

function ListTab({ title, items, storageKey }) {
  const [checked, setChecked] = useState(() => {
    try { return JSON.parse(localStorage.getItem(storageKey) || "{}"); }
    catch { return {}; }
  });
  const toggle = (i) => {
    const next = { ...checked, [i]: !checked[i] };
    setChecked(next);
    localStorage.setItem(storageKey, JSON.stringify(next));
  };
  const doneCount = Object.values(checked).filter(Boolean).length;
  return (
    <section data-screen-label={title}>
      <div className="section">
        <div className="section-title">
          <h2>{title}</h2>
          <div className="stripe"></div>
          <span style={{fontSize:11, color:"var(--ink-soft)", letterSpacing:".05em"}}>
            {doneCount}/{items.length}
          </span>
        </div>
      </div>
      <div className="list-grid">
        {items.map((it, i) => (
          <div className={`list-item ${checked[i] ? "checked" : ""}`} key={i}>
            <div className="num">{String(i+1).padStart(2,"0")}</div>
            <div className="body">
              <div className="name">{it.name}</div>
              {it.desc && <div className="desc">{it.desc}</div>}
              {(it.where || it.note) && <div className="where">{it.where || it.note}</div>}
            </div>
            <button className="check" onClick={() => toggle(i)} aria-label="check">✓</button>
          </div>
        ))}
      </div>
    </section>
  );
}

function App() {
  const data = window.TRIP_DATA;
  const [t, setTweak] = useTweaks(TWEAK_DEFAULTS);
  const [active, setActive] = useState(() => localStorage.getItem("kh:active") || "day1");

  useEffect(() => { localStorage.setItem("kh:active", active); }, [active]);

  // テーマ・フォントをルートに反映
  useEffect(() => {
    document.documentElement.setAttribute("data-theme", t.theme || "tropical");
    document.body.style.setProperty("--font",
      t.font === "serif" ? "var(--font-serif)" : "var(--font-sans)"
    );
  }, [t.theme, t.font]);

  const tabs = useMemo(() => {
    const dayTabs = data.days.map((d, i) => ({
      key: `day${i+1}`, num: i+1, label: `${d.date} ${d.label}`
    }));
    return [
      { key: "hotel", label: "🏠 ホテル" },
      ...dayTabs,
      { key: "food", label: "🍜 食べたい" },
      { key: "souv", label: "🎁 お土産" },
    ];
  }, [data]);

  let body;
  if (active === "hotel") body = <HotelTab data={data} />;
  else if (active === "food") body = <ListTab title="食べたいもの" items={data.food} storageKey="kh:food" />;
  else if (active === "souv") body = <ListTab title="お土産リスト" items={data.souvenirs} storageKey="kh:souv" />;
  else {
    const idx = parseInt(active.replace("day",""), 10) - 1;
    body = <DayView day={data.days[idx]} dayNum={idx + 1} />;
  }

  return (
    <div className="app">
      <Cover data={data} />
      <Tabs tabs={tabs} active={active} onChange={setActive} />
      {body}
      <footer className="footer">
        <span className="heart">♥</span> ENJOY KAOHSIUNG · 高雄玩得開心 <span className="heart">♥</span>
      </footer>

      <TweaksPanel>
        <TweakSection label="カラーテーマ" />
        <TweakRadio
          label="パレット"
          value={t.theme}
          options={[
            { value: "tropical", label: "Tropical" },
            { value: "sunset",   label: "Sunset" },
            { value: "ocean",    label: "Ocean" },
            { value: "jungle",   label: "Jungle" },
          ]}
          onChange={(v) => setTweak("theme", v)}
        />
        <TweakSection label="フォント" />
        <TweakRadio
          label="書体"
          value={t.font}
          options={[
            { value: "sans",  label: "ゴシック" },
            { value: "serif", label: "明朝" },
          ]}
          onChange={(v) => setTweak("font", v)}
        />
      </TweaksPanel>
    </div>
  );
}

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