import React, { useEffect, useMemo, useState } from 'react';
import { InfoWindow, Map, Marker, useMap } from '@vis.gl/react-google-maps';
import { Globe, Loader2, MapPin, Navigation, Phone, Star } from 'lucide-react';
import { listBusinesses, listBusinessesForJobs } from '../lib/database';
import { cleanMapOptions } from '../lib/map-styles';
import type { Business } from '../types';
import type { AppUser } from '../../shared/types';
import { Alert, Badge, EmptyState } from './ui';

interface MapViewProps {
  user: AppUser;
  jobIds?: string[] | null;
}

export function MapView({ user, jobIds }: MapViewProps) {
  const map = useMap();
  const [businesses, setBusinesses] = useState<Business[]>([]);
  const [selected, setSelected] = useState<Business | null>(null);
  const [loading, setLoading] = useState(true);
  const [error, setError] = useState<string | null>(null);
  const selectedJobCount = jobIds?.length ?? 0;

  useEffect(() => {
    const loadBusinesses = async () => {
      setLoading(true);
      setError(null);

      try {
        const nextBusinesses = selectedJobCount > 0 ? await listBusinessesForJobs(user.id, jobIds ?? []) : await listBusinesses(user.id);
        setBusinesses(nextBusinesses);
      } catch (err) {
        setError(err instanceof Error ? err.message : 'Failed to load map leads.');
      } finally {
        setLoading(false);
      }
    };

    void loadBusinesses();
  }, [jobIds, selectedJobCount, user.id]);

  useEffect(() => {
    if (!selected) {
      return;
    }

    const stillExists = businesses.some((business) => business.id === selected.id);

    if (!stillExists) {
      setSelected(null);
    }
  }, [businesses, selected]);

  useEffect(() => {
    if (!map || businesses.length === 0) {
      return;
    }

    const bounds = new google.maps.LatLngBounds();
    let hasCoords = false;

    businesses.forEach((business) => {
      if (typeof business.latitude === 'number' && typeof business.longitude === 'number') {
        bounds.extend({ lat: business.latitude, lng: business.longitude });
        hasCoords = true;
      }
    });

    if (!hasCoords) {
      return;
    }

    map.fitBounds(bounds, 50);

    if (businesses.length === 1) {
      map.setZoom(15);
    }
  }, [businesses, map]);

  const center = useMemo(() => {
    const validCoords = businesses.filter(
      (business) => typeof business.latitude === 'number' && typeof business.longitude === 'number',
    );

    if (validCoords.length === 0) {
      return { lat: 37.42, lng: -122.08 };
    }

    const lat = validCoords.reduce((sum, business) => sum + (business.latitude ?? 0), 0) / validCoords.length;
    const lng = validCoords.reduce((sum, business) => sum + (business.longitude ?? 0), 0) / validCoords.length;

    return { lat, lng };
  }, [businesses]);

  if (loading) {
    return (
      <div className="flex flex-1 items-center justify-center bg-stone-50">
        <Loader2 className="h-8 w-8 animate-spin text-emerald-500" />
      </div>
    );
  }

  if (businesses.length === 0) {
    return (
      <div className="flex flex-1 items-center justify-center bg-stone-50 p-8">
        <div className="w-full max-w-lg">
          <EmptyState
            icon={MapPin}
            title="No leads to show on the map"
            description={selectedJobCount > 0
              ? 'The selected research jobs do not have saved map results yet. Try completed jobs or run the research again.'
              : 'No saved leads are available yet. Run a research job to populate the map.'}
          />
          {error ? <Alert variant="error" className="mt-4">{error}</Alert> : null}
        </div>
      </div>
    );
  }

  return (
    <div className="relative flex-1 bg-stone-100">
      {error && (
        <Alert variant="error" className="absolute left-4 right-4 top-4 z-10 shadow-lg lg:left-8 lg:right-auto lg:top-8 lg:max-w-md">{error}</Alert>
      )}

      <Map
        defaultCenter={center}
        defaultZoom={12}
        style={{ width: '100%', height: '100%' }}
        gestureHandling="greedy"
        {...cleanMapOptions}
      >
        {businesses.map((business) =>
          typeof business.latitude === 'number' && typeof business.longitude === 'number' ? (
            <Marker
              key={business.id}
              position={{ lat: business.latitude, lng: business.longitude }}
              onClick={() => setSelected(business)}
              icon={{
                path: google.maps.SymbolPath.CIRCLE,
                fillColor: selected?.id === business.id ? '#059669' : '#10b981',
                fillOpacity: 1,
                strokeColor: selected?.id === business.id ? '#064e3b' : '#065f46',
                strokeWeight: 2,
                scale: selected?.id === business.id ? 8 : 7,
              }}
            />
          ) : null,
        )}

        {selected && typeof selected.latitude === 'number' && typeof selected.longitude === 'number' && (
          <InfoWindow position={{ lat: selected.latitude, lng: selected.longitude }} onCloseClick={() => setSelected(null)}>
            <div className="max-w-[280px] space-y-3 p-2">
              <header>
                <h3 className="text-base font-semibold leading-tight text-stone-950">{selected.name}</h3>
                <div className="mt-1 flex items-center gap-1 text-xs text-stone-500">
                  <MapPin className="h-3 w-3" />
                  <span className="truncate">{selected.address}</span>
                </div>
              </header>

              <div className="flex items-center gap-3 border-y border-stone-100 py-2">
                <div className="flex items-center gap-1 text-sm font-semibold text-amber-600">
                  <Star className="h-4 w-4 fill-amber-500 text-amber-500" />
                  {selected.rating || 'N/A'}
                  <span className="text-xs font-normal text-stone-400">({selected.reviewCount || 0})</span>
                </div>
                <Badge>
                  {selected.category || 'Uncategorized'}
                </Badge>
              </div>

              <div className="flex items-center gap-2">
                {selected.website && (
                  <a
                    href={selected.website}
                    target="_blank"
                    rel="noopener"
                    className="inline-flex h-9 flex-1 items-center justify-center gap-2 rounded-xl bg-emerald-600 px-3 text-xs font-semibold text-white transition hover:bg-emerald-700"
                  >
                    <Globe className="h-3.5 w-3.5" />
                    Website
                  </a>
                )}
                {selected.phone && (
                  <a
                    href={`tel:${selected.phone}`}
                    className="inline-flex h-9 flex-1 items-center justify-center gap-2 rounded-xl border border-stone-200 bg-white px-3 text-xs font-semibold text-stone-700 transition hover:bg-stone-50"
                  >
                    <Phone className="h-3.5 w-3.5" />
                    Call
                  </a>
                )}
              </div>

              <a
                href={`https://www.google.com/maps/dir/?api=1&destination=${selected.latitude},${selected.longitude}`}
                target="_blank"
                rel="noopener"
                className="flex w-full items-center justify-center gap-2 pt-1 text-xs font-medium text-stone-500 hover:text-stone-900"
              >
                <Navigation className="h-3.5 w-3.5" />
                Get Directions
              </a>
            </div>
          </InfoWindow>
        )}
      </Map>

      <div className="absolute inset-x-4 bottom-4 z-10 rounded-2xl border border-white/20 bg-white/90 p-4 shadow-xl backdrop-blur-sm lg:inset-x-auto lg:bottom-8 lg:left-8 lg:max-w-xs">
        <h4 className="mb-2 text-sm font-semibold text-stone-950">Map Summary</h4>
        <div className="space-y-2">
          <div className="flex items-center justify-between text-xs">
            <span className="text-stone-500">Total Leads on Map</span>
            <span className="font-bold text-emerald-600">{businesses.length}</span>
          </div>
          <div className="flex items-center justify-between text-xs">
            <span className="text-stone-500">Selected Lead</span>
            <span className="max-w-[140px] truncate font-bold text-stone-900 lg:max-w-[120px]">{selected ? selected.name : 'None'}</span>
          </div>
          {selectedJobCount > 0 && (
            <div className="mt-2 border-t border-stone-200 pt-2">
              <p className="text-[10px] font-bold uppercase tracking-wider text-stone-400">Filtering by Selection</p>
              <p className="text-xs font-medium text-emerald-700 truncate">
                {selectedJobCount === 1 ? '1 selected research job' : `${selectedJobCount} selected research jobs`}
              </p>
            </div>
          )}
        </div>
      </div>
    </div>
  );
}
