// app.jsx — main shell, router, language + tweaks state

// ─── Per-route SEO: [title, meta description] by language + page ───────
// Hash routing means Google indexes one URL, but updating these still gives
// each view a distinct, keyword-targeted title/description in the SERP,
// social shares, and browser tab as the guest navigates.
const SEO = {
  pl: {
    home: ["Long Street Aparthostel — pokoje w centrum Krakowa, ul. Długa",
      "Kameralny aparthostel przy ul. Długiej 43 w Krakowie. Pokoje Standard i Komfort z prywatną łazienką, wspólną kuchnią i samodzielnym zameldowaniem. Rezerwuj online."],
    rooms: ["Pokoje Standard i Komfort — Long Street Aparthostel Kraków",
      "Dwa pokoje Standard 15 m² i dwa Komfortowe 23 m², każdy z prywatną łazienką i dostępem do wspólnej kuchni. Kraków, Stare Miasto, ul. Długa."],
    "room-detail": ["Pokój — Long Street Aparthostel, Kraków",
      "Pokój z prywatną łazienką w centrum Krakowa, przy ul. Długiej. Wspólna kuchnia, samodzielne zameldowanie. Rezerwuj bezpośrednio online."],
    gallery: ["Galeria — Long Street Aparthostel, Kraków Stare Miasto",
      "Zdjęcia pokoi, wnętrz i okolicy Long Street Aparthostel przy ul. Długiej w Krakowie — kilka minut od Rynku Głównego i Wawelu."],
    reservation: ["Rezerwacja online — Long Street Aparthostel Kraków",
      "Zarezerwuj pokój bezpośrednio online z natychmiastowym potwierdzeniem. Płatność Przelewy24 lub przelew Revolut. Ul. Długa, Kraków."],
    contact: ["Kontakt — Long Street Aparthostel, ul. Długa 43, Kraków",
      "Kontakt: ul. Długa 43/6, 31-047 Kraków, tel. +48 602 321 838. Mapa dojazdu i formularz kontaktowy."],
  },
  en: {
    home: ["Long Street Aparthostel — rooms in central Kraków, ul. Długa",
      "A small aparthostel on Długa Street in Kraków's Old Town. Standard and Comfort rooms with private bathrooms, a shared kitchen and self check-in. Book online."],
    rooms: ["Standard & Comfort rooms — Long Street Aparthostel Kraków",
      "Two 15 m² Standard rooms and two 23 m² Comfort rooms, each with a private bathroom and shared kitchen access. Old Town, Długa Street, Kraków."],
    "room-detail": ["Room — Long Street Aparthostel, Kraków",
      "A private-bathroom room in central Kraków on Długa Street. Shared kitchen, self check-in. Book direct online with instant confirmation."],
    gallery: ["Gallery — Long Street Aparthostel, Kraków Old Town",
      "Photos of the rooms, interiors and neighbourhood of Long Street Aparthostel on Długa Street — minutes from the Main Square and Wawel."],
    reservation: ["Book online — Long Street Aparthostel Kraków",
      "Book a room directly online with instant confirmation. Pay via Przelewy24 or Revolut transfer. Długa Street, Kraków."],
    contact: ["Contact — Long Street Aparthostel, ul. Długa 43, Kraków",
      "Contact: ul. Długa 43/6, 31-047 Kraków, +48 602 321 838. Directions map and contact form."],
  },
};

function seoTag(kind, idAttr, idVal) {
  let el = document.head.querySelector(`${kind}[${idAttr}="${idVal}"]`);
  if (!el) {
    el = document.createElement(kind);
    el.setAttribute(idAttr, idVal);
    document.head.appendChild(el);
  }
  return el;
}
function applySeo(lang, page, params) {
  const table = SEO[lang] || SEO.pl;
  let [title, desc] = table[page] || table.home;

  // Per-room title/description so each /rooms/<slug> is its own indexable page.
  if (page === "room-detail") {
    const cards = (window.I18N[lang] || window.I18N.pl).rooms.cards;
    const card = cards[(params && params.roomIdx) || 0] || cards[0];
    title = `${card.name} — Long Street Aparthostel, Kraków`;
    desc = card.desc || desc;
  }

  const O = window.SITE_ORIGIN;
  const plUrl = O + window.routeToPath(page, params, "pl");
  const enUrl = O + window.routeToPath(page, params, "en");
  const selfUrl = lang === "en" ? enUrl : plUrl;

  document.documentElement.setAttribute("lang", lang);
  if (title) document.title = title;
  seoTag("meta", "name", "description").setAttribute("content", desc || "");
  seoTag("meta", "property", "og:title").setAttribute("content", title || "");
  seoTag("meta", "property", "og:description").setAttribute("content", desc || "");
  seoTag("meta", "property", "og:url").setAttribute("content", selfUrl);
  seoTag("meta", "property", "og:locale").setAttribute("content", lang === "en" ? "en_US" : "pl_PL");
  seoTag("meta", "property", "og:locale:alternate").setAttribute("content", lang === "en" ? "pl_PL" : "en_US");
  seoTag("link", "rel", "canonical").setAttribute("href", selfUrl);
  // hreflang alternates so Google serves the right language and avoids duplicate-content.
  const alt = (hl, href) => {
    const e = seoTag("link", "hreflang", hl);
    e.setAttribute("rel", "alternate");
    e.setAttribute("href", href);
  };
  alt("pl", plUrl);
  alt("en", enUrl);
  alt("x-default", plUrl);
}

