// ─── MAP view ─────────────────────────────────────────────────────────

const MapView = ({ activeFilter, setActiveFilter, onBack, onProfile, onClaim, user }) => {
  const t = useT();
  const [search, setSearch] = useState('');
  const [selected, setSelected] = useState(null);
  const [bizVer, setBizVer] = useState(0);
  const [bdayRedemptions, setBdayRedemptions] = useState(new Set());
  const [mapZone, setMapZone] = useState(() => localStorage.getItem('helixZone') || (window.ZONES?.[0]?.id || ZONES?.[0]?.id));
  const [showZoneDropdown, setShowZoneDropdown] = useState(false);
  const mapRef = useRef(null);
  const leafletMap = useRef(null);
  const markersRef = useRef([]);
  const markersMapRef = useRef({}); // id → { marker, biz }
  // Read __helixPendingBiz synchronously at mount, before any useEffect runs.
  // This guarantees the ref is set before getCurrentPosition can fire.
  const bizFocusRef = useRef(window.__helixPendingBiz || null);
  const userCenteredRef = useRef(true); // nunca auto-centrar; el usuario usa el botón de ubicación

  const handleZoneChange = (zoneId) => {
    setMapZone(zoneId);
    setShowZoneDropdown(false);
    setSelected(null);
    userCenteredRef.current = true;
    const zonesData = window.ZONES?.length ? window.ZONES : ZONES;
    const zd = zonesData.find(z => z.id === zoneId) || zonesData[0];
    if (zd && leafletMap.current) leafletMap.current.flyTo([zd.lat, zd.lng], 13, { animate: true, duration: 1 });
    window.loadBusinesses(zoneId).then(() => setBizVer(v => v + 1));
  };

  // Fetch birthday redemptions whenever user or birthday filter activates
  useEffect(() => {
    if (!user?.id) return;
    fetch(`${API}/birthday/user?userId=${user.id}`)
      .then(r => r.json())
      .then(data => {
        if (Array.isArray(data.redemptions)) {
          setBdayRedemptions(new Set(data.redemptions.map(r => r.business_id)));
        }
      })
      .catch(() => {});
  }, [user?.id, activeFilter === 'birthday']);

  // Differentiated palette — each category gets a distinct, high-contrast hue
  const CAT_COLOR = {
    food:      '#0891B2', // deep cyan  — cool, refreshing
    adventure: '#0D9488', // teal       — Helix brand, outdoors
    grooming:  '#7C3AED', // violet     — premium, beauty
    lifestyle: '#D97706', // amber      — warm, energetic
  };

  const makeIcon = (b, isActive, bdayMode = false, promoMode = false) => {
    let color = CAT_COLOR[b.category] || '#0D9488';
    let glyph = CATEGORY_GLYPH[b.category] || '✦';
    if (bdayMode && b.birthday_active) {
      color = bdayRedemptions.has(b.id) ? '#9CA3AF' : '#E91E8C';
      glyph = '🎁';
    } else if (promoMode && b.has_promo_today) {
      color = '#D97706';
      glyph = '🔥';
    }
    const scale  = isActive ? 'scale(1.3)' : 'scale(1)';
    const shadow = isActive
      ? '0 8px 28px rgba(0,0,0,0.50), 0 3px 8px rgba(0,0,0,0.30)'
      : '0 3px 8px rgba(0,0,0,0.22), 0 1px 3px rgba(0,0,0,0.14)';
    return L.divIcon({
      html: `<div style="
        width:32px;height:32px;
        border-radius:50% 50% 50% 0;
        transform:rotate(-45deg) ${scale};
        background:${color};
        display:flex;align-items:center;justify-content:center;
        box-shadow:${shadow};
        border:1.5px solid rgba(255,255,255,0.85);
      "><span style="
        transform:rotate(45deg);
        font-size:13px;
        color:white;
        line-height:1;
        display:block;
      ">${glyph}</span></div>`,
      className: '',
      iconSize:   [32, 32],
      iconAnchor: [16, 32],
    });
  };

  const [userPos, setUserPos] = useState(null);
  const [geoStatus, setGeoStatus] = useState(null); // 'granted' | 'denied' | 'prompt'

  useEffect(() => {
    if (!navigator.permissions) return;
    let permResult = null;
    navigator.permissions.query({ name: 'geolocation' }).then(r => {
      permResult = r;
      setGeoStatus(r.state);
      r.onchange = () => setGeoStatus(r.state);
    }).catch(() => {});
    return () => { if (permResult) permResult.onchange = null; };
  }, []);

  const getDistance = (b) => {
    if (!userPos) return -(b.featured_order || 0);
    return Math.hypot(b.lat - userPos.lat, b.lng - userPos.lng);
  };

  const filtered = activeFilter === 'all'
    ? BUSINESSES
    : activeFilter === 'birthday'
      ? BUSINESSES.filter(b => b.birthday_active)
      : activeFilter === 'promo_hoy'
        ? BUSINESSES.filter(b => b.has_promo_today)
        : BUSINESSES.filter(b => b.category === activeFilter);
  const searchLow = search.trim().toLowerCase();
  const visible = [...filtered]
    .filter(b => !searchLow || b.name.toLowerCase().includes(searchLow) || (b.tag || '').toLowerCase().includes(searchLow))
    .sort((a, b) => {
      if (!userPos) {
        const order = [1, 2, 3, 0];
        const oa = order.indexOf(a.featured_order) === -1 ? 3 : order.indexOf(a.featured_order);
        const ob = order.indexOf(b.featured_order) === -1 ? 3 : order.indexOf(b.featured_order);
        return oa - ob;
      }
      return getDistance(a) - getDistance(b);
    });

  useEffect(() => {
    window.__helixMapSelect = (b) => {
      bizFocusRef.current = b;
      userCenteredRef.current = true; // prevent GPS from overriding the business focus
      setSelected(b);
      if (leafletMap.current) leafletMap.current.setView([b.lat, b.lng], 14, { animate: true });
    };
    return () => { window.__helixMapSelect = null; };
  }, []);

  useEffect(() => {
    if (!mapRef.current || leafletMap.current) return;
    const zonesData = window.ZONES?.length ? window.ZONES : ZONES;
    const activeZone = zonesData.find(z => z.id === mapZone) || zonesData[0];
    const biz = bizFocusRef.current;
    const initCenter = biz ? [biz.lat, biz.lng] : [activeZone.lat, activeZone.lng];
    const initZoom = biz ? 14 : 12;
    leafletMap.current = L.map(mapRef.current, {
      center: initCenter,
      zoom: initZoom,
      zoomControl: false,
      attributionControl: false
    });
    L.tileLayer('https://{s}.basemaps.cartocdn.com/light_all/{z}/{x}/{y}{r}.png', {
      maxZoom: 19
    }).addTo(leafletMap.current);

    window.__helixPendingBiz = null; // consumed, clear global

    // Ubicación del usuario
    if (navigator.geolocation) {
      navigator.geolocation.getCurrentPosition(
        (pos) => {
          const { latitude, longitude } = pos.coords;
          setUserPos({ lat: latitude, lng: longitude });

        },
        () => {} // si falla, se queda en el centro de la zona
      );
    }
  }, []);

   const userMarkerRef = useRef(null);

  useEffect(() => {
    if (!userPos || !leafletMap.current) return;
    if (userMarkerRef.current) userMarkerRef.current.remove();
    const userIcon = L.divIcon({
      html: `<div style="width:16px;height:16px;border-radius:50%;background:#0D9488;border:3px solid white;box-shadow:0 2px 8px rgba(13,148,136,0.5)"></div>`,
      className: '', iconSize: [16, 16], iconAnchor: [8, 8]
    });
    userMarkerRef.current = L.marker([userPos.lat, userPos.lng], { icon: userIcon }).addTo(leafletMap.current);
    if (!userCenteredRef.current) {
      leafletMap.current.setView([userPos.lat, userPos.lng], 15, { animate: true });
      userCenteredRef.current = true;
    }
  }, [userPos]);

  useEffect(() => {
    if (!leafletMap.current) return;
    markersRef.current.forEach(m => m.remove());
    markersRef.current = [];
    markersMapRef.current = {};
    const isBday = activeFilter === 'birthday';
    const isPromo = activeFilter === 'promo_hoy';
    filtered.forEach(b => {
      const marker = L.marker([b.lat, b.lng], { icon: makeIcon(b, false, isBday, isPromo) })
        .addTo(leafletMap.current)
        .on('click', () => setSelected(b));
      markersRef.current.push(marker);
      markersMapRef.current[b.id] = { marker, biz: b };
    });
  }, [activeFilter, bizVer]);

  // Refresh birthday marker colors when redemption data arrives
  useEffect(() => {
    if (activeFilter !== 'birthday') return;
    Object.values(markersMapRef.current).forEach(({ marker, biz }) => {
      marker.setIcon(makeIcon(biz, selected?.id === biz.id, true, false));
    });
  }, [bdayRedemptions]);

  // Highlight active marker; reset previous one
  useEffect(() => {
    const isBday = activeFilter === 'birthday';
    const isPromo = activeFilter === 'promo_hoy';
    Object.values(markersMapRef.current).forEach(({ marker, biz }) => {
      marker.setIcon(makeIcon(biz, false, isBday, isPromo));
    });
    if (selected && markersMapRef.current[selected.id]) {
      markersMapRef.current[selected.id].marker.setIcon(makeIcon(selected, true, isBday, isPromo));
    }
  }, [selected]);

  return (
    <div className="view-enter">
      <HeaderBar title={t('map_title')} onBack={onBack} onProfile={onProfile}/>

      {/* Filters */}
      {geoStatus && geoStatus !== 'granted' && (
  <div style={{
    margin:'10px 24px 0',
    background:'rgba(13,148,136,0.08)',
    border:'1px solid rgba(13,148,136,0.2)',
    borderRadius:12, padding:'10px 14px',
    display:'flex', alignItems:'center', justifyContent:'space-between', gap:10
  }}>
    <div style={{ fontSize:12, color:'var(--ink)', lineHeight:1.4 }}>
      <span style={{ fontWeight:700, color:'var(--teal)' }}>📍 </span>
      {t('map_geo_banner')}
    </div>
    <button onClick={() => navigator.geolocation.getCurrentPosition(
      (pos) => {
        setUserPos({ lat: pos.coords.latitude, lng: pos.coords.longitude });
        setGeoStatus('granted');
      },
      () => setGeoStatus('denied'),
      { timeout: 5000, maximumAge: 60000 }
    )} style={{
      background:'var(--teal)', color:'white', border:0,
      borderRadius:8, padding:'7px 12px',
      fontSize:11, fontWeight:700, cursor:'pointer', whiteSpace:'nowrap'
    }}>{t('map_geo_cta')}</button>
  </div>
)}
      <div className="no-scrollbar" style={{
        padding:'14px 24px 6px',
        display:'flex', gap:8, overflowX:'auto',
        scrollbarWidth:'none'
      }}>
        {CATEGORIES.map(c => {
          const active = activeFilter === c.id;
          return (
            <button
              key={c.id}
              onClick={() => setActiveFilter(c.id)}
              className="filter-pill"
              style={{
                background: active ? 'var(--ink)' : 'var(--fog)',
                color: active ? 'white' : 'var(--ink)',
                border:0,
                borderRadius:99,
                padding:'9px 14px',
                fontSize:12.5, fontWeight:600,
                letterSpacing:'.01em',
                whiteSpace:'nowrap',
                cursor:'pointer',
                display:'inline-flex', alignItems:'center', gap:6,
                flexShrink:0
              }}
            >
              <span style={{ opacity: active ? 1 : .55 }}>{c.glyph}</span>
              {t(c.labelKey)}
            </button>
          );
        })}
        <button
          onClick={() => setActiveFilter(activeFilter === 'birthday' ? 'all' : 'birthday')}
          className="filter-pill"
          style={{
            background: activeFilter === 'birthday' ? '#E91E8C' : 'var(--fog)',
            color: activeFilter === 'birthday' ? 'white' : '#E91E8C',
            border: activeFilter === 'birthday' ? 0 : '1.5px solid rgba(233,30,140,0.35)',
            borderRadius:99,
            padding:'9px 14px',
            fontSize:12.5, fontWeight:700,
            whiteSpace:'nowrap',
            cursor:'pointer',
            display:'inline-flex', alignItems:'center', gap:5,
            flexShrink:0
          }}
        >
          {t('map_filter_birthday')}
        </button>
        {BUSINESSES.some(b => b.has_promo_today) && (
          <button
            onClick={() => setActiveFilter(activeFilter === 'promo_hoy' ? 'all' : 'promo_hoy')}
            className="filter-pill"
            style={{
              background: activeFilter === 'promo_hoy' ? '#D97706' : 'var(--fog)',
              color: activeFilter === 'promo_hoy' ? 'white' : '#D97706',
              border: activeFilter === 'promo_hoy' ? 0 : '1.5px solid rgba(217,119,6,0.35)',
              borderRadius:99,
              padding:'9px 14px',
              fontSize:12.5, fontWeight:700,
              whiteSpace:'nowrap',
              cursor:'pointer',
              display:'inline-flex', alignItems:'center', gap:5,
              flexShrink:0
            }}
          >
            {t('map_filter_promo')}
          </button>
        )}
      </div>

      {/* Map */}
      <div style={{ padding:'10px 24px 0' }}>
        <div style={{
          position:'relative',
          height:'52vh',
          minHeight:380,
          borderRadius:18, overflow:'hidden',
          border:'1px solid rgba(15,23,42,0.08)',
        }}>
          <div ref={mapRef} style={{ width:'100%', height:'100%' }}/>
          <div style={{ position:'absolute', top:14, left:14, zIndex:1000 }}>
            <button onClick={() => setShowZoneDropdown(v => !v)} style={{
              background:'rgba(251,249,243,0.92)',
              backdropFilter:'blur(8px)',
              padding:'6px 10px', borderRadius:99,
              fontSize:10, fontWeight:700, letterSpacing:'.16em',
              textTransform:'uppercase',
              border:'none', cursor:'pointer',
              display:'flex', alignItems:'center', gap:5
            }}>
              {(window.ZONES || ZONES).find(z => z.id === mapZone)?.label || mapZone || ''}
              <svg width="10" height="10" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2.5" strokeLinecap="round" strokeLinejoin="round"><polyline points="6 9 12 15 18 9"/></svg>
            </button>
            {showZoneDropdown && (
              <>
                <div onClick={() => setShowZoneDropdown(false)} style={{ position:'fixed', inset:0, zIndex:999 }}/>
                <div style={{
                  position:'absolute', top:'calc(100% + 6px)', left:0, zIndex:1001,
                  background:'rgba(251,249,243,0.98)', backdropFilter:'blur(12px)',
                  borderRadius:14, overflow:'hidden',
                  boxShadow:'0 8px 24px rgba(15,23,42,0.2)',
                  border:'1px solid rgba(15,23,42,0.08)',
                  minWidth:150
                }}>
                  {(window.ZONES || ZONES).map(z => (
                    <button key={z.id} onClick={() => handleZoneChange(z.id)} style={{
                      display:'block', width:'100%',
                      padding:'10px 14px', textAlign:'left',
                      background: z.id === mapZone ? 'rgba(13,148,136,0.1)' : 'transparent',
                      border:'none', cursor:'pointer',
                      fontSize:13, fontWeight: z.id === mapZone ? 700 : 500,
                      color: z.id === mapZone ? 'var(--teal)' : 'var(--ink)',
                      letterSpacing:'.01em'
                    }}>
                      {z.label}
                    </button>
                  ))}
                </div>
              </>
            )}
          </div>
          <div style={{
            position:'absolute', top:14, right:14, zIndex:1000,
            background:'rgba(15,23,42,0.85)',
            color:'white',
            padding:'6px 10px', borderRadius:99,
            fontSize:10, fontWeight:700, letterSpacing:'.12em',
            textTransform:'uppercase',
            display:'flex', alignItems:'center', gap:5
          }}>
            <span style={{ width:6, height:6, borderRadius:99, background:'var(--cyan)' }} className="pulse-soft"/>
            {filtered.length} {t('home_spots_plural')}
          </div>
          {userPos && (
            <button
              onClick={() => leafletMap.current && leafletMap.current.setView([userPos.lat, userPos.lng], 15, { animate: true })}
              title={t('map_center_btn')}
              style={{
                position:'absolute', bottom: selected ? 118 : 14, right:14, zIndex:1000,
                width:40, height:40,
                background:'rgba(15,23,42,0.88)',
                border:'1.5px solid rgba(255,255,255,0.12)',
                borderRadius:12,
                display:'flex', alignItems:'center', justifyContent:'center',
                cursor:'pointer',
                boxShadow:'0 4px 16px rgba(0,0,0,0.4)',
                backdropFilter:'blur(6px)',
                transition:'bottom 0.25s ease, opacity 0.2s',
              }}
            >
              <svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="#0D9488" strokeWidth="2.2" strokeLinecap="round" strokeLinejoin="round">
                <circle cx="12" cy="12" r="4"/>
                <line x1="12" y1="2" x2="12" y2="6"/>
                <line x1="12" y1="18" x2="12" y2="22"/>
                <line x1="2" y1="12" x2="6" y2="12"/>
                <line x1="18" y1="12" x2="22" y2="12"/>
              </svg>
            </button>
          )}
          {selected && (
            <div key={selected.id}
              onClick={e => {
                if (e.target.closest('button,a')) return;
                if (leafletMap.current) leafletMap.current.panTo([selected.lat, selected.lng], { animate: true });
              }}
              style={{
                position:'absolute', left:12, right:12, bottom:12, zIndex:1000,
                background:'rgba(251,249,243,0.96)',
                backdropFilter:'blur(14px)',
                borderRadius:14, padding:12,
                display:'grid', gridTemplateColumns:'60px 1fr auto',
                gap:12, alignItems:'center',
                border:'1px solid rgba(15,23,42,0.08)',
                boxShadow:'0 10px 30px rgba(15,23,42,0.18)',
                animation:'slideUp .25s cubic-bezier(.2,.8,.2,1) both',
                cursor:'pointer',
              }}>
              <SmartImg src={selected.img} alt={selected.name} style={{ width:60, height:60, borderRadius:10 }}/>
              <div style={{ minWidth:0 }}>
                <div className="label-eyebrow" style={{ marginBottom:3 }}>{selected.tag}</div>
                <div style={{ fontWeight:800, fontSize:14, letterSpacing:'-0.01em', whiteSpace:'nowrap', overflow:'hidden', textOverflow:'ellipsis' }}>{selected.name}</div>
                {activeFilter === 'birthday' && selected.birthday_active ? (
                  bdayRedemptions.has(selected.id) ? (
                    <div style={{ fontSize:10, color:'#9CA3AF', fontWeight:600, marginTop:3 }}>✓ {t('map_bday_redeemed')}</div>
                  ) : (
                    <div>
                      {selected.birthday_gift && <div style={{ fontSize:11, color:'#E91E8C', fontWeight:700, marginTop:3 }}>🎁 {selected.birthday_gift}</div>}
                      {selected.birthday_terms && <div style={{ fontSize:10, color:'var(--muted)', marginTop:2, lineHeight:1.35, overflow:'hidden', display:'-webkit-box', WebkitLineClamp:2, WebkitBoxOrient:'vertical' }}><span style={{ fontWeight:700 }}>{t('map_bday_terms_label')}: </span>{selected.birthday_terms}</div>}
                    </div>
                  )
                ) : (
                  <>
                    <div style={{ fontSize:11, color:'var(--muted)', marginTop:2 }}>{selected.address}</div>
                    {selected.has_promo_today && (
                      <div style={{ fontSize:11, color:'#D97706', fontWeight:700, marginTop:3, lineHeight:1.3 }}>
                        🔥 {selected.promo_today_es || t('map_promo_badge')}
                        {selected.promo_today_en && selected.promo_today_en !== selected.promo_today_es && (
                          <span style={{ fontWeight:500, color:'#B45309', fontSize:10 }}> · {selected.promo_today_en}</span>
                        )}
                      </div>
                    )}
                  </>
                )}
              </div>
              <div style={{ display:'flex', flexDirection:'column', gap:6 }}>
                <button onClick={() => { onClaim(activeFilter === 'birthday' ? { ...selected, _birthdayMode: true } : selected); }} style={{
                  background: activeFilter === 'birthday' ? '#E91E8C' : 'var(--teal)', color:'white',
                  border:0, borderRadius:10,
                  padding:'8px 12px', fontSize:11.5, fontWeight:700,
                  letterSpacing:'.04em', textTransform:'uppercase',
                  cursor:'pointer'
                }}>{t('home_see_more')}</button>
                <a href={`https://maps.google.com/maps?daddr=${selected.lat},${selected.lng}`} target="_blank" rel="noopener noreferrer"
                  style={{
                    background:'var(--fog)', color:'var(--ink)',
                    border:'1px solid rgba(15,23,42,0.1)',
                    borderRadius:10,
                    padding:'8px 12px', fontSize:11, fontWeight:600,
                    textAlign:'center', textDecoration:'none',
                    display:'block'
                  }}>{t('map_directions')}</a>
              </div>
            </div>
          )}
        </div>
      </div>

      {/* List */}
      <div style={{ padding:'22px 24px 0' }}>
        <input
          value={search}
          onChange={e => setSearch(e.target.value)}
          placeholder={t('map_search_placeholder')}
          style={{ width:'100%', boxSizing:'border-box', background:'var(--fog)', border:'1px solid rgba(15,23,42,0.1)', borderRadius:12, padding:'12px 16px', fontSize:14, outline:'none', marginBottom:16, fontFamily:'inherit' }}
        />
        <SectionLabel style={{ padding:0 }}>
          {activeFilter === 'all' ? (userPos ? t('map_nearby') : t('map_featured')) : `${userPos ? t('map_nearby') : t('map_featured')} · ${t(CATEGORIES.find(c=>c.id===activeFilter)?.labelKey || (activeFilter === 'promo_hoy' ? 'map_filter_promo' : 'map_filter_birthday'))}`}
        </SectionLabel>
        <div style={{ display:'grid', gridTemplateColumns:'1fr 1fr', gap:10 }}>
          {visible.map(b => (
            <button
              key={b.id}
              onClick={() => { setSelected(b); if (leafletMap.current) leafletMap.current.setView([b.lat, b.lng], 14, { animate: true }); window.scrollTo({ top: 0, behavior: 'smooth' }); }}
              style={{
                background:'var(--fog)',
                border:'1px solid rgba(15,23,42,0.06)',
                borderRadius:14,
                overflow:'hidden',
                textAlign:'left', cursor:'pointer',
                color:'var(--ink)', padding:0
              }}>
              <div style={{ position:'relative' }}>
                <SmartImg src={b.img} alt={b.name} style={{ width:'100%', aspectRatio:'4/3', objectFit:'cover', display:'block' }}/>
                {b.featured_order > 0 && (
                  <div style={{ position:'absolute', top:7, left:7, background:'linear-gradient(135deg,#0D9488,#06B6D4)', color:'white', borderRadius:99, padding:'3px 7px', fontSize:9, fontWeight:800, letterSpacing:'.06em', display:'flex', alignItems:'center', gap:3 }}>
                    <IconStar size={8}/> {t('map_featured_badge')}
                  </div>
                )}
              </div>
              <div style={{ padding:'10px 10px 12px' }}>
                <div className="label-eyebrow" style={{ marginBottom:3, fontSize:9 }}>{b.tag}</div>
                <div style={{ fontWeight:700, fontSize:13, letterSpacing:'-0.01em', lineHeight:1.3 }}>{b.name}</div>
                {b.has_promo_today && b.promo_today_es && (
                  <div style={{ fontSize:10, color:'#D97706', fontWeight:700, marginTop:4, lineHeight:1.3 }}>🔥 {b.promo_today_es}</div>
                )}
              </div>
            </button>
          ))}
          {visible.length === 0 && (
            <div style={{
              padding:'30px 14px', textAlign:'center',
              color:'var(--muted)', fontSize:13
            }}>
              {t('map_empty')}
            </div>
          )}
        </div>
      </div>
    </div>
  );
};

Object.assign(window, { MapView });