'use client';

import 'leaflet/dist/leaflet.css';
import Link from 'next/link';
import { useEffect, useMemo, useRef, useState } from 'react';
import { useI18n } from '../components/I18nProvider';

type ListingResult = {
  id: string;
  title: string;
  slug: string;
  teaser: string | null;
  locale: string | null;
  country: string;
  region: string;
  city: string;
  streetAddress: string | null;
  addressNote: string | null;
  latitude: number | null;
  longitude: number | null;
  hasSauna: boolean;
  hasFireplace: boolean;
  hasWifi: boolean;
  petsAllowed: boolean;
  byTheLake: boolean;
  hasAirConditioning: boolean;
  hasKitchen: boolean;
  hasDishwasher: boolean;
  hasWashingMachine: boolean;
  hasBarbecue: boolean;
  hasMicrowave: boolean;
  hasFreeParking: boolean;
  evChargingAvailable: boolean;
  evChargingOnSite: boolean;
  wheelchairAccessible: boolean;
  hasSkiPass: boolean;
  maxGuests: number;
  bedrooms: number;
  beds: number;
  bathrooms: number;
  priceWeekdayEuros: number | null;
  priceWeekendEuros: number | null;
  coverImage: string | null;
  isSample: boolean;
  hasCalendar: boolean;
  availableForDates?: boolean;
};

type LatLng = { lat: number; lon: number };

function haversineKm(a: LatLng, b: LatLng) {
  const toRad = (v: number) => (v * Math.PI) / 180;
  const R = 6371;
  const dLat = toRad(b.lat - a.lat);
  const dLon = toRad(b.lon - a.lon);
  const lat1 = toRad(a.lat);
  const lat2 = toRad(b.lat);
  const sinLat = Math.sin(dLat / 2);
  const sinLon = Math.sin(dLon / 2);
  const h = sinLat * sinLat + Math.cos(lat1) * Math.cos(lat2) * sinLon * sinLon;
  return 2 * R * Math.atan2(Math.sqrt(h), Math.sqrt(1 - h));
}

type LeafletLib = typeof import('leaflet');

async function loadLeaflet(): Promise<LeafletLib> {
  if (typeof window === 'undefined') return Promise.reject(new Error('No window'));
  if ((window as any).L) return (window as any).L as LeafletLib;
  const linkId = 'leaflet-css';
  if (!document.getElementById(linkId)) {
    const link = document.createElement('link');
    link.id = linkId;
    link.rel = 'stylesheet';
    link.href = 'https://unpkg.com/leaflet@1.9.4/dist/leaflet.css';
    document.head.appendChild(link);
  }
  const mod: LeafletLib = await import('leaflet');
  (window as any).L = mod;
  return mod;
}

const amenityIcons: Record<string, string> = {
  sauna: '🧖',
  fireplace: '🔥',
  wifi: '📶',
  pets: '🐾',
  lake: '🌊',
  ac: '❄️',
  kitchen: '🍽️',
  dishwasher: '🧼',
  washer: '🧺',
  barbecue: '🍖',
  microwave: '🍲',
  parking: '🅿️',
  accessible: '♿',
  ski: '⛷️',
  ev: '⚡',
  evOnSite: '🔌',
};

