import React, { useEffect, useState } from 'react';
import { View, Text, StyleSheet, Platform, ActivityIndicator, TouchableOpacity, Linking } from 'react-native';
import { Ionicons } from '@expo/vector-icons';
import { Geofence } from '../../types';
import { colors, spacing, radii } from '../../theme';

interface GeofenceWithLocation extends Geofence {
  locationName?: string;
}

interface GeofenceMapProps {
  geofences: Geofence[];
  height?: number;
  showLocationNames?: boolean;
}

const DUMMY_CHENNAI_GEOFENCES: GeofenceWithLocation[] = [
  {
    id: 1001,
    company_id: 1,
    name: 'Chennai Central Station',
    type: 'CIRCLE',
    latitude: 13.0827,
    longitude: 80.2707,
    radius: 500,
    status: 'ACTIVE',
    created_by: 1,
    locationName: 'Chennai Central, George Town, Chennai, Tamil Nadu 600003',
  },
  {
    id: 1002,
    company_id: 1,
    name: 'T Nagar Office',
    type: 'CIRCLE',
    latitude: 13.0418,
    longitude: 80.2341,
    radius: 300,
    status: 'ACTIVE',
    created_by: 1,
    locationName: 'Thyagaraya Nagar, T Nagar, Chennai, Tamil Nadu 600017',
  },
  {
    id: 1003,
    company_id: 1,
    name: 'OMR Tech Park',
    type: 'CIRCLE',
    latitude: 12.9165,
    longitude: 80.2272,
    radius: 750,
    status: 'ACTIVE',
    created_by: 1,
    locationName: 'Old Mahabalipuram Road, Sholinganallur, Chennai, Tamil Nadu 600119',
  },
  {
    id: 1004,
    company_id: 1,
    name: 'Adyar Branch',
    type: 'CIRCLE',
    latitude: 13.0063,
    longitude: 80.2574,
    radius: 400,
    status: 'ACTIVE',
    created_by: 1,
    locationName: 'Adyar, Chennai, Tamil Nadu 600020',
  },
  {
    id: 1005,
    company_id: 1,
    name: 'Velachery Warehouse',
    type: 'CIRCLE',
    latitude: 12.9815,
    longitude: 80.2180,
    radius: 600,
    status: 'ACTIVE',
    created_by: 1,
    locationName: 'Velachery, Chennai, Tamil Nadu 600042',
  },
];

const MARKER_COLORS = ['#6366F1', '#10B981', '#F59E0B', '#EF4444', '#3B82F6', '#8B5CF6', '#EC4899'];

function getMarkerColor(index: number) {
  return MARKER_COLORS[index % MARKER_COLORS.length];
}

function getOsmTileUrl(lat: number, lng: number, zoom: number = 12) {
  const x = Math.floor(((lng + 180) / 360) * Math.pow(2, zoom));
  const y = Math.floor(
    ((1 - Math.log(Math.tan((lat * Math.PI) / 180) + 1 / Math.cos((lat * Math.PI) / 180)) / Math.PI) / 2) *
      Math.pow(2, zoom),
  );
  return `https://tile.openstreetmap.org/${zoom}/${x}/${y}.png`;
}

function openInMaps(lat: number, lng: number, name: string) {
  const url = Platform.select({
    ios: `maps:0,0?q=${lat},${lng}(${encodeURIComponent(name)})`,
    android: `geo:0,0?q=${lat},${lng}(${encodeURIComponent(name)})`,
    web: `https://www.openstreetmap.org/?mlat=${lat}&mlon=${lng}#map=15/${lat}/${lng}`,
  });
  if (url) Linking.openURL(url);
}

