import React, { useState, useEffect, useMemo } from 'react';
import '../App.css';
import SearchBar from '../components/SearchBar';
import MedicineResults from '../components/MedicineResults';
import PharmacyList from '../components/PharmacyList';
import PharmacyMap from '../components/PharmacyMap';
import HomeView from './HomeView';
import ScannerView from './ScannerView';
import { haversineKm, getUserPosition } from '../utils/geo';

function PublicView({
  currentUser,
  onLoginRequest,
  screen: screenProp,
  onScreenChange,
}) {
  // ponytail: uncontrolled by default (own state); controlled when App.jsx passes props
  // so BottomNav can drive the inner screen directly. No-op fallback breaks tests.
  const [internalScreen, setInternalScreen] = useState('home');
  const screen = screenProp ?? internalScreen;
  const setScreen = onScreenChange ?? setInternalScreen;

  const [searchQuery, setSearchQuery] = useState('');
  const [medicines, setMedicines] = useState([]);
  const [selectedMedicine, setSelectedMedicine] = useState(null);
  const [pharmacies, setPharmacies] = useState([]);
  const [loading, setLoading] = useState(false);
  const [userPosition, setUserPosition] = useState(null);
  const [positionSource, setPositionSource] = useState(null); // 'profile' | 'browser'
  const [sortByDistance, setSortByDistance] = useState(false);
  const [locating, setLocating] = useState(false);
  const [locationError, setLocationError] = useState('');

  useEffect(() => {
    const searchMedicines = async () => {
      if (searchQuery.trim().length < 2) {
        setMedicines([]);
        setSelectedMedicine(null);
        setPharmacies([]);
        return;
      }

      setLoading(true);
      try {
        const response = await fetch(`/api/medicines/search?q=${encodeURIComponent(searchQuery)}`);
        const data = await response.json();
        setMedicines(data);
      } catch (error) {
        console.error('Error searching medicines:', error);
      } finally {
        setLoading(false);
      }
    };

    const timeoutId = setTimeout(searchMedicines, 300);
    return () => clearTimeout(timeoutId);
  }, [searchQuery]);

  useEffect(() => {
    const fetchPharmacies = async () => {
      if (!selectedMedicine) {
        setPharmacies([]);
        return;
      }

      setLoading(true);
      try {
        const response = await fetch(`/api/medicines/${selectedMedicine.id}/pharmacies`);
        const data = await response.json();
        setPharmacies(data);
      } catch (error) {
        console.error('Error fetching pharmacies:', error);
      } finally {
        setLoading(false);
      }
    };

    fetchPharmacies();
  }, [selectedMedicine]);

  const savedLat = currentUser?.latitude;
  const savedLon = currentUser?.longitude;
  const hasSavedCoords = savedLat != null && savedLon != null;

  const handleSortByDistance = async () => {
    if (sortByDistance) {
      setSortByDistance(false);
      return;
    }
    setLocationError('');
    if (hasSavedCoords) {
      setUserPosition({ lat: savedLat, lon: savedLon });
      setPositionSource('profile');
      setSortByDistance(true);
      // Save to search history
      try {
        fetch('/api/search-history', {
          method: 'POST',
          headers: { 'Content-Type': 'application/json' },
          credentials: 'include',
          body: JSON.stringify({
            address: currentUser?.address,
            latitude: savedLat,
            longitude: savedLon,
          }),
        });
      } catch (err) {
        console.error('Error saving search history:', err);
      }
      return;
    }
    if (userPosition) {
      setSortByDistance(true);
      return;
    }
    setLocating(true);
    try {
      const pos = await getUserPosition();
      setUserPosition(pos);
      setPositionSource('browser');
      setSortByDistance(true);
      // Save to search history
      try {
        fetch('/api/search-history', {
          method: 'POST',
          headers: { 'Content-Type': 'application/json' },
          credentials: 'include',
          body: JSON.stringify({
            address: 'Ubicación actual',
            latitude: pos.lat,
            longitude: pos.lon,
          }),
        });
      } catch (err) {
        console.error('Error saving search history:', err);
      }
    } catch (err) {
      console.error('[location] error', err);
      let msg;
      if (err && typeof err.code === 'number') {
        if (err.code === 1) msg = 'Permiso de ubicación denegado — actívalo en la configuración del navegador';
        else if (err.code === 2) msg = 'Ubicación no disponible — comprueba los servicios de ubicación/WiFi';
        else if (err.code === 3) msg = 'La solicitud de ubicación expiró — inténtalo de nuevo';
        else msg = `Error de geolocalización (código ${err.code})`;
      } else {
        msg = err && err.message ? err.message : 'No se pudo obtener tu ubicación';
      }
      setLocationError(msg);
    } finally {
      setLocating(false);
    }
  };

  const displayedPharmacies = useMemo(() => {
    if (!sortByDistance || !userPosition) return pharmacies;
    return [...pharmacies].sort((a, b) => {
      if (a.latitude == null || a.longitude == null) return 1;
      if (b.latitude == null || b.longitude == null) return -1;
      return (
        haversineKm(userPosition.lat, userPosition.lon, a.latitude, a.longitude) -
        haversineKm(userPosition.lat, userPosition.lon, b.latitude, b.longitude)
      );
    });
  }, [pharmacies, sortByDistance, userPosition]);

  /* ── Scanner → Search handoff ──────────────────────────── */
  function handleScanSelectMedicine(medicineName) {
    setSearchQuery(medicineName);
    setSelectedMedicine(null);
    setPharmacies([]);
    setScreen('search');
  }

  /* ── Screens ─────────────────────────────────────────────── */
  if (screen === 'home') {
    return (
      <HomeView
        onScanClick={() => setScreen('scan')}
        onSearchClick={() => setScreen('search')}
      />
    );
  }

  if (screen === 'scan') {
    return (
      <ScannerView
        onClose={() => setScreen('home')}
        onSelectMedicine={handleScanSelectMedicine}
      />
    );
  }

  // screen === 'search'
  return (
    <>
      <header className="app-header">
        <button
          className="back-to-home-btn"
          onClick={() => {
            setSearchQuery('');
            setSelectedMedicine(null);
            setPharmacies([]);
            setScreen('home');
          }}
          aria-label="Volver al inicio"
        >
          ← Inicio
        </button>
        <h1>💊 FarmaClic</h1>
        <p>Encuentra tu medicamento en farmacias cercanas</p>
      </header>

      <main className="app-main">
        <SearchBar
          value={searchQuery}
          onChange={setSearchQuery}
          placeholder="Buscar un medicamento..."
        />

        {loading && <div className="loading">Buscando...</div>}

        {searchQuery && !selectedMedicine && (
          <MedicineResults
            medicines={medicines}
            onSelect={setSelectedMedicine}
            query={searchQuery}
            currentUser={currentUser}
            onLoginRequest={onLoginRequest}
          />
        )}

        {selectedMedicine && (
          <div className="selected-medicine-section">
            <div className="medicine-info">
              <h2>{selectedMedicine.name}</h2>
              <div className="medicine-details">
                <span><strong>Principio Activo:</strong> {selectedMedicine.active_ingredient}</span>
                <span><strong>Dosis:</strong> {selectedMedicine.dosage}</span>
                <span><strong>Forma:</strong> {selectedMedicine.form}</span>
              </div>
              <button
                className="back-button"
                onClick={() => {
                  setSelectedMedicine(null);
                  setPharmacies([]);
                }}
              >
                ← Volver a búsqueda
              </button>
            </div>

            {pharmacies.length > 0 && (
              <div className="pharmacy-controls">
                <button
                  className={`sort-distance-button ${sortByDistance ? 'active' : ''}`}
                  onClick={handleSortByDistance}
                  disabled={locating}
                >
                  {locating
                    ? '📍 Localizando…'
                    : sortByDistance
                      ? '📍 Ordenado por distancia · Reset'
                      : hasSavedCoords
                        ? '📍 Ordenar por ubicación guardada'
                        : '📍 Ordenar por distancia'}
                </button>
                {sortByDistance && positionSource === 'profile' && (
                  <span className="location-source">Usando tu dirección guardada</span>
                )}
                {locationError && (
                  <span className="location-error">{locationError}</span>
                )}
              </div>
            )}

            <PharmacyMap pharmacies={displayedPharmacies} />
            <PharmacyList
              pharmacies={displayedPharmacies}
              loading={loading}
              userPosition={sortByDistance ? userPosition : null}
              medicine={selectedMedicine}
              currentUser={currentUser}
              onLoginRequest={onLoginRequest}
            />
          </div>
        )}
      </main>
    </>
  );
}

export default PublicView;