function ListingsMap({
  listings,
  center,
  selectedId,
  onSelect,
  loadingText,
}: {
  listings: ListingResult[];
  center: LatLng | null;
  selectedId: string | null;
  onSelect: (id: string) => void;
  loadingText: string;
}) {
  const mapContainerRef = useRef<HTMLDivElement | null>(null);
  const mapRef = useRef<any>(null);
  const markersRef = useRef<any[]>([]);
  const [ready, setReady] = useState(false);
  const [mapError, setMapError] = useState<string | null>(null);

  useEffect(() => {
    let cancelled = false;
    loadLeaflet()
      .then((L) => {
        if (cancelled) return;
        setReady(true);
        setMapError(null);
        if (!mapContainerRef.current) return;
        if (!mapRef.current) {
          mapRef.current = L.map(mapContainerRef.current).setView([64.5, 26], 5);
          L.tileLayer('https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', {
            attribution: '&copy; OpenStreetMap contributors',
            maxZoom: 18,
          }).addTo(mapRef.current);
        }

        markersRef.current.forEach((m) => m.remove());
        markersRef.current = [];

        listings
          .filter((l) => l.latitude !== null && l.longitude !== null)
          .forEach((l) => {
            const marker = L.marker([l.latitude!, l.longitude!], { title: l.title });
            marker.addTo(mapRef.current);
            marker.on('click', () => onSelect(l.id));
            markersRef.current.push(marker);
          });

        const withCoords = listings.filter((l) => l.latitude !== null && l.longitude !== null);
        if (center && mapRef.current) {
          mapRef.current.setView([center.lat, center.lon], 8);
        } else if (withCoords.length && mapRef.current) {
          const group = L.featureGroup(
            withCoords.map((l) => L.marker([l.latitude as number, l.longitude as number]))
          );
          mapRef.current.fitBounds(group.getBounds().pad(0.25));
        }
      })
      .catch((err) => {
        console.error('Leaflet load failed', err);
        setReady(false);
        setMapError('Map could not be loaded right now.');
      });

    return () => {
      cancelled = true;
    };
  }, [listings, center, onSelect]);

  useEffect(() => {
    if (!mapRef.current || !selectedId) return;
    const listing = listings.find((l) => l.id === selectedId);
    if (listing && listing.latitude && listing.longitude) {
      mapRef.current.setView([listing.latitude, listing.longitude], 10);
    }
  }, [selectedId, listings]);

  return (
    <div className="map-frame">
      {!ready ? <div className="map-placeholder">{loadingText}</div> : null}
      {mapError ? <div className="map-placeholder">{mapError}</div> : null}
      <div ref={mapContainerRef} style={{ width: '100%', height: '100%' }} />
    </div>
  );
}

export default function ListingsIndexPage() {
  const { t } = useI18n();
  const [query, setQuery] = useState('');
  const [city, setCity] = useState('');
  const [region, setRegion] = useState('');
  const [listings, setListings] = useState<ListingResult[]>([]);
  const [loading, setLoading] = useState(false);
  const [error, setError] = useState<string | null>(null);
  const [selectedId, setSelectedId] = useState<string | null>(null);
  const [addressQuery, setAddressQuery] = useState('');
  const [addressCenter, setAddressCenter] = useState<LatLng | null>(null);
  const [radiusKm, setRadiusKm] = useState(50);
  const [geocoding, setGeocoding] = useState(false);
  const [geoError, setGeoError] = useState<string | null>(null);
  const [startDate, setStartDate] = useState('');
  const [endDate, setEndDate] = useState('');
  const [amenities, setAmenities] = useState<string[]>([]);
  const scrollRef = useRef<HTMLDivElement | null>(null);

  const filteredByAddress = useMemo(() => {
    if (!addressCenter) return listings;
    return listings.filter((l) => {
      if (l.latitude === null || l.longitude === null) return false;
      const d = haversineKm(addressCenter, { lat: l.latitude, lon: l.longitude });
      return d <= radiusKm;
    });
  }, [listings, addressCenter, radiusKm]);

  const filtered = filteredByAddress;

  const amenityOptions = [
    { key: 'sauna', label: t('amenitySauna'), icon: amenityIcons.sauna },
    { key: 'fireplace', label: t('amenityFireplace'), icon: amenityIcons.fireplace },
    { key: 'wifi', label: t('amenityWifi'), icon: amenityIcons.wifi },
    { key: 'pets', label: t('amenityPets'), icon: amenityIcons.pets },
    { key: 'lake', label: t('amenityLake'), icon: amenityIcons.lake },
    { key: 'ac', label: t('amenityAirConditioning'), icon: amenityIcons.ac },
    { key: 'kitchen', label: t('amenityKitchen'), icon: amenityIcons.kitchen },
    { key: 'dishwasher', label: t('amenityDishwasher'), icon: amenityIcons.dishwasher },
    { key: 'washer', label: t('amenityWashingMachine'), icon: amenityIcons.washer },
    { key: 'barbecue', label: t('amenityBarbecue'), icon: amenityIcons.barbecue },
    { key: 'microwave', label: t('amenityMicrowave'), icon: amenityIcons.microwave },
    { key: 'parking', label: t('amenityFreeParking'), icon: amenityIcons.parking },
    { key: 'accessible', label: t('amenityWheelchairAccessible'), icon: amenityIcons.accessible },
    { key: 'skipass', label: t('amenitySkiPass'), icon: amenityIcons.ski },
    { key: 'ev', label: t('amenityEvNearby'), icon: amenityIcons.ev },
    { key: 'ev-onsite', label: t('amenityEvOnSite'), icon: amenityIcons.evOnSite },
  ];

  async function fetchListings() {
    setLoading(true);
    setError(null);
    try {
      const params = new URLSearchParams();
      if (query) params.set('q', query);
      if (city) params.set('city', city);
      if (region) params.set('region', region);
      if (startDate) params.set('availableStart', startDate);
      if (endDate) params.set('availableEnd', endDate);
      const evSelected = amenities.includes('ev');
      if (evSelected) params.set('evCharging', 'true');
      amenities
        .filter((a) => a !== 'ev')
        .forEach((a) => params.append('amenity', a));
      const res = await fetch(`/api/listings?${params.toString()}`, { cache: 'no-store' });
      const data = await res.json();
      if (!res.ok || data.error) {
        throw new Error(data.error || 'Failed to load listings');
      }
      setListings(data.listings ?? []);
      setSelectedId(data.listings?.[0]?.id ?? null);
    } catch (e: any) {
      setError(e.message || 'Failed to load listings');
    } finally {
      setLoading(false);
    }
  }

  function toggleAmenity(key: string) {
    setAmenities((prev) => (prev.includes(key) ? prev.filter((k) => k !== key) : [...prev, key]));
  }

  async function locateAddress() {
    if (!addressQuery.trim()) return;
    setGeocoding(true);
    setGeoError(null);
    try {
      const res = await fetch(
        `https://nominatim.openstreetmap.org/search?format=json&q=${encodeURIComponent(addressQuery)}&limit=1`
      );
      const data = await res.json();
      if (Array.isArray(data) && data.length > 0) {
        const hit = data[0];
        setAddressCenter({ lat: parseFloat(hit.lat), lon: parseFloat(hit.lon) });
      } else {
        setGeoError(t('addressNotFound'));
      }
    } catch (e) {
      setGeoError(t('addressLookupFailed'));
    } finally {
      setGeocoding(false);
    }
  }

  useEffect(() => {
    fetchListings();
    // eslint-disable-next-line react-hooks/exhaustive-deps
  }, []);

  const countLabel = t('listingsFound', { count: filtered.length });

  useEffect(() => {
    if (!selectedId) return;
    const el = document.querySelector<HTMLElement>(`[data-listing-id="${selectedId}"]`);
    if (el) {
      el.scrollIntoView({ behavior: 'smooth', block: 'center' });
    }
  }, [selectedId]);

  return (
    <main>
      <section className="panel">
        <div className="breadcrumb">
          <Link href="/">{t('homeCrumb')}</Link> / <span>{t('navBrowse')}</span>
        </div>
        <h1>{t('browseListingsTitle')}</h1>
        <p style={{ marginTop: 8 }}>{t('browseListingsLead')}</p>
        <div className="search-grid" style={{ marginTop: 16 }}>
          <label>
            {t('searchLabel')}
            <input
              value={query}
              onChange={(e) => setQuery(e.target.value)}
              placeholder={t('searchPlaceholder')}
              autoComplete="off"
            />
          </label>
          <label>
          {t('cityFilter')}
          <input value={city} onChange={(e) => setCity(e.target.value)} placeholder={t('cityFilter')} />
        </label>
        <label>
          {t('regionFilter')}
          <input value={region} onChange={(e) => setRegion(e.target.value)} placeholder={t('regionFilter')} />
        </label>
      </div>
        <div style={{ display: 'grid', gap: 10, gridTemplateColumns: 'repeat(auto-fit, minmax(180px, 1fr))', marginTop: 12 }}>
          <label>
            {t('startDate')}
            <input type="date" value={startDate} onChange={(e) => setStartDate(e.target.value)} />
          </label>
          <label>
            {t('endDate')}
            <input type="date" value={endDate} onChange={(e) => setEndDate(e.target.value)} />
          </label>
        </div>
        <div style={{ marginTop: 8, color: '#cbd5e1', fontSize: 13 }}>{t('availabilityOnlyWithCalendar')}</div>
        <div className="amenity-grid" style={{ marginTop: 12 }}>
          <div style={{ gridColumn: '1 / -1', color: '#cbd5e1', fontWeight: 600 }}>{t('searchAmenities')}</div>
          {amenityOptions.map((opt) => (
            <button
              key={opt.key}
              type="button"
              className={`amenity-option ${amenities.includes(opt.key) ? 'selected' : ''}`}
              aria-pressed={amenities.includes(opt.key)}
              onClick={() => toggleAmenity(opt.key)}
            >
              <div className="amenity-option-meta">
                <span className="amenity-emoji" aria-hidden>
                  {opt.icon}
                </span>
                <span className="amenity-name">{opt.label}</span>
              </div>
              <span className="amenity-check" aria-hidden>
                {amenities.includes(opt.key) ? '✓' : ''}
              </span>
            </button>
          ))}
        </div>
        <div style={{ display: 'flex', gap: 10, marginTop: 12, flexWrap: 'wrap' }}>
          <button className="button" onClick={fetchListings} disabled={loading}>
            {loading ? t('loading') : t('searchButton')}
          </button>
          <button
            className="button secondary"
            onClick={() => {
              setQuery('');
              setCity('');
              setRegion('');
              setAddressCenter(null);
              setAddressQuery('');
              setStartDate('');
              setEndDate('');
              setAmenities([]);
            }}
          >
            {t('clearFilters')}
          </button>
          <span style={{ alignSelf: 'center', color: '#cbd5e1' }}>{countLabel}</span>
        </div>
        {error ? <p style={{ marginTop: 8, color: '#ef4444' }}>{error}</p> : null}
      </section>

      <section className="map-grid" style={{ marginTop: 18 }}>
        <div className="panel">
          <div style={{ display: 'grid', gap: 10, marginBottom: 12 }}>
            <label>
              {t('addressSearchLabel')}
              <input
                value={addressQuery}
                onChange={(e) => setAddressQuery(e.target.value)}
                placeholder={t('addressSearchPlaceholder')}
              />
            </label>
            <div style={{ display: 'flex', gap: 8, alignItems: 'center', flexWrap: 'wrap' }}>
              <button className="button secondary" onClick={locateAddress} disabled={geocoding}>
                {geocoding ? t('loading') : t('locateAddress')}
              </button>
              <label style={{ display: 'flex', alignItems: 'center', gap: 8 }}>
                <input
                  type="range"
                  min={10}
                  max={200}
                  step={10}
                  value={radiusKm}
                  onChange={(e) => setRadiusKm(Number(e.target.value))}
                  disabled={!addressCenter}
                />
                <span style={{ color: '#cbd5e1' }}>{t('addressRadiusLabel', { km: radiusKm })}</span>
              </label>
              {addressCenter ? (
                <button className="button secondary" onClick={() => setAddressCenter(null)}>
                  {t('clearFilters')}
                </button>
              ) : null}
            </div>
            {geoError ? <p style={{ color: '#ef4444' }}>{geoError}</p> : null}
          </div>
          <ListingsMap
            listings={filtered}
            center={addressCenter}
            selectedId={selectedId}
            onSelect={setSelectedId}
            loadingText={t('loadingMap')}
          />
        </div>
        <div className="panel">
          <div style={{ display: 'flex', alignItems: 'center', justifyContent: 'space-between', marginBottom: 10 }}>
            <strong>{countLabel}</strong>
            {addressCenter ? (
              <span className="badge">{t('addressRadiusLabel', { km: radiusKm })}</span>
            ) : null}
          </div>
          {filtered.length === 0 ? (
            <p>{t('mapNoResults')}</p>
          ) : (
            <div className="results-grid" ref={scrollRef}>
              {filtered.map((l) => (
                <article
                  key={l.id}
                  className={`listing-card ${selectedId === l.id ? 'active' : ''}`}
                  data-listing-id={l.id}
                  onMouseEnter={() => setSelectedId(l.id)}
                  onClick={() => setSelectedId(l.id)}
                >
                  <Link href={`/listings/${l.slug}`} aria-label={l.title} style={{ display: 'block' }}>
                    {l.coverImage ? (
                      <img src={l.coverImage} alt={l.title} style={{ width: '100%', height: 140, objectFit: 'cover', borderRadius: 12 }} />
                    ) : (
                      <div
                        style={{
                          height: 140,
                          borderRadius: 12,
                          background: 'linear-gradient(120deg, rgba(34,211,238,0.12), rgba(14,165,233,0.12))',
                        }}
                      />
                    )}
                  </Link>
                  <div style={{ display: 'grid', gap: 6, marginTop: 8 }}>
                    <h3 style={{ margin: 0 }}>{l.title}</h3>
                    {l.isSample ? (
                      <span className="badge warning" style={{ width: 'fit-content' }}>
                        {t('sampleBadge')}
                      </span>
                    ) : null}
                    <p style={{ margin: 0 }}>{l.teaser ?? ''}</p>
                    {l.priceWeekdayEuros || l.priceWeekendEuros ? (
                      <div style={{ color: '#cbd5e1', fontSize: 14 }}>
                        {t('priceStartingFromShort', {
                          price: Math.min(...([l.priceWeekdayEuros, l.priceWeekendEuros].filter((p): p is number => typeof p === 'number'))),
                        })}
                      </div>
                    ) : null}
                    <div style={{ color: '#cbd5e1', fontSize: 14 }}>
                      {l.streetAddress ? `${l.streetAddress}, ` : ''}
                      {l.city}, {l.region}
                    </div>
                    <div style={{ display: 'flex', gap: 6, flexWrap: 'wrap', fontSize: 13 }}>
                      <span className="badge">{t('capacityGuests', { count: l.maxGuests })}</span>
                      <span className="badge">{t('capacityBedrooms', { count: l.bedrooms })}</span>
                      {l.hasCalendar ? <span className="badge secondary">{t('calendarConnected')}</span> : null}
                      {startDate && endDate && l.availableForDates ? (
                        <span className="badge">{t('availableForDates')}</span>
                      ) : null}
                      {l.evChargingOnSite ? <span className="badge">{t('amenityEvOnSite')}</span> : null}
                      {l.evChargingAvailable && !l.evChargingOnSite ? <span className="badge">{t('amenityEvNearby')}</span> : null}
                      {l.wheelchairAccessible ? <span className="badge">{t('amenityWheelchairAccessible')}</span> : null}
                      {l.hasSkiPass ? <span className="badge">{t('amenitySkiPass')}</span> : null}
                      {l.hasAirConditioning ? <span className="badge">{t('amenityAirConditioning')}</span> : null}
                      {l.hasKitchen ? <span className="badge">{t('amenityKitchen')}</span> : null}
                      {l.hasDishwasher ? <span className="badge">{t('amenityDishwasher')}</span> : null}
                      {l.hasWashingMachine ? <span className="badge">{t('amenityWashingMachine')}</span> : null}
                      {l.hasBarbecue ? <span className="badge">{t('amenityBarbecue')}</span> : null}
                      {l.hasMicrowave ? <span className="badge">{t('amenityMicrowave')}</span> : null}
                      {l.hasFreeParking ? <span className="badge">{t('amenityFreeParking')}</span> : null}
                      {l.hasSauna ? <span className="badge">{t('amenitySauna')}</span> : null}
                      {l.hasWifi ? <span className="badge">{t('amenityWifi')}</span> : null}
                    </div>
                    <div style={{ display: 'flex', gap: 8, marginTop: 6 }}>
                      <Link className="button secondary" href={`/listings/${l.slug}`}>
                        {t('openListing')}
                      </Link>
                      <button className="button secondary" onClick={() => setSelectedId(l.id)}>
                        {t('locateAddress')}
                      </button>
                    </div>
                  </div>
                </article>
              ))}
            </div>
          )}
        </div>
      </section>
    </main>
  );
}