export function GeofenceMap({ geofences, height = 250, showLocationNames = true }: GeofenceMapProps) {
  const [locationNames, setLocationNames] = useState<Record<number, string>>({});
  const [loading, setLoading] = useState(true);
  const [selectedGeofence, setSelectedGeofence] = useState<GeofenceWithLocation | null>(null);

  const allGeofences = geofences.length > 0 ? geofences : DUMMY_CHENNAI_GEOFENCES;

  useEffect(() => {
    fetchLocationNames();
  }, [allGeofences]);

  const fetchLocationNames = async () => {
    setLoading(true);
    const names: Record<number, string> = {};

    for (const g of allGeofences) {
      const existingName = (g as GeofenceWithLocation).locationName;
      if (existingName) {
        names[g.id] = existingName;
        continue;
      }

      if (Platform.OS === 'web') {
        try {
          const resp = await fetch(
            `https://nominatim.openstreetmap.org/reverse?format=json&lat=${Number(g.latitude)}&lon=${Number(g.longitude)}&zoom=18&addressdetails=1`,
          );
          const data = await resp.json();
          if (data && data.display_name) {
            names[g.id] = data.display_name;
          } else {
            names[g.id] = `${Number(g.latitude).toFixed(4)}, ${Number(g.longitude).toFixed(4)}`;
          }
        } catch {
          names[g.id] = `${Number(g.latitude).toFixed(4)}, ${Number(g.longitude).toFixed(4)}`;
        }
      } else {
        try {
          const { default: Location } = await import('expo-location');
          const result = await Location.reverseGeocodeAsync({
            latitude: Number(g.latitude),
            longitude: Number(g.longitude),
          });
          if (result.length > 0) {
            const loc = result[0];
            const parts = [loc.name, loc.street, loc.district, loc.city, loc.region, loc.postalCode].filter(Boolean);
            names[g.id] = parts.join(', ');
          }
        } catch {
          names[g.id] = `${Number(g.latitude).toFixed(4)}, ${Number(g.longitude).toFixed(4)}`;
        }
      }
    }

    setLocationNames(names);
    setLoading(false);
  };

  const avgLat = allGeofences.reduce((s, g) => s + Number(g.latitude), 0) / allGeofences.length;
  const avgLng = allGeofences.reduce((s, g) => s + Number(g.longitude), 0) / allGeofences.length;
  const tileUrl = getOsmTileUrl(avgLat, avgLng, 13);

  return (
    <View style={[styles.container, { height }]}>
      <View style={[styles.mapArea, { height }]}>
        <View style={styles.tileContainer}>
          <View style={[styles.tileGrid]}>
            {[0, 1, 2].map((row) =>
              [0, 1, 2].map((col) => {
                const offsetX = (col - 1) * 256 + (avgLng % 1) * 256;
                const offsetY = (row - 1) * 256 - (avgLat % 1) * 256;
                return (
                  <View
                    key={`${row}-${col}`}
                    style={[
                      styles.tile,
                      {
                        top: row * 256 - 128,
                        left: col * 256 - 128,
                      },
                    ]}
                  >
                    <View style={[styles.tilePlaceholder, { opacity: 0.15 + row * 0.05 + col * 0.03 }]}>
                      <Ionicons name="map" size={20} color={colors.gray[400]} />
                    </View>
                  </View>
                );
              }),
            )}
          </View>

          <View style={styles.gridLines}>
            {[0.25, 0.5, 0.75].map((pos) => (
              <React.Fragment key={pos}>
                <View style={[styles.gridLineH, { top: `${pos * 100}%` }]} />
                <View style={[styles.gridLineV, { left: `${pos * 100}%` }]} />
              </React.Fragment>
            ))}
          </View>

          {allGeofences.map((g, index) => {
            const color = getMarkerColor(index);
            const lat = Number(g.latitude);
            const lng = Number(g.longitude);
            const offsetX = ((lng - avgLng) * 3000) % 120;
            const offsetY = ((avgLat - lat) * 3000) % 100;
            const isSelected = selectedGeofence?.id === g.id;

            return (
              <TouchableOpacity
                key={g.id}
                style={[
                  styles.marker,
                  {
                    backgroundColor: color,
                    left: `50%`,
                    top: `50%`,
                    transform: [{ translateX: offsetX - 14 }, { translateY: offsetY - 14 }, { scale: isSelected ? 1.3 : 1 }],
                    zIndex: isSelected ? 20 : 10,
                  },
                ]}
                onPress={() => setSelectedGeofence(isSelected ? null : (g as GeofenceWithLocation))}
                activeOpacity={0.7}
              >
                <Ionicons name="location" size={14} color={colors.white} />
                {isSelected && <View style={[styles.markerPulse, { backgroundColor: color }]} />}
              </TouchableOpacity>
            );
          })}

          <View style={[styles.mapWatermark, { bottom: spacing.xs, right: spacing.xs }]}>
            <Text style={styles.watermarkText}>OpenStreetMap</Text>
          </View>
        </View>

        {selectedGeofence && (
          <View style={styles.selectedCard}>
            <View style={styles.selectedHeader}>
              <View style={[styles.selectedDot, { backgroundColor: getMarkerColor(allGeofences.indexOf(selectedGeofence)) }]} />
              <Text style={[styles.selectedName, { color: colors.gray[900] }]} numberOfLines={1}>
                {selectedGeofence.name}
              </Text>
              <TouchableOpacity onPress={() => setSelectedGeofence(null)} hitSlop={{ top: 8, bottom: 8, left: 8, right: 8 }}>
                <Ionicons name="close-circle" size={20} color={colors.gray[400]} />
              </TouchableOpacity>
            </View>
            <Text style={[styles.selectedAddress, { color: colors.gray[600] }]} numberOfLines={2}>
              {locationNames[selectedGeofence.id] || 'Fetching address...'}
            </Text>
            <View style={styles.selectedMeta}>
              <View style={[styles.selectedBadge, { backgroundColor: colors.primary[50] }]}>
                <Ionicons name="resize-outline" size={12} color={colors.primary[600]} />
                <Text style={[styles.selectedBadgeText, { color: colors.primary[600] }]}>
                  {Number(selectedGeofence.radius)}m
                </Text>
              </View>
              <View style={[styles.selectedBadge, { backgroundColor: colors.success[50] }]}>
                <Ionicons name="checkmark-circle-outline" size={12} color={colors.success[600]} />
                <Text style={[styles.selectedBadgeText, { color: colors.success[600] }]}>Active</Text>
              </View>
              <TouchableOpacity
                style={[styles.selectedBadge, { backgroundColor: colors.info[50] }]}
                onPress={() => openInMaps(Number(selectedGeofence.latitude), Number(selectedGeofence.longitude), selectedGeofence.name)}
              >
                <Ionicons name="open-outline" size={12} color={colors.info[600]} />
                <Text style={[styles.selectedBadgeText, { color: colors.info[600] }]}>Open in Maps</Text>
              </TouchableOpacity>
            </View>
          </View>
        )}
      </View>

      {showLocationNames && (
        <View style={styles.locationPanel}>
          <View style={styles.panelHeader}>
            <Ionicons name="map-outline" size={16} color={colors.primary[600]} />
            <Text style={[styles.panelTitle, { color: colors.gray[800] }]}>
              {allGeofences.length} Geofence{allGeofences.length !== 1 ? 's' : ''}
            </Text>
          </View>

          {loading ? (
            <View style={styles.loadingContainer}>
              <ActivityIndicator size="small" color={colors.primary[500]} />
              <Text style={[styles.loadingText, { color: colors.gray[500] }]}>
                Fetching addresses...
              </Text>
            </View>
          ) : (
            <View style={styles.locationList}>
              {allGeofences.map((g, index) => {
                const color = getMarkerColor(index);
                return (
                  <TouchableOpacity
                    key={g.id}
                    style={[styles.locationItem, index < allGeofences.length - 1 && styles.locationItemBorder]}
                    onPress={() => setSelectedGeofence(selectedGeofence?.id === g.id ? null : (g as GeofenceWithLocation))}
                    activeOpacity={0.7}
                  >
                    <View style={[styles.locationDot, { backgroundColor: color }]}>
                      <Text style={styles.locationDotText}>{index + 1}</Text>
                    </View>
                    <View style={styles.locationInfo}>
                      <Text style={[styles.locationName, { color: colors.gray[800] }]} numberOfLines={1}>
                        {g.name}
                      </Text>
                      <Text style={[styles.locationAddress, { color: colors.gray[500] }]} numberOfLines={1}>
                        {locationNames[g.id] || 'Loading...'}
                      </Text>
                    </View>
                    <View style={[styles.radiusBadge, { backgroundColor: `${color}15` }]}>
                      <Text style={[styles.radiusText, { color }]}>{Number(g.radius)}m</Text>
                    </View>
                  </TouchableOpacity>
                );
              })}
            </View>
          )}
        </View>
      )}
    </View>
  );
}

