// Clan Of VTC — Homepage. Fullscreen MapLibre map + centered search + layer toggles.

const MAP_STYLE = 'https://tiles.openfreemap.org/styles/liberty';
const GCC_VIEW  = { center: [50, 25], zoom: 4.4 };
const POINTS_URL = 'data/points.geojson';

const KIND_COLOR = {
  event:    '#bd24df',
  spot:     '#2d6ade',
  product:  '#d6c441',
  part:     '#34d399',
  workshop: '#f87171',
  city:     '#aabbd9',
};

const KIND_LABEL = {
  event:    'Events',
  spot:     'Spots',
  product:  'Listings',
  part:     'Parts',
  workshop: 'Workshops',
  city:     'Cities',
};

const KIND_ORDER = ['event', 'spot', 'product', 'part', 'workshop', 'city'];

// Rough GCC bounding box — center on user only if they're inside.
const GCC_BBOX = { minLng: 34, maxLng: 60, minLat: 16, maxLat: 32 };
const inGCC = (lng, lat) =>
  lng >= GCC_BBOX.minLng && lng <= GCC_BBOX.maxLng &&
  lat >= GCC_BBOX.minLat && lat <= GCC_BBOX.maxLat;

const HomePage = () => {
  const mapRef = React.useRef(null);
  const containerRef = React.useRef(null);
  const dataRef = React.useRef(null);
  const sourceLoaded = React.useRef(false);

  const [ready, setReady] = React.useState(false);
  const [query, setQuery] = React.useState('');
  const [searchOpen, setSearchOpen] = React.useState(false);
  const [searchCompact, setSearchCompact] = React.useState(false);
  const [enabledKinds, setEnabledKinds] = React.useState(() => new Set(KIND_ORDER));
  const [kindCounts, setKindCounts] = React.useState({});
  const [locating, setLocating] = React.useState(false);

  // ─── Init map once ────────────────────────────────────────────
  React.useEffect(() => {
    if (!containerRef.current || mapRef.current) return;

    const map = new maplibregl.Map({
      container: containerRef.current,
      style: MAP_STYLE,
      center: GCC_VIEW.center,
      zoom: GCC_VIEW.zoom,
      attributionControl: { compact: true },
    });
    mapRef.current = map;

    map.addControl(new maplibregl.NavigationControl({ visualizePitch: false }), 'bottom-right');

    const geolocate = new maplibregl.GeolocateControl({
      positionOptions: { enableHighAccuracy: true, timeout: 8000 },
      trackUserLocation: false,
      showUserLocation: true,
      showAccuracyCircle: true,
      fitBoundsOptions: { maxZoom: 11 },
    });
    map.addControl(geolocate, 'bottom-right');

    map.on('load', async () => {
      // Load sample data
      let geojson;
      try {
        const res = await fetch(POINTS_URL);
        geojson = await res.json();
      } catch (e) {
        console.error('Failed to load points.geojson', e);
        geojson = { type: 'FeatureCollection', features: [] };
      }
      dataRef.current = geojson;

      // Pre-compute kind counts for the toggle chips
      const counts = {};
      geojson.features.forEach((f) => {
        const k = f.properties && f.properties.kind;
        counts[k] = (counts[k] || 0) + 1;
      });
      setKindCounts(counts);

      map.addSource('vtc', {
        type: 'geojson',
        data: geojson,
        cluster: true,
        clusterMaxZoom: 11,
        clusterRadius: 50,
      });
      sourceLoaded.current = true;

      addClusterLayers(map);
      addPointLayer(map);
      wireMapInteractions(map);

      setReady(true);

      // ─── Geolocation-aware default view ────────────────────────
      // If permission is already granted, fly to the user automatically.
      // Otherwise leave them on the GCC overview; they can hit the locate button.
      tryAutoLocate(geolocate);
    });

    // ─── Compact-search triggers ──────────────────────────────────
    // Any user-driven zoom/pan/wheel/touch should snap the search to the top.
    const userGesture = () => setSearchCompact(true);
    map.on('wheel',       userGesture);
    map.on('dragstart',   userGesture);
    map.on('touchstart',  userGesture);
    map.on('dblclick',    userGesture);
    map.on('zoomstart',   (e) => { if (e.originalEvent) setSearchCompact(true); });

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

  // ─── Re-filter the source when enabled kinds change ──────────
  React.useEffect(() => {
    const map = mapRef.current;
    if (!map || !sourceLoaded.current || !dataRef.current) return;
    const filtered = {
      type: 'FeatureCollection',
      features: dataRef.current.features.filter((f) => enabledKinds.has(f.properties.kind)),
    };
    const src = map.getSource('vtc');
    if (src) src.setData(filtered);
  }, [enabledKinds, ready]);

  // ─── Search filtering ─────────────────────────────────────────
  const results = React.useMemo(() => {
    if (!query.trim() || !dataRef.current) return [];
    const q = query.trim().toLowerCase();
    return dataRef.current.features
      .filter((f) => {
        const p = f.properties || {};
        if (!enabledKinds.has(p.kind)) return false;
        return (p.name || '').toLowerCase().includes(q)
          || (p.region || '').toLowerCase().includes(q)
          || (p.country || '').toLowerCase().includes(q)
          || (p.kind || '').toLowerCase().includes(q)
          || (p.description || '').toLowerCase().includes(q);
      })
      .slice(0, 8);
  }, [query, ready, enabledKinds]);

  const flyTo = (feature) => {
    const map = mapRef.current;
    if (!map) return;
    map.easeTo({ center: feature.geometry.coordinates, zoom: 12, duration: 1200 });
    setSearchOpen(false);
    setQuery('');
    setSearchCompact(true);
    setTimeout(() => {
      new maplibregl.Popup({ closeButton: true, maxWidth: '280px' })
        .setLngLat(feature.geometry.coordinates)
        .setHTML(renderPopup(feature.properties || {}))
        .addTo(map);
    }, 600);
  };

  const toggleKind = (k) => {
    setEnabledKinds((prev) => {
      const next = new Set(prev);
      if (next.has(k)) next.delete(k); else next.add(k);
      return next;
    });
  };

  const tryAutoLocate = async (geolocate) => {
    if (!navigator.geolocation) return;
    try {
      // Check permission state without prompting.
      const perm = navigator.permissions && navigator.permissions.query
        ? await navigator.permissions.query({ name: 'geolocation' })
        : { state: 'prompt' };
      if (perm.state !== 'granted') return;
      setLocating(true);
      navigator.geolocation.getCurrentPosition(
        (pos) => {
          setLocating(false);
          const { longitude, latitude } = pos.coords;
          const map = mapRef.current;
          if (!map) return;
          if (inGCC(longitude, latitude)) {
            map.easeTo({ center: [longitude, latitude], zoom: 10, duration: 1400 });
            setSearchCompact(true);
            // Trigger the control so the user dot shows
            try { geolocate.trigger(); } catch (_) {}
          }
        },
        () => setLocating(false),
        { enableHighAccuracy: true, timeout: 7000, maximumAge: 60000 }
      );
    } catch (_) {
      setLocating(false);
    }
  };

  return (
    <div className="home">
      <div ref={containerRef} className="home__map" aria-label="GCC enthusiast map" />

      <header className="home__header">
        <div className="home__brand">
          <img src="assets/logo.svg" alt="" className="home__logo" />
          <span>{(window.DATA && window.DATA.brand && window.DATA.brand.name) || 'Clan Of VTC'}</span>
        </div>

        <LayerToggles
          kinds={KIND_ORDER}
          enabled={enabledKinds}
          counts={kindCounts}
          onToggle={toggleKind}
        />
      </header>

      <div className={`home__search${searchCompact ? ' home__search--compact' : ''}`}>
        <div className="home__search-wrap">
          <SearchIcon />
          <input
            className="home__search-input"
            type="search"
            placeholder="Search events, spots, products, parts…"
            value={query}
            onChange={(e) => { setQuery(e.target.value); setSearchOpen(true); }}
            onFocus={() => { setSearchOpen(true); setSearchCompact(true); }}
            aria-label="Search the map"
          />
          {query && (
            <button className="home__search-clear"
                    onClick={() => { setQuery(''); setSearchOpen(false); }}
                    aria-label="Clear">×</button>
          )}
        </div>

        {searchOpen && query && (
          <div className="home__results">
            {results.length === 0 && (
              <div className="home__result home__result--empty">No matches for "{query}"</div>
            )}
            {results.map((f) => {
              const p = f.properties || {};
              return (
                <div key={p.id || p.name} className="home__result" onClick={() => flyTo(f)}>
                  <span className="home__result-dot" style={{ background: KIND_COLOR[p.kind] || '#74849f' }} />
                  <div className="home__result-body">
                    <div className="home__result-name">{p.name}</div>
                    <div className="home__result-meta">
                      <span className="home__result-kind">{KIND_LABEL[p.kind] || p.kind}</span>
                      {p.region && <span> · {p.region}</span>}
                      {p.country && <span> · {p.country}</span>}
                    </div>
                  </div>
                </div>
              );
            })}
          </div>
        )}

        {!searchCompact && <Legend />}
      </div>

      {locating && <div className="home__locating">Locating you…</div>}

      <Footer />
    </div>
  );
};

// ─── Map layer helpers ──────────────────────────────────────────

function addClusterLayers(map) {
  map.addLayer({
    id: 'clusters',
    type: 'circle',
    source: 'vtc',
    filter: ['has', 'point_count'],
    paint: {
      'circle-color': [
        'step', ['get', 'point_count'],
        '#2d6ade', 5,
        '#bd24df', 15,
        '#d97706',
      ],
      'circle-radius': [
        'step', ['get', 'point_count'],
        18, 5,
        24, 15,
        32,
      ],
      'circle-stroke-width': 2,
      'circle-stroke-color': 'rgba(255,255,255,0.85)',
      'circle-opacity': 0.9,
    },
  });

  map.addLayer({
    id: 'cluster-count',
    type: 'symbol',
    source: 'vtc',
    filter: ['has', 'point_count'],
    layout: {
      'text-field': '{point_count_abbreviated}',
      'text-font': ['Noto Sans Regular'],
      'text-size': 13,
    },
    paint: { 'text-color': '#ffffff' },
  });
}

function addPointLayer(map) {
  const colorMatch = ['match', ['get', 'kind']];
  Object.entries(KIND_COLOR).forEach(([k, c]) => { colorMatch.push(k, c); });
  colorMatch.push('#74849f');

  map.addLayer({
    id: 'point',
    type: 'circle',
    source: 'vtc',
    filter: ['!', ['has', 'point_count']],
    paint: {
      'circle-color': colorMatch,
      'circle-radius': [
        'interpolate', ['linear'], ['zoom'],
        4, 4,
        8, 6,
        12, 9,
      ],
      'circle-stroke-width': 2,
      'circle-stroke-color': 'rgba(255,255,255,0.9)',
    },
  });

  // Larger halo layer for events (extra emphasis)
  map.addLayer({
    id: 'point-halo',
    type: 'circle',
    source: 'vtc',
    filter: ['all', ['!', ['has', 'point_count']], ['==', ['get', 'kind'], 'event']],
    paint: {
      'circle-color': KIND_COLOR.event,
      'circle-radius': [
        'interpolate', ['linear'], ['zoom'],
        4, 10,
        12, 22,
      ],
      'circle-opacity': 0.18,
      'circle-blur': 0.4,
    },
  }, 'point');
}

function wireMapInteractions(map) {
  ['clusters', 'point'].forEach((id) => {
    map.on('mouseenter', id, () => { map.getCanvas().style.cursor = 'pointer'; });
    map.on('mouseleave', id, () => { map.getCanvas().style.cursor = ''; });
  });

  map.on('click', 'clusters', (e) => {
    const f = map.queryRenderedFeatures(e.point, { layers: ['clusters'] })[0];
    if (!f) return;
    const clusterId = f.properties.cluster_id;
    map.getSource('vtc').getClusterExpansionZoom(clusterId).then((zoom) => {
      map.easeTo({ center: f.geometry.coordinates, zoom });
    });
  });

  map.on('click', 'point', (e) => {
    const f = e.features[0];
    new maplibregl.Popup({ closeButton: true, maxWidth: '280px' })
      .setLngLat(f.geometry.coordinates.slice())
      .setHTML(renderPopup(f.properties || {}))
      .addTo(map);
  });
}

// ─── Subcomponents ──────────────────────────────────────────────

const LayerToggles = ({ kinds, enabled, counts, onToggle }) => (
  <div className="home__layers" role="group" aria-label="Map layers">
    {kinds.map((k) => {
      const on = enabled.has(k);
      const count = counts[k] || 0;
      return (
        <button
          key={k}
          className={`home__layer${on ? '' : ' home__layer--off'}`}
          onClick={() => onToggle(k)}
          aria-pressed={on}
          title={`${KIND_LABEL[k]} (${count})`}
        >
          <span className="home__layer-dot" style={{ background: KIND_COLOR[k] }} />
          <span className="home__layer-label">{KIND_LABEL[k]}</span>
          <span className="home__layer-count">{count}</span>
        </button>
      );
    })}
  </div>
);

const SearchIcon = () => (
  <svg className="home__search-icon" viewBox="0 0 24 24" width="20" height="20" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round" aria-hidden="true">
    <circle cx="11" cy="11" r="7" />
    <line x1="21" y1="21" x2="16.65" y2="16.65" />
  </svg>
);

const Legend = () => (
  <div className="home__legend">
    {KIND_ORDER.filter((k) => k !== 'city').map((k) => (
      <span key={k} className="home__legend-item">
        <span className="home__legend-dot" style={{ background: KIND_COLOR[k] }} />
        {KIND_LABEL[k]}
      </span>
    ))}
  </div>
);

const Footer = () => {
  const brand = (window.DATA && window.DATA.brand) || { tagline: 'Built On Sand. Sworn To The 4800.' };
  const connect = (window.DATA && window.DATA.connect) || [];
  return (
    <footer className="home__footer">
      <div className="home__footer-left">
        <div className="home__tagline">{brand.tagline}</div>
        <div className="home__copy">© {new Date().getFullYear()} Clan Of VTC · vtcclan.com</div>
      </div>
      <div className="home__connect">
        {connect.map((c) => (
          <a key={c.ttl} className="home__connect-item" href={connectHref(c)}
             target={c.ico === 'whatsapp' || c.ico === 'insta' || c.ico === 'pin' ? '_blank' : undefined}
             rel="noopener noreferrer">
            <ConnectIcon name={c.ico} />
            <span className="home__connect-text">
              <span className="home__connect-label">{c.ttl}</span>
              <span className="home__connect-value">{c.v}</span>
            </span>
          </a>
        ))}
      </div>
    </footer>
  );
};

const connectHref = (c) => {
  if (c.ico === 'whatsapp') return `https://wa.me/${c.v.replace(/[^0-9]/g, '')}`;
  if (c.ico === 'insta')    return `https://instagram.com/${c.v.replace(/^@/, '')}`;
  if (c.ico === 'mail')     return `mailto:${c.v}`;
  if (c.ico === 'pin')      return `https://www.google.com/maps/search/${encodeURIComponent(c.v)}`;
  return '#';
};

const ConnectIcon = ({ name }) => {
  const common = { width: 18, height: 18, viewBox: '0 0 24 24', fill: 'none', stroke: 'currentColor', strokeWidth: 2, strokeLinecap: 'round', strokeLinejoin: 'round' };
  if (name === 'whatsapp') return <svg {...common}><path d="M21 11.5a8.38 8.38 0 0 1-.9 3.8 8.5 8.5 0 0 1-7.6 4.7 8.38 8.38 0 0 1-3.8-.9L3 21l1.9-5.7a8.38 8.38 0 0 1-.9-3.8 8.5 8.5 0 0 1 4.7-7.6 8.38 8.38 0 0 1 3.8-.9h.5a8.48 8.48 0 0 1 8 8v.5z"/></svg>;
  if (name === 'insta')    return <svg {...common}><rect x="2" y="2" width="20" height="20" rx="5" ry="5"/><path d="M16 11.37A4 4 0 1 1 12.63 8 4 4 0 0 1 16 11.37z"/><line x1="17.5" y1="6.5" x2="17.51" y2="6.5"/></svg>;
  if (name === 'mail')     return <svg {...common}><path d="M4 4h16c1.1 0 2 .9 2 2v12c0 1.1-.9 2-2 2H4c-1.1 0-2-.9-2-2V6c0-1.1.9-2 2-2z"/><polyline points="22,6 12,13 2,6"/></svg>;
  if (name === 'pin')      return <svg {...common}><path d="M21 10c0 7-9 13-9 13s-9-6-9-13a9 9 0 0 1 18 0z"/><circle cx="12" cy="10" r="3"/></svg>;
  return null;
};

function renderPopup(p) {
  const kind = (KIND_LABEL[p.kind] || p.kind || '').toUpperCase();
  const color = KIND_COLOR[p.kind] || '#74849f';
  const meta = [p.region, p.country].filter(Boolean).join(' · ');
  const extras = [];
  if (p.date)  extras.push(`<div class="popup-extra"><strong>When:</strong> ${escapeHtml(p.date)}</div>`);
  if (p.price) extras.push(`<div class="popup-extra"><strong>Price:</strong> ${escapeHtml(p.price)}</div>`);
  return `
    <div class="popup">
      <div class="popup-kind" style="color:${color}">
        <span class="popup-dot" style="background:${color}"></span>${escapeHtml(kind)}
      </div>
      <div class="popup-name">${escapeHtml(p.name || 'Unnamed')}</div>
      ${meta ? `<div class="popup-meta">${escapeHtml(meta)}</div>` : ''}
      ${p.description ? `<div class="popup-desc">${escapeHtml(p.description)}</div>` : ''}
      ${extras.join('')}
    </div>
  `;
}

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