import React, { useEffect, useState, useMemo } from 'react';
import { View, Text, ScrollView, StyleSheet, TouchableOpacity, Linking } from 'react-native';
import { useLocalSearchParams, useRouter } from 'expo-router';
import { Ionicons } from '@expo/vector-icons';
import * as Location from 'expo-location';
import { getMedicine, getMedicinePharmacies } from '../../services/medicines';
import { subscribeToMedicine, unsubscribeFromMedicine } from '../../services/notifications';
import { useAuth } from '../../hooks/useAuth';
import { StockBadge } from '../../components/StockBadge';
import { LoadingSpinner } from '../../components/LoadingSpinner';
import { useThemeContext } from '../../components/ThemeProvider';
import { spacing, borderRadius } from '../../constants/theme';
import { Medicine, PharmacyMedicine } from '../../types';

function haversineKm(lat1: number, lon1: number, lat2: number, lon2: number): number {
  const R = 6371;
  const dLat = ((lat2 - lat1) * Math.PI) / 180;
  const dLon = ((lon2 - lon1) * Math.PI) / 180;
  const a =
    Math.sin(dLat / 2) ** 2 +
    Math.cos((lat1 * Math.PI) / 180) *
      Math.cos((lat2 * Math.PI) / 180) *
      Math.sin(dLon / 2) ** 2;
  return R * 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1 - a));
}

function formatDistance(km: number): string {
  if (km < 1) return `${Math.round(km * 1000)} m`;
  if (km < 10) return `${km.toFixed(1)} km`;
  return `${Math.round(km)} km`;
}

function getPharmacyLat(p: PharmacyMedicine): number | null {
  return p.latitude ?? p.pharmacy?.latitude ?? null;
}

function getPharmacyLon(p: PharmacyMedicine): number | null {
  return p.longitude ?? p.pharmacy?.longitude ?? null;
}

export default function MedicineDetailScreen() {
  const { id } = useLocalSearchParams<{ id: string }>();
  const router = useRouter();
  const { colors } = useThemeContext();
  const { isAuthenticated } = useAuth();
  const [medicine, setMedicine] = useState<Medicine | null>(null);
  const [pharmacies, setPharmacies] = useState<PharmacyMedicine[]>([]);
  const [isLoading, setIsLoading] = useState(true);
  const [sortByDistance, setSortByDistance] = useState(false);
  const [userPosition, setUserPosition] = useState<{ lat: number; lon: number } | null>(null);
  const [locating, setLocating] = useState(false);
  const [locationError, setLocationError] = useState<string | null>(null);
  const [isSubscribed, setIsSubscribed] = useState(false);
  const [togglingSub, setTogglingSub] = useState(false);

  useEffect(() => {
    if (!id) return;

    const fetchMedicine = async () => {
      try {
        const [medData, pharmData] = await Promise.all([
          getMedicine(id),
          getMedicinePharmacies(id),
        ]);
        setMedicine(medData);
        setPharmacies(pharmData);
      } catch (error) {
        console.error('Error fetching medicine:', error);
      } finally {
        setIsLoading(false);
      }
    };

    fetchMedicine();
  }, [id]);

  const handleSortByDistance = async () => {
    if (sortByDistance) {
      setSortByDistance(false);
      return;
    }

    setLocating(true);
    setLocationError(null);

    try {
      const { status } = await Location.requestForegroundPermissionsAsync();
      if (status !== 'granted') {
        setLocationError('Permiso de ubicación denegado');
        setLocating(false);
        return;
      }

      const pos = await Location.getCurrentPositionAsync({ accuracy: Location.Accuracy.Balanced });
      setUserPosition({ lat: pos.coords.latitude, lon: pos.coords.longitude });
      setSortByDistance(true);
    } catch {
      setLocationError('No se pudo obtener tu ubicación');
    } finally {
      setLocating(false);
    }
  };

  const handleToggleSubscription = async () => {
    if (!isAuthenticated || !id) return;
    setTogglingSub(true);
    try {
      if (isSubscribed) {
        await unsubscribeFromMedicine(id as string);
        setIsSubscribed(false);
      } else {
        await subscribeToMedicine(id as string, medicine?.name || null);
        setIsSubscribed(true);
      }
    } catch {
      // silently fail
    } finally {
      setTogglingSub(false);
    }
  };

  const sortedPharmacies = useMemo(() => {
    if (!sortByDistance || !userPosition) return pharmacies;

    return [...pharmacies]
      .map((p) => {
        const lat = getPharmacyLat(p);
        const lon = getPharmacyLon(p);
        const distance =
          lat != null && lon != null
            ? haversineKm(userPosition.lat, userPosition.lon, lat, lon)
            : Infinity;
        return { ...p, _distance: distance };
      })
      .sort((a, b) => a._distance - b._distance);
  }, [pharmacies, sortByDistance, userPosition]);

  const locatedPharmacies = useMemo(
    () =>
      sortedPharmacies.filter(
        (p) => getPharmacyLat(p) != null && getPharmacyLon(p) != null
      ),
    [sortedPharmacies]
  );

  const mapCenter = useMemo(() => {
    if (locatedPharmacies.length === 0) return { latitude: 40.4168, longitude: -3.7038 };
    const lat = locatedPharmacies.reduce((s, p) => s + (getPharmacyLat(p) || 0), 0) / locatedPharmacies.length;
    const lon = locatedPharmacies.reduce((s, p) => s + (getPharmacyLon(p) || 0), 0) / locatedPharmacies.length;
    return { latitude: lat, longitude: lon };
  }, [locatedPharmacies]);

  const handleDirections = (latitude: number, longitude: number) => {
    const url = `https://www.google.com/maps/dir/?api=1&destination=${latitude},${longitude}`;
    Linking.openURL(url);
  };

  if (isLoading) {
    return <LoadingSpinner message="Cargando medicamento..." />;
  }

  if (!medicine) {
    return (
      <View style={[styles.errorContainer, { backgroundColor: colors.background }]}>
        <Text style={[styles.errorText, { color: colors.textSecondary }]}>Medicamento no encontrado</Text>
      </View>
    );
  }

  return (
    <ScrollView style={[styles.container, { backgroundColor: colors.background }]}>
      <View style={[styles.header, { backgroundColor: colors.card }]}>
        <Text style={[styles.name, { color: colors.text }]}>{medicine.name}</Text>
        <View style={styles.headerRight}>
          {medicine.stock != null && <StockBadge stock={medicine.stock} />}
          {isAuthenticated && (
            <TouchableOpacity
              style={[styles.bellButton, { backgroundColor: isSubscribed ? colors.primary : colors.surfaceVariant }]}
              onPress={handleToggleSubscription}
              disabled={togglingSub}
            >
              <Ionicons
                name={isSubscribed ? 'notifications' : 'notifications-outline'}
                size={20}
                color={isSubscribed ? '#fff' : colors.textSecondary}
              />
            </TouchableOpacity>
          )}
        </View>
      </View>

      <View style={[styles.infoSection, { backgroundColor: colors.card }]}>
        <InfoRow label="Principio activo" value={medicine.active_ingredient} colors={colors} />
        <InfoRow label="Laboratorio" value={medicine.laboratory} colors={colors} />
        <InfoRow label="Forma farmacéutica" value={medicine.form} colors={colors} />
        <InfoRow label="Dosificación" value={medicine.dosage} colors={colors} />
        <InfoRow
          label="Precio"
          value={medicine.precio != null ? `${medicine.precio.toFixed(2)} €` : 'No disponible'}
          colors={colors}
        />
        <InfoRow label="Registro" value={medicine.nregistro} colors={colors} />
      </View>

      {locatedPharmacies.length > 0 && (
        <View style={[styles.mapContainer, { backgroundColor: colors.surfaceVariant }]}>
          <Ionicons name="map-outline" size={48} color={colors.textSecondary} />
          <Text style={[styles.mapPlaceholder, { color: colors.textSecondary }]}>
            Mapa próximamente…
          </Text>
        </View>
      )}

      <View style={styles.pharmaciesSection}>
        <View style={styles.pharmaciesHeader}>
          <Text style={[styles.sectionTitle, { color: colors.text }]}>
            Farmacias ({sortedPharmacies.length})
          </Text>
          <TouchableOpacity
            style={[styles.sortButton, sortByDistance && styles.sortButtonActive, { backgroundColor: sortByDistance ? colors.primary : colors.primaryContainer, borderColor: colors.primary }]}
            onPress={handleSortByDistance}
            disabled={locating}
          >
            <Ionicons name="location" size={16} color={sortByDistance ? '#fff' : colors.primary} />
            <Text style={[styles.sortButtonText, sortByDistance && styles.sortButtonTextActive, { color: sortByDistance ? '#fff' : colors.primary }]}>
              {locating
                ? 'Localizando…'
                : sortByDistance
                  ? 'Distancia · Reset'
                  : 'Ordenar por distancia'}
            </Text>
          </TouchableOpacity>
        </View>

        {locationError && (
          <View style={[styles.locationErrorContainer, { backgroundColor: colors.dangerContainer }]}>
            <Text style={[styles.locationErrorText, { color: colors.danger }]}>{locationError}</Text>
            <TouchableOpacity onPress={handleSortByDistance}>
              <Text style={[styles.retryText, { color: colors.primary }]}>Reintentar</Text>
            </TouchableOpacity>
          </View>
        )}

        {sortedPharmacies.length === 0 ? (
          <Text style={[styles.noPharmacies, { color: colors.textSecondary }]}>No hay farmacias disponibles</Text>
        ) : (
          sortedPharmacies.map((pharm) => {
            const lat = getPharmacyLat(pharm);
            const lon = getPharmacyLon(pharm);
            const distanceKm =
              sortByDistance && userPosition && lat != null && lon != null
                ? haversineKm(userPosition.lat, userPosition.lon, lat, lon)
                : null;

            return (
              <View key={pharm.id} style={[styles.pharmacyCard, { backgroundColor: colors.card }]}>
                <TouchableOpacity
                  style={styles.pharmacyCardContent}
                  onPress={() => router.push(`/pharmacy/${pharm.pharmacy_id || pharm.id}`)}
                >
                  <View style={styles.pharmacyInfo}>
                    <View style={styles.pharmacyNameRow}>
                      <Text style={[styles.pharmacyName, { color: colors.text }]}>{pharm.pharmacy?.name || pharm.name}</Text>
                      {distanceKm != null && (
                        <Text style={[styles.pharmacyDistance, { color: colors.primary, backgroundColor: colors.primaryContainer }]}>{formatDistance(distanceKm)}</Text>
                      )}
                    </View>
                    <Text style={[styles.pharmacyAddress, { color: colors.textSecondary }]}>{pharm.pharmacy?.address || pharm.address}</Text>
                  </View>
                  <View style={styles.pharmacyStock}>
                    {pharm.price != null ? (
                      <Text style={[styles.price, { color: colors.primary }]}>{pharm.price.toFixed(2)} €</Text>
                    ) : (
                      <Text style={[styles.price, { color: colors.primary }]}>Consultar precio</Text>
                    )}
                    {pharm.stock > 0 && (
                      <Text style={[styles.stock, { color: colors.textSecondary }]}>Stock: {pharm.stock}</Text>
                    )}
                  </View>
                </TouchableOpacity>
                {lat != null && lon != null && (
                  <TouchableOpacity
                    style={[styles.directionsButton, { borderTopColor: colors.border }]}
                    onPress={() => handleDirections(lat, lon)}
                  >
                    <Ionicons name="navigate" size={16} color={colors.primary} />
                    <Text style={[styles.directionsText, { color: colors.primary }]}>Cómo llegar</Text>
                  </TouchableOpacity>
                )}
              </View>
            );
          })
        )}
      </View>
    </ScrollView>
  );
}

function InfoRow({ label, value, colors }: { label: string; value: string; colors: any }) {
  return (
    <View style={[styles.infoRow, { borderBottomColor: colors.border }]}>
      <Text style={[styles.infoLabel, { color: colors.textSecondary }]}>{label}</Text>
      <Text style={[styles.infoValue, { color: colors.text }]}>{value}</Text>
    </View>
  );
}

const styles = StyleSheet.create({
  container: {
    flex: 1,
  },
  header: {
    flexDirection: 'row',
    justifyContent: 'space-between',
    alignItems: 'flex-start',
    padding: spacing.lg,
  },
  headerRight: {
    flexDirection: 'row',
    alignItems: 'center',
    gap: spacing.sm,
  },
  name: {
    flex: 1,
    fontSize: 22,
    fontWeight: 'bold',
    marginRight: spacing.sm,
  },
  bellButton: {
    width: 36,
    height: 36,
    borderRadius: 18,
    alignItems: 'center',
    justifyContent: 'center',
  },
  infoSection: {
    marginTop: spacing.sm,
    padding: spacing.lg,
  },
  infoRow: {
    flexDirection: 'row',
    justifyContent: 'space-between',
    paddingVertical: spacing.sm,
    borderBottomWidth: 1,
  },
  infoLabel: {
    fontSize: 13,
    flexShrink: 0,
    marginRight: spacing.sm,
  },
  infoValue: {
    fontSize: 13,
    fontWeight: '500',
    flex: 1,
    textAlign: 'right',
  },
  mapContainer: {
    marginTop: spacing.sm,
    marginHorizontal: spacing.lg,
    height: 200,
    borderRadius: borderRadius.lg,
    overflow: 'hidden',
    alignItems: 'center',
    justifyContent: 'center',
    gap: spacing.sm,
  },
  mapPlaceholder: {
    fontSize: 14,
    fontWeight: '500',
  },
  pharmaciesSection: {
    marginTop: spacing.sm,
    padding: spacing.lg,
  },
  pharmaciesHeader: {
    flexDirection: 'row',
    justifyContent: 'space-between',
    alignItems: 'center',
    marginBottom: spacing.md,
  },
  sectionTitle: {
    fontSize: 18,
    fontWeight: '600',
  },
  sortButton: {
    flexDirection: 'row',
    alignItems: 'center',
    gap: spacing.xs,
    paddingHorizontal: spacing.sm + 4,
    paddingVertical: spacing.xs + 2,
    borderRadius: borderRadius.full,
    borderWidth: 1,
  },
  sortButtonActive: {},
  sortButtonText: {
    fontSize: 13,
    fontWeight: '600',
  },
  sortButtonTextActive: {},
  locationErrorContainer: {
    flexDirection: 'row',
    alignItems: 'center',
    gap: spacing.sm,
    padding: spacing.sm,
    marginBottom: spacing.sm,
    borderRadius: borderRadius.md,
  },
  locationErrorText: {
    flex: 1,
    fontSize: 13,
  },
  retryText: {
    fontSize: 13,
    fontWeight: '600',
  },
  noPharmacies: {
    textAlign: 'center',
    padding: spacing.xl,
  },
  pharmacyCard: {
    borderRadius: borderRadius.lg,
    marginBottom: spacing.sm,
    overflow: 'hidden',
    shadowColor: '#000',
    shadowOffset: { width: 0, height: 2 },
    shadowOpacity: 0.06,
    shadowRadius: 8,
    elevation: 2,
  },
  pharmacyCardContent: {
    flexDirection: 'row',
    justifyContent: 'space-between',
    padding: spacing.md,
  },
  pharmacyInfo: {
    flex: 1,
  },
  pharmacyNameRow: {
    flexDirection: 'row',
    justifyContent: 'space-between',
    alignItems: 'center',
  },
  pharmacyName: {
    flex: 1,
    fontSize: 16,
    fontWeight: '600',
    marginRight: spacing.sm,
  },
  pharmacyDistance: {
    fontSize: 12,
    fontWeight: '600',
    paddingHorizontal: spacing.sm,
    paddingVertical: 2,
    borderRadius: borderRadius.full,
    overflow: 'hidden',
  },
  pharmacyAddress: {
    fontSize: 14,
    marginTop: spacing.xs,
  },
  pharmacyStock: {
    alignItems: 'flex-end',
  },
  price: {
    fontSize: 16,
    fontWeight: '600',
  },
  stock: {
    fontSize: 12,
    marginTop: spacing.xs,
  },
  directionsButton: {
    flexDirection: 'row',
    alignItems: 'center',
    justifyContent: 'center',
    gap: spacing.xs,
    paddingVertical: spacing.sm,
    borderTopWidth: 1,
  },
  directionsText: {
    fontSize: 14,
    fontWeight: '600',
  },
  errorContainer: {
    flex: 1,
    justifyContent: 'center',
    alignItems: 'center',
  },
  errorText: {
    fontSize: 16,
  },
});