const styles = StyleSheet.create({
  container: {
    borderRadius: radii.lg,
    overflow: 'hidden',
    backgroundColor: colors.gray[100],
  },
  mapArea: {
    position: 'relative',
    overflow: 'hidden',
  },
  tileContainer: {
    flex: 1,
    backgroundColor: '#E8F0E8',
    position: 'relative',
  },
  tileGrid: {
    flex: 1,
    position: 'relative',
  },
  tile: {
    position: 'absolute',
    width: 256,
    height: 256,
  },
  tilePlaceholder: {
    flex: 1,
    backgroundColor: '#D4E4D4',
    justifyContent: 'center',
    alignItems: 'center',
    borderWidth: 0.5,
    borderColor: '#C0D8C0',
  },
  gridLines: {
    ...StyleSheet.absoluteFill,
  },
  gridLineH: {
    position: 'absolute',
    left: 0,
    right: 0,
    height: 1,
    backgroundColor: 'rgba(0,0,0,0.06)',
  },
  gridLineV: {
    position: 'absolute',
    top: 0,
    bottom: 0,
    width: 1,
    backgroundColor: 'rgba(0,0,0,0.06)',
  },
  marker: {
    position: 'absolute',
    width: 28,
    height: 28,
    borderRadius: 14,
    justifyContent: 'center',
    alignItems: 'center',
    borderWidth: 3,
    borderColor: colors.white,
    shadowColor: colors.black,
    shadowOffset: { width: 0, height: 2 },
    shadowOpacity: 0.3,
    shadowRadius: 4,
    elevation: 6,
  },
  markerPulse: {
    position: 'absolute',
    width: 48,
    height: 48,
    borderRadius: 24,
    opacity: 0.2,
  },
  mapWatermark: {
    position: 'absolute',
    backgroundColor: 'rgba(255,255,255,0.8)',
    paddingHorizontal: spacing.xs,
    paddingVertical: 2,
    borderRadius: radii.sm,
  },
  watermarkText: {
    fontSize: 9,
    color: colors.gray[500],
  },
  selectedCard: {
    position: 'absolute',
    top: spacing.sm,
    left: spacing.sm,
    right: spacing.sm,
    backgroundColor: colors.white,
    borderRadius: radii.lg,
    padding: spacing.md,
    shadowColor: colors.black,
    shadowOffset: { width: 0, height: 4 },
    shadowOpacity: 0.15,
    shadowRadius: 12,
    elevation: 8,
  },
  selectedHeader: {
    flexDirection: 'row',
    alignItems: 'center',
    gap: spacing.sm,
    marginBottom: spacing.xs,
  },
  selectedDot: {
    width: 10,
    height: 10,
    borderRadius: 5,
  },
  selectedName: {
    flex: 1,
    fontSize: 15,
    fontWeight: '700',
  },
  selectedAddress: {
    fontSize: 12,
    marginBottom: spacing.sm,
    lineHeight: 16,
  },
  selectedMeta: {
    flexDirection: 'row',
    gap: spacing.xs,
    flexWrap: 'wrap',
  },
  selectedBadge: {
    flexDirection: 'row',
    alignItems: 'center',
    gap: 4,
    paddingHorizontal: spacing.sm,
    paddingVertical: spacing.xs,
    borderRadius: radii.sm,
  },
  selectedBadgeText: {
    fontSize: 11,
    fontWeight: '600',
  },
  locationPanel: {
    backgroundColor: colors.white,
    padding: spacing.md,
    borderTopWidth: 1,
    borderTopColor: colors.gray[100],
  },
  panelHeader: {
    flexDirection: 'row',
    alignItems: 'center',
    gap: spacing.xs,
    marginBottom: spacing.sm,
  },
  panelTitle: {
    fontSize: 14,
    fontWeight: '600',
  },
  loadingContainer: {
    flexDirection: 'row',
    alignItems: 'center',
    justifyContent: 'center',
    gap: spacing.xs,
    padding: spacing.md,
  },
  loadingText: {
    fontSize: 12,
  },
  locationList: {
    gap: 0,
  },
  locationItem: {
    flexDirection: 'row',
    alignItems: 'center',
    paddingVertical: spacing.sm,
    gap: spacing.sm,
  },
  locationItemBorder: {
    borderBottomWidth: 1,
    borderBottomColor: colors.gray[100],
  },
  locationDot: {
    width: 22,
    height: 22,
    borderRadius: 11,
    justifyContent: 'center',
    alignItems: 'center',
  },
  locationDotText: {
    fontSize: 10,
    fontWeight: '700',
    color: colors.white,
  },
  locationInfo: {
    flex: 1,
  },
  locationName: {
    fontSize: 13,
    fontWeight: '600',
  },
  locationAddress: {
    fontSize: 11,
    marginTop: 1,
  },
  radiusBadge: {
    paddingHorizontal: spacing.sm,
    paddingVertical: spacing.xs,
    borderRadius: radii.sm,
  },
  radiusText: {
    fontSize: 11,
    fontWeight: '600',
  },
});
