/* global React, L, BrandStrip, SectionHead, PageHero, WaveDivider,
   IconArrow, IconClose, IconMapPin, GALLERY_ITEMS, NEIGHBORHOOD, CATEGORIES */

const { useState: useStateGal, useEffect: useEffectGal, useRef: useRefGal, useMemo: useMemoGal } = React;

const MAP_CENTER = [39.3573487, -74.4281568];

function escapeMapText(value) {
  return String(value).replace(/[&<>"']/g, (char) => ({
    "&": "&amp;",
    "<": "&lt;",
    ">": "&gt;",
    '"': "&quot;",
    "'": "&#39;",
  }[char]));
}

function NeighborhoodMap({ visiblePins, activePin, setActivePin }) {
  const mapEl = useRefGal(null);
  const mapRef = useRefGal(null);
  const markerLayerRef = useRefGal(null);
  const markerRefs = useRefGal({});

  useEffectGal(() => {
    if (!mapEl.current || mapRef.current || !window.L) return;

    const map = L.map(mapEl.current, {
      center: MAP_CENTER,
      zoom: 15,
      minZoom: 13,
      maxZoom: 18,
      scrollWheelZoom: true,
      dragging: true,
      tap: true,
    });

    L.tileLayer("https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png", {
      maxZoom: 19,
      attribution: "&copy; OpenStreetMap contributors",
    }).addTo(map);

    markerLayerRef.current = L.layerGroup().addTo(map);
    mapRef.current = map;
    setTimeout(() => map.invalidateSize(), 0);

    return () => {
      map.remove();
      mapRef.current = null;
      markerLayerRef.current = null;
      markerRefs.current = {};
    };
  }, []);

  useEffectGal(() => {
    const map = mapRef.current;
    const layer = markerLayerRef.current;
    if (!map || !layer) return;

    layer.clearLayers();
    markerRefs.current = {};

    visiblePins.forEach((pin) => {
      const categoryColor = CATEGORIES.find((category) => category.name === pin.category)?.color || "#8B6F4D";
      const marker = L.marker([pin.lat, pin.lng], {
        icon: L.divIcon({
          className: "map-marker-icon",
          html: `<span class="map-marker${pin.isHouse ? " house" : ""}" style="background:${categoryColor}" aria-hidden="true"></span>`,
          iconSize: pin.isHouse ? [26, 26] : [20, 20],
          iconAnchor: pin.isHouse ? [13, 13] : [10, 10],
        }),
        title: pin.name,
      });

      marker.bindPopup(
        `<strong>${escapeMapText(pin.name)}</strong><span>${escapeMapText(pin.meta)}</span>`
      );
      marker.on("click", () => setActivePin(pin.id));
      marker.addTo(layer);
      markerRefs.current[pin.id] = marker;
    });

    const bounds = L.latLngBounds(visiblePins.map((pin) => [pin.lat, pin.lng]));
    map.fitBounds(bounds.pad(0.18), { animate: true, maxZoom: 16 });
  }, [visiblePins, setActivePin]);

  useEffectGal(() => {
    const marker = markerRefs.current[activePin];
    const map = mapRef.current;
    if (!marker || !map) return;

    marker.openPopup();
    map.panTo(marker.getLatLng(), { animate: true });
  }, [activePin]);

  return (
    <div className="map-wrap">
      <div ref={mapEl} className="map-leaflet" role="img" aria-label="Interactive map centered on Boardwalk House at 190 South Kentucky Avenue" />
      <button type="button" className="map-reset" onClick={() => {
        setActivePin("house");
        mapRef.current?.setView(MAP_CENTER, 16, { animate: true });
      }}>
        Boardwalk House
      </button>
    </div>
  );
}

// =====================================================
// GALLERY PAGE (with lightbox)
// =====================================================
function GalleryPage() {
  const [filter, setFilter] = useStateGal("all");
  const [displayFilter, setDisplayFilter] = useStateGal("all");
  const [gridPhase, setGridPhase] = useStateGal("");
  const [lightboxIdx, setLightboxIdx] = useStateGal(null);
  const [displayedLightboxIdx, setDisplayedLightboxIdx] = useStateGal(null);
  const filterTimerRef = useRefGal(null);
  const lightboxTimerRef = useRefGal(null);

  const filtered = displayFilter === "all" ? GALLERY_ITEMS : GALLERY_ITEMS.filter((i) => i.kind === displayFilter);

  const closeLightbox = () => {
    setLightboxIdx(null);
    window.clearTimeout(lightboxTimerRef.current);
    lightboxTimerRef.current = window.setTimeout(() => setDisplayedLightboxIdx(null), 240);
  };

  const openLightbox = (index) => {
    window.clearTimeout(lightboxTimerRef.current);
    setDisplayedLightboxIdx(index);
    setLightboxIdx(index);
  };

  const changeFilter = (nextFilter) => {
    if (nextFilter === filter) return;
    setFilter(nextFilter);
    closeLightbox();
    window.clearTimeout(filterTimerRef.current);
    setGridPhase("is-leaving");
    const reduceMotion = window.matchMedia("(prefers-reduced-motion: reduce)").matches;
    filterTimerRef.current = window.setTimeout(() => {
      setDisplayFilter(nextFilter);
      setGridPhase("is-entering");
      window.requestAnimationFrame(() => window.requestAnimationFrame(() => setGridPhase("")));
    }, reduceMotion ? 0 : 180);
  };

  useEffectGal(() => {
    if (lightboxIdx === null) return;
    const previousOverflow = document.body.style.overflow;
    const onKey = (e) => {
      if (e.key === "Escape") closeLightbox();
      if (e.key === "ArrowRight") {
        setLightboxIdx((i) => {
          const next = (i + 1) % filtered.length;
          setDisplayedLightboxIdx(next);
          return next;
        });
      }
      if (e.key === "ArrowLeft") {
        setLightboxIdx((i) => {
          const next = (i - 1 + filtered.length) % filtered.length;
          setDisplayedLightboxIdx(next);
          return next;
        });
      }
    };
    document.body.style.overflow = "hidden";
    document.addEventListener("keydown", onKey);
    return () => {
      document.body.style.overflow = previousOverflow;
      document.removeEventListener("keydown", onKey);
    };
  }, [lightboxIdx, filtered.length]);

  useEffectGal(() => () => {
    window.clearTimeout(filterTimerRef.current);
    window.clearTimeout(lightboxTimerRef.current);
  }, []);

  const filters = [
    { id: "all", lbl: "All" },
    { id: "exterior", lbl: "Exterior" },
    { id: "interior", lbl: "Interiors" },
    { id: "amenity", lbl: "Amenities" },
    { id: "lounge", lbl: "Lounge" },
    { id: "neighborhood", lbl: "Neighborhood" },
  ];

  return (
    <div>
      <PageHero
        eyebrow="Gallery"
        title="Look around."
        lede="A view through the lens of Boardwalk House — exterior, residences, amenities, and the neighborhood that surrounds us."
        photoUrl="images/aerial-2.jpeg"
      />

      <section className="section bg-cream">
        <div className="shell">
          <div style={{ display: "flex", gap: 8, justifyContent: "center", flexWrap: "wrap", marginBottom: "var(--space-7)" }}>
            {filters.map((f) => (
              <button key={f.id}
                      className={"btn btn-sm " + (filter === f.id ? "btn-navy" : "btn-outline")}
                      onClick={() => changeFilter(f.id)}>
                {f.lbl}
              </button>
            ))}
          </div>

          <div className={`gallery-grid state-panel ${gridPhase}`}>
            {filtered.map((it, idx) => (
              <div
                key={it.id}
                className={"gallery-item " + (it.size || "")}
                style={{ "--item-index": idx % 8 }}
                onClick={() => openLightbox(idx)}>
                {it.img ? (
                  <img src={it.img} alt={it.caption} />
                ) : (
                  <div className="placeholder">
                    <div className="ph-tag">{it.placeholder.toUpperCase()}</div>
                  </div>
                )}
                <div className="overlay">
                  <span className="cap">{it.caption}</span>
                </div>
              </div>
            ))}
          </div>
        </div>
      </section>

      {/* Lightbox */}
      <div
        className={"lightbox" + (lightboxIdx !== null ? " open" : "")}
        role="dialog"
        aria-modal="true"
        aria-label="Photo gallery viewer"
        aria-hidden={lightboxIdx === null}
        onClick={closeLightbox}>
        {displayedLightboxIdx !== null && filtered[displayedLightboxIdx] && (
          <div className="lightbox-content" onClick={(e) => e.stopPropagation()}>
            <button className="nav-btn close" onClick={closeLightbox} aria-label="Close gallery"><IconClose size={20} /></button>
            <button className="nav-btn prev" aria-label="Previous image" onClick={() => openLightbox((displayedLightboxIdx - 1 + filtered.length) % filtered.length)}>‹</button>
            <button className="nav-btn next" aria-label="Next image" onClick={() => openLightbox((displayedLightboxIdx + 1) % filtered.length)}>›</button>
            {filtered[displayedLightboxIdx].img ? (
              <img key={filtered[displayedLightboxIdx].img} className="media-swap" src={filtered[displayedLightboxIdx].img} alt={filtered[displayedLightboxIdx].caption} />
            ) : (
              <div className="placeholder dark" style={{ width: "min(90vw, 900px)", aspectRatio: "16/10" }}>
                <div className="ph-tag">{filtered[displayedLightboxIdx].placeholder.toUpperCase()}</div>
              </div>
            )}
            <div className="cap">
              {filtered[displayedLightboxIdx].caption} · {displayedLightboxIdx + 1} of {filtered.length}
            </div>
          </div>
        )}
      </div>

      <BrandStrip />
    </div>
  );
}

// =====================================================
// LOCATION PAGE (interactive map with pins)
// =====================================================
function LocationPage({ navTo, openTour }) {
  const [activeCat, setActiveCat] = useStateGal(null);
  const [activePin, setActivePin] = useStateGal(null);

  const visiblePins = useMemoGal(() => (
    activeCat
      ? NEIGHBORHOOD.filter((p) => p.category === activeCat || p.isHouse)
      : NEIGHBORHOOD
  ), [activeCat]);

  return (
    <div>
      <PageHero
        eyebrow="The Location"
        title="On the boardwalk.\nIn the middle of everything."
        lede="190 S Kentucky Avenue. Directly on the Atlantic City Boardwalk. Steps to the beach, minutes to dining, casinos, and entertainment."
        photoUrl="images/aerial-2.jpeg"
      />

      <section className="section bg-cream">
        <div className="shell">
          <div style={{ display: "grid", gridTemplateColumns: "1.4fr 1fr", gap: "var(--space-7)" }} className="map-grid">
            {/* Map */}
            <div>
              <NeighborhoodMap
                visiblePins={visiblePins}
                activePin={activePin}
                setActivePin={setActivePin}
              />
              <p style={{ fontSize: 11, color: "var(--muted)", marginTop: 12, letterSpacing: "0.06em" }}>
                Map data © OpenStreetMap contributors. Click a category to focus nearby destinations.
              </p>
            </div>

            {/* Legend / categories */}
            <div>
              <span className="eyebrow" style={{ display: "block" }}>Neighborhood Highlights</span>
              <h3 style={{ fontSize: 28, marginTop: 6 }}>Live close to everything.</h3>
              <p style={{ fontSize: 14, color: "var(--muted)", marginTop: 10, marginBottom: 24 }}>
                {NEIGHBORHOOD.length - 1} destinations within a short walk. Filter by category to explore.
              </p>
              <div style={{ display: "grid", gap: 4 }}>
                <button onClick={() => setActiveCat(null)}
                        style={{
                          background: !activeCat ? "rgba(13,27,42,0.06)" : "transparent",
                          border: "1px solid rgba(13,27,42,0.1)",
                          padding: "10px 14px",
                          fontSize: 11, letterSpacing: "0.18em", textTransform: "uppercase",
                          fontFamily: "var(--sans)", fontWeight: 600,
                          textAlign: "left", color: "var(--navy)"
                        }}>
                  Show All Categories
                </button>
                {CATEGORIES.filter((c) => !c.isHouse).map((c) => (
                  <button key={c.name}
                          className={"map-legend"}
                          onClick={() => setActiveCat(c.name === activeCat ? null : c.name)}
                          style={{
                            display: "flex", alignItems: "center", gap: 12,
                            background: activeCat === c.name ? "rgba(139,111,77,0.1)" : "transparent",
                            border: "1px solid rgba(13,27,42,0.08)",
                            padding: "12px 14px",
                            fontSize: 13, fontFamily: "var(--sans)",
                            color: "var(--navy)", textAlign: "left",
                            cursor: "pointer"
                          }}>
                    <span style={{ width: 10, height: 10, background: c.color, borderRadius: "50%" }} />
                    <span style={{ fontWeight: 600 }}>{c.name}</span>
                    <span style={{ marginLeft: "auto", color: "var(--muted)", fontSize: 11 }}>{c.count}</span>
                  </button>
                ))}
              </div>

              <div style={{ marginTop: 32, padding: 20, background: "var(--navy)", color: "var(--linen-2)" }}>
                <div className="eyebrow on-dark">Address</div>
                <div className="serif" style={{ fontSize: 22, marginTop: 8 }}>190 S Kentucky Avenue</div>
                <div style={{ fontSize: 13, color: "rgba(245,242,237,0.7)", marginTop: 4 }}>Atlantic City, NJ 08401</div>
                <button className="btn btn-ghost btn-sm" style={{ marginTop: 18 }} onClick={openTour}>
                  Join Waitlist <IconArrow size={14} />
                </button>
              </div>
            </div>
          </div>

          {/* Distance grid */}
          <div style={{ marginTop: "var(--space-9)" }}>
            <SectionHead
              eyebrow="By the Numbers"
              title="A short walk to everything."
            />
            <div className="card-grid cols-4">
              {[
                { num: "0", lbl: "Steps to the Boardwalk" },
                { num: "30s", lbl: "Walk to the Beach" },
                { num: "5min", lbl: "To Major Casinos" },
                { num: "10min", lbl: "To AC Expressway" },
              ].map((s) => (
                <div key={s.lbl} style={{
                  padding: "32px 24px",
                  background: "#fff",
                  border: "1px solid rgba(13,27,42,0.08)",
                  textAlign: "center"
                }}>
                  <div style={{ fontFamily: "var(--serif)", fontSize: 56, lineHeight: 1, color: "var(--bronze)", fontWeight: 500 }}>
                    {s.num}
                  </div>
                  <div style={{ fontSize: 11, letterSpacing: "0.22em", textTransform: "uppercase", fontWeight: 600, color: "var(--navy)", marginTop: 14 }}>
                    {s.lbl}
                  </div>
                </div>
              ))}
            </div>
          </div>
        </div>
      </section>

      <BrandStrip />
    </div>
  );
}

Object.assign(window, { GalleryPage, LocationPage });