function App() {
  // ─── Tweaks (persisted) ──────────────────────────────────────────────
  const TWEAK_DEFAULTS = /*EDITMODE-BEGIN*/{
    "hero": "editorial",
    "palette": "ivory",
    "type": "cormorant",
    "currency": "PLN",
    "sectionOrder": "default",
    "bgOverride": "",
    "inkOverride": "",
    "accentOverride": ""
  }/*EDITMODE-END*/;

  const [tweaks, setTweak] = useTweaks(TWEAK_DEFAULTS);

  // ─── Apply palette + type via data attrs on html ─────────────────────
  useEffect(() => {
    document.documentElement.setAttribute("data-palette", tweaks.palette || "warmth");
    document.documentElement.setAttribute("data-type", tweaks.type || "cormorant");
  }, [tweaks.palette, tweaks.type]);

  // ─── Reset color overrides when palette changes ──────────────────────
  const prevPaletteRef = useRef(tweaks.palette);
  useEffect(() => {
    if (prevPaletteRef.current !== tweaks.palette) {
      setTweak({ bgOverride: "", inkOverride: "", accentOverride: "" });
      prevPaletteRef.current = tweaks.palette;
    }
  }, [tweaks.palette]);

  // ─── Apply per-color overrides as inline custom properties ───────────
  useEffect(() => {
    const el = document.documentElement;
    if (tweaks.bgOverride) {
      el.style.setProperty("--bg", tweaks.bgOverride);
      el.style.setProperty("--bg-2", shadeHex(tweaks.bgOverride, -6));
      el.style.setProperty("--bg-3", shadeHex(tweaks.bgOverride, -14));
    } else {
      ["--bg", "--bg-2", "--bg-3"].forEach((p) => el.style.removeProperty(p));
    }
    if (tweaks.inkOverride) {
      el.style.setProperty("--ink", tweaks.inkOverride);
    } else {
      el.style.removeProperty("--ink");
    }
    if (tweaks.accentOverride) {
      el.style.setProperty("--accent", tweaks.accentOverride);
      el.style.setProperty("--accent-2", shadeHex(tweaks.accentOverride, -14));
      el.style.setProperty("--on-accent", isLightHex(tweaks.accentOverride) ? "#1A1B1E" : "#F8F8F7");
    } else {
      ["--accent", "--accent-2", "--on-accent"].forEach((p) => el.style.removeProperty(p));
    }
  }, [tweaks.bgOverride, tweaks.inkOverride, tweaks.accentOverride]);

  // ─── Router (real URL paths via the History API) ─────────────────────
  const [route, setRoute] = useState(() => window.pathToRoute(window.location.pathname));

  const navigate = (page, params = {}, lng) => {
    const lang = lng || route.lang;
    setRoute({ page, params, lang });
    window.history.pushState({}, "", window.routeToPath(page, params, lang));
    window.scrollTo({ top: 0, behavior: "smooth" });
  };

  useEffect(() => {
    const onPop = () => setRoute(window.pathToRoute(window.location.pathname));
    window.addEventListener("popstate", onPop);
    return () => window.removeEventListener("popstate", onPop);
  }, []);

  // ─── Language derives from the URL (/en/* = English) ─────────────────
  const lang = route.lang;
  const t = window.I18N[lang] || window.I18N.pl;
  const setLang = (nl) => {
    try { localStorage.setItem("dluga.lang", nl); } catch (e) {}
    navigate(route.page, route.params, nl);   // switch to the same page in the other language
  };

  useEffect(() => {
    track("page_view", { page_path: window.routeToPath(route.page, route.params), page_title: route.page });
  }, [route.page, route.params]);

  // Keep <title>, meta description, canonical and OG tags in sync per route/lang
  useEffect(() => {
    applySeo(lang, route.page, route.params);
  }, [route.page, route.params, lang]);

  // ─── Context value ───────────────────────────────────────────────────
  const ctx = {
    lang, setLang, t,
    tweaks, setTweak,
    currency: tweaks.currency || "PLN",
    page: route.page, route, navigate,
  };

  const heroFullBleed = tweaks.hero === "fullbleed" && route.page === "home";

  return (
    <AppCtx.Provider value={ctx}>
      <Header transparent={heroFullBleed} />
      <main>
        {route.page === "home" && <HomePage />}
        {route.page === "rooms" && <RoomsPage />}
        {route.page === "room-detail" && <RoomDetailPage />}
        {route.page === "gallery" && <GalleryPage />}
        {route.page === "contact" && <ContactPage />}
        {route.page === "reservation" && <ReservationPage />}
      </main>
      <Footer />
      <TweaksPanelWrapper t={t} tweaks={tweaks} setTweak={setTweak} lang={lang} />
    </AppCtx.Provider>
  );
}

// ─── Tweaks panel ─────────────────────────────────────────────────────
function TweaksPanelWrapper({ t, tweaks, setTweak, lang }) {
  return (
    <TweaksPanel>
      <TweakSection label={lang === "pl" ? "Hero" : "Hero"} />
      <TweakRadio
        label={lang === "pl" ? "Styl" : "Style"}
        value={tweaks.hero}
        options={[
          { value: "editorial", label: "Editorial" },
          { value: "fullbleed", label: lang === "pl" ? "Pełen" : "Bleed" },
          { value: "split", label: "Split" },
        ]}
        onChange={(v) => setTweak("hero", v)}
      />

      <TweakSection label={lang === "pl" ? "Wygląd" : "Appearance"} />
      <TweakRow label={lang === "pl" ? "Paleta" : "Palette"}>
        <PalettePicker
          value={tweaks.palette}
          options={[
            { value: "warmth", colors: ["#F8F8F7", "#1F1612", "#550B14"] },
            { value: "steel", colors: ["#FFFFFF", "#1A1B1E", "#BB7A3C"] },
            { value: "ivory", colors: ["#FAF7F2", "#1F2D24", "#B89368"] },
            { value: "sage", colors: ["#F5F2EA", "#1F2A22", "#6B8369"] },
            { value: "olive", colors: ["#F4F2EB", "#1E2118", "#6F7340"] },
            { value: "navy", colors: ["#F4F2EC", "#131A26", "#1F3A5E"] },
            { value: "cobalt", colors: ["#F6F7F9", "#0F1419", "#2D55A8"] },
            { value: "plum", colors: ["#F2EDE6", "#2E1A2A", "#8B5A6B"] },
            { value: "oxblood", colors: ["#F6F1EA", "#1B1318", "#7C2A33"] },
            { value: "slate", colors: ["#EEEDE8", "#1E2329", "#C6873A"] },
            { value: "charcoal", colors: ["#15120E", "#EFE6D9", "#C7A77A"] },
          ]}
          onChange={(v) => setTweak("palette", v)}
        />
      </TweakRow>
      <TweakRadio
        label={lang === "pl" ? "Typografia" : "Typography"}
        value={tweaks.type}
        options={[
          { value: "cormorant", label: "Cormorant" },
          { value: "fraunces", label: "Fraunces" },
          { value: "sans", label: "Sans" },
        ]}
        onChange={(v) => setTweak("type", v)}
      />

      <TweakSection label={lang === "pl" ? "Własne kolory" : "Custom colors"} />
      <ColorOverride
        label={lang === "pl" ? "Tło" : "Background"}
        varName="--bg"
        paletteKey={tweaks.palette}
        value={tweaks.bgOverride}
        onChange={(v) => setTweak("bgOverride", v || "")}
      />
      <ColorOverride
        label={lang === "pl" ? "Tekst" : "Text"}
        varName="--ink"
        paletteKey={tweaks.palette}
        value={tweaks.inkOverride}
        onChange={(v) => setTweak("inkOverride", v || "")}
      />
      <ColorOverride
        label={lang === "pl" ? "Akcent" : "Accent"}
        varName="--accent"
        paletteKey={tweaks.palette}
        value={tweaks.accentOverride}
        onChange={(v) => setTweak("accentOverride", v || "")}
      />

      <TweakSection label={lang === "pl" ? "Waluta" : "Currency"} />
      <TweakRadio
        label={lang === "pl" ? "Waluta" : "Currency"}
        value={tweaks.currency}
        options={["PLN", "EUR", "USD"]}
        onChange={(v) => setTweak("currency", v)}
      />
    </TweaksPanel>
  );
}

// ─── Color helpers ───────────────────────────────────────────────────
function shadeHex(hex, percent) {
  // percent: -100..+100 (negative = darker)
  const h = hex.replace("#", "");
  const num = parseInt(h.length === 3 ? h.split("").map((c) => c + c).join("") : h, 16);
  let r = (num >> 16) + Math.round(percent * 2.55);
  let g = ((num >> 8) & 0xff) + Math.round(percent * 2.55);
  let b = (num & 0xff) + Math.round(percent * 2.55);
  r = Math.max(0, Math.min(255, r));
  g = Math.max(0, Math.min(255, g));
  b = Math.max(0, Math.min(255, b));
  return "#" + ((1 << 24) + (r << 16) + (g << 8) + b).toString(16).slice(1);
}
function isLightHex(hex) {
  const h = hex.replace("#", "");
  const num = parseInt(h.length === 3 ? h.split("").map((c) => c + c).join("") : h, 16);
  const r = num >> 16, g = (num >> 8) & 0xff, b = num & 0xff;
  return (0.299 * r + 0.587 * g + 0.114 * b) > 150;
}
function rgbStringToHex(rgb) {
  if (!rgb) return "#000000";
  rgb = rgb.trim();
  if (rgb.startsWith("#")) {
    return rgb.length === 4
      ? "#" + rgb.slice(1).split("").map((c) => c + c).join("")
      : rgb;
  }
  const m = rgb.match(/rgba?\((\d+)[ ,]+(\d+)[ ,]+(\d+)/);
  if (!m) return "#000000";
  return "#" + [m[1], m[2], m[3]].map((n) => parseInt(n).toString(16).padStart(2, "0")).join("");
}

// ─── ColorOverride control ────────────────────────────────────────────
function ColorOverride({ label, varName, paletteKey, value, onChange }) {
  // When no override, resolve effective value from the live CSS var
  const [effective, setEffective] = useState(value || "#000000");
  useEffect(() => {
    if (value) {
      setEffective(value);
    } else {
      // Read the palette value off documentElement
      // Need to temporarily clear inline override (if any) — but the parent already does that
      const v = getComputedStyle(document.documentElement).getPropertyValue(varName).trim();
      setEffective(rgbStringToHex(v));
    }
  }, [value, varName, paletteKey]);

  return (
    <div className="twk-row twk-row-h">
      <div className="twk-lbl"><span>{label}</span></div>
      <div style={{ display: "flex", gap: 6, alignItems: "center" }}>
        <input
          type="color"
          value={effective}
          onChange={(e) => onChange(e.target.value)}
          style={{
            width: 32, height: 22, padding: 0, border: "1px solid rgba(0,0,0,.15)",
            borderRadius: 4, cursor: "pointer", background: "none",
          }}
        />
        <span style={{ fontSize: 9.5, color: "rgba(0,0,0,.5)", fontFamily: "ui-monospace, monospace", minWidth: 56 }}>
          {effective.toUpperCase()}
        </span>
        {value && (
          <button
            type="button"
            onClick={() => onChange("")}
            title="Reset to palette"
            style={{
              border: 0, background: "rgba(0,0,0,.06)", borderRadius: 4,
              width: 18, height: 18, fontSize: 10, color: "rgba(0,0,0,.55)",
              cursor: "pointer", padding: 0, display: "grid", placeItems: "center",
            }}
          >
            ↻
          </button>
        )}
      </div>
    </div>
  );
}

// Custom palette picker — like TweakColor but with named values
function PalettePicker({ value, options, onChange }) {
  return (
    <div style={{ display: "grid", gridTemplateColumns: "repeat(5, 1fr)", gap: 6 }}>
      {options.map((opt) => {
        const active = opt.value === value;
        const [bg, ink, accent] = opt.colors;
        return (
          <button
            key={opt.value}
            type="button"
            onClick={() => onChange(opt.value)}
            title={opt.value}
            style={{
              aspectRatio: "1",
              border: active ? "2px solid rgba(0,0,0,.6)" : "1px solid rgba(0,0,0,.12)",
              borderRadius: 6,
              background: bg,
              padding: 0,
              position: "relative",
              overflow: "hidden",
              cursor: "pointer",
            }}
          >
            <span style={{ position: "absolute", inset: "40% 8% 8% 40%", background: ink, borderRadius: 3 }} />
            <span style={{ position: "absolute", inset: "60% 50% 8% 8%", background: accent, borderRadius: 3 }} />
          </button>
        );
      })}
    </div>
  );
}

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