import React, { useCallback, useEffect, useRef, useState } from 'react';
import { View, Text, TouchableOpacity } from 'react-native';
import { SafeAreaView } from 'react-native-safe-area-context';
import { useNavigation } from '@react-navigation/native';
import * as turf from '@turf/turf';
import MapLibreGL, { CameraRef, MapViewRef } from '@maplibre/maplibre-react-native';

import { Header, Modal, FlatList as List } from 'src/components';

import { VECTOR_MAP_HOST } from 'src/constants';
import { Colors } from 'src/theme';
import { NAVIGATION_PAGES } from 'src/types';
import { RegionAddData } from '../utils/types';
import { useGetRegionsForTripsQuery } from '@api/trips';
import { useGetListRegionsQuery } from '@api/regions';
import { styles } from './styles';

import SearchSvg from '../../../../../assets/icons/search.svg';
import SaveSvg from '../../../../../assets/icons/travels-screens/save.svg';

MapLibreGL.setAccessToken(null);

const generateFilter = (ids: number[]) => {
  return ids?.length ? ['any', ...ids.map((id) => ['==', 'id', id])] : ['==', 'id', -1];
};

let nm_regions = {
  id: 'regions',
  type: 'fill',
  source: 'regions',
  'source-layer': 'regions',
  style: {
    fillColor: 'rgba(15, 63, 79, 0)'
  },
  filter: ['all'],
  maxzoom: 16
};

let selected_region = {
  id: 'selected_region',
  type: 'fill',
  source: 'regions',
  'source-layer': 'regions',
  style: {
    fillColor: 'rgba(237, 147, 52, 0.7)'
  },
  maxzoom: 12
};

const AddRegionsScreen = ({ route }: { route: any }) => {
  const { regionsParams }: { regionsParams: RegionAddData[] } = route.params;
  const { data } = useGetRegionsForTripsQuery(true);
  const { data: regionsList } = useGetListRegionsQuery(true);
  const navigation = useNavigation();

  const [regions, setRegions] = useState<RegionAddData[] | null>(null);
  const [isModalVisible, setIsModalVisible] = useState(false);
  const [selectedRegions, setSelectedRegions] = useState<any[]>([]);
  const [regionsToSave, setRegionsToSave] = useState<RegionAddData[]>([]);
  const [regionData, setRegionData] = useState<RegionAddData | null>(null);
  const [regionPopupVisible, setRegionPopupVisible] = useState(false);
  const mapRef = useRef<MapViewRef>(null);
  const cameraRef = useRef<CameraRef>(null);

  const [filterSelectedRegions, setFilterSelectedRegions] = useState<any[]>(generateFilter([]));

  useEffect(() => {
    if (data && data.regions) {
      setRegions(data.regions);
    }
  }, [data]);

  useEffect(() => {
    const ids = selectedRegions.map((region) => region.id);
    setFilterSelectedRegions(generateFilter(ids));
  }, [selectedRegions]);

  useEffect(() => {
    const addRegionsAsync = async () => {
      if (regionsParams) {
        setRegionsToSave((prevRegions) => [...prevRegions, ...regionsParams]);

        setSelectedRegions(
          (prevSelectedRegions) => [...prevSelectedRegions, ...regionsParams] as any
        );
      }
    };

    addRegionsAsync();
  }, [regionsParams]);

  const addRegionFromSearch = async (searchRegion: RegionAddData) => {
    const regionIndex = selectedRegions.findIndex((region) => region.id === searchRegion.id);
    const regionFromApi = regions?.find((region) => region.id === searchRegion.id);

    if (regionIndex < 0 && regionFromApi) {
      const newRegion = {
        id: searchRegion.id,
        name: searchRegion.name
      };

      setSelectedRegions([...selectedRegions, newRegion] as any);
      setRegionsToSave((prevRegions) => [...prevRegions, regionFromApi]);
      setRegionPopupVisible(true);

      if (regionsList) {
        const region = regionsList.data.find((region) => region.id === searchRegion.id);
        if (region) {
          const bounds = turf.bbox(region.bbox);
          cameraRef.current?.fitBounds(
            [bounds[2], bounds[3]],
            [bounds[0], bounds[1]],
            [50, 50, 50, 50],
            600
          );
        }
      }
    }
  };

  const handleSavePress = () => {
    navigation.navigate(
      ...([
        NAVIGATION_PAGES.ADD_TRIP,
        { regionsToSave: regionsToSave, editTripId: route.params?.editId }
      ] as never)
    );
  };

  const handleSetRegionData = (regionId: number) => {
    const foundRegion = regions?.find((region) => region.id === regionId);

    if (foundRegion) {
      setRegionData(foundRegion);
      setRegionsToSave((prevRegions) => [...prevRegions, foundRegion]);
    }
  };

  const handleMapPress = useCallback(
    async (event: any) => {
      if (!mapRef.current) return;

      try {
        const { screenPointX, screenPointY } = event.properties;

        const { features } = await mapRef.current.queryRenderedFeaturesAtPoint(
          [screenPointX, screenPointY],
          undefined,
          ['regions']
        );

        if (features?.length) {
          const selectedRegion = features[0];

          if (selectedRegion.properties) {
            const id = selectedRegion.properties.id;

            const regionIndex = selectedRegions.findIndex((region) => region.id === id);

            if (regionIndex >= 0) {
              const newSelectedRegions = [...selectedRegions];
              newSelectedRegions.splice(regionIndex, 1);
              setSelectedRegions(newSelectedRegions);
              setRegionsToSave(regionsToSave.filter((region) => region.id !== id));
              setRegionPopupVisible(false);
              return;
            } else {
              setSelectedRegions([...selectedRegions, selectedRegion.properties] as any);
            }

            handleSetRegionData(id);
            setRegionPopupVisible(true);

            if (regionsList) {
              const region = regionsList.data.find((region) => region.id === id);
              if (region) {
                const bounds = turf.bbox(region.bbox);
                cameraRef.current?.fitBounds(
                  [bounds[2], bounds[3]],
                  [bounds[0], bounds[1]],
                  [50, 50, 50, 50],
                  600
                );
              }
            }
          }
        }
      } catch (error) {
        console.error('Failed to get coordinates on AddRegionsScreen', error);
      }
    },
    [selectedRegions, regions]
  );

  return (
    <SafeAreaView style={{ height: '100%' }} edges={['top']}>
      <View style={styles.wrapper}>
        <Header label={'Add Regions'} />
        <View style={styles.searchContainer}>
          <TouchableOpacity style={[styles.regionSelector]} onPress={() => setIsModalVisible(true)}>
            <SearchSvg fill={Colors.LIGHT_GRAY} />
            <Text style={styles.regionText}>Search</Text>
          </TouchableOpacity>
          <TouchableOpacity
            style={[
              styles.saveBtn,
              selectedRegions.length ? styles.saveBtnActive : styles.saveBtnDisabled
            ]}
            onPress={handleSavePress}
            disabled={!selectedRegions.length}
          >
            <SaveSvg fill={selectedRegions.length ? Colors.WHITE : Colors.LIGHT_GRAY} />
          </TouchableOpacity>
        </View>
      </View>

      <View style={styles.container}>
        <MapLibreGL.MapView
          ref={mapRef}
          style={styles.map}
          styleJSON={VECTOR_MAP_HOST + '/nomadmania-maps.json'}
          rotateEnabled={false}
          attributionEnabled={false}
          onPress={handleMapPress}
        >
          <MapLibreGL.Camera ref={cameraRef} />

          <MapLibreGL.LineLayer
            id="nm-regions-line-layer"
            sourceID={nm_regions.source}
            sourceLayerID={nm_regions['source-layer']}
            filter={nm_regions.filter as any}
            maxZoomLevel={nm_regions.maxzoom}
            style={{
              lineColor: 'rgba(14, 80, 109, 1)',
              lineWidth: ['interpolate', ['linear'], ['zoom'], 0, 0.2, 4, 1, 5, 1.5, 12, 3],
              lineWidthTransition: { duration: 300, delay: 0 }
            }}
            belowLayerID="waterway-name"
          />
          <MapLibreGL.FillLayer
            id={nm_regions.id}
            sourceID={nm_regions.source}
            sourceLayerID={nm_regions['source-layer']}
            filter={nm_regions.filter as any}
            style={nm_regions.style}
            maxZoomLevel={nm_regions.maxzoom}
            belowLayerID="nm-regions-line-layer"
          />

          {selectedRegions && selectedRegions.length > 0 ? (
            <MapLibreGL.FillLayer
              id={selected_region.id}
              sourceID={nm_regions.source}
              sourceLayerID={nm_regions['source-layer']}
              filter={filterSelectedRegions as any}
              style={selected_region.style}
              maxZoomLevel={selected_region.maxzoom}
              belowLayerID="nm-regions-line-layer"
            />
          ) : null}
        </MapLibreGL.MapView>
      </View>
      {regionPopupVisible && regionData && (
        <View style={styles.popupWrapper}>
          <View style={styles.popupContainer}>
            <Text style={styles.popupText}>{regionData.name ?? regionData.region_name}</Text>
          </View>
        </View>
      )}
      <Modal
        onRequestClose={() => setIsModalVisible(false)}
        headerTitle={'Select Regions'}
        visible={isModalVisible}
      >
        <List
          itemObject={(object) => {
            setIsModalVisible(false);
            setRegionData(object);
            addRegionFromSearch(object);
          }}
        />
      </Modal>
    </SafeAreaView>
  );
};

export default AddRegionsScreen;
