import {
  Dimensions,
  Linking,
  Platform,
  Text,
  TextInput,
  TouchableOpacity,
  View,
  Image,
  StatusBar
} from 'react-native';
import React, { useEffect, useRef, useState, useCallback } from 'react';

import MapLibreGL, { CameraRef, MapViewRef } from '@maplibre/maplibre-react-native';
import { styles } from './style';
import { SafeAreaView } from 'react-native-safe-area-context';
import { Colors } from 'src/theme';
import { storage, StoreType } from 'src/storage';
import { RegionPayload } from '@maplibre/maplibre-react-native/javascript/components/MapView';
import * as turf from '@turf/turf';
import * as Location from 'expo-location';

import SearchIcon from 'assets/icons/search.svg';
import LocationIcon from 'assets/icons/location.svg';
import CloseSvg from 'assets/icons/close.svg';
import FilterIcon from 'assets/icons/filter.svg';
import ProfileIcon from 'assets/icons/bottom-navigation/profile.svg';
import RegionPopup from 'src/components/RegionPopup';
import { useRegion } from 'src/contexts/RegionContext';
import { qualityOptions } from '../TravelsScreen/utils/constants';
import { AvatarWithInitials, EditNmModal, WarningModal } from 'src/components';
import { API_HOST, MAP_HOST, VECTOR_MAP_HOST } from 'src/constants';
import { NAVIGATION_PAGES } from 'src/types';
import Animated, {
  Easing,
  useAnimatedStyle,
  useSharedValue,
  withTiming
} from 'react-native-reanimated';
import { getData } from 'src/modules/map/regionData';
import {
  getCountriesDatabase,
  getFirstDatabase,
  getSecondDatabase,
  refreshDatabases
} from 'src/db';
import { fetchUserData, fetchUserDataDare, useGetListRegionsQuery } from '@api/regions';
import { SQLiteDatabase } from 'expo-sqlite/legacy';
import { useFocusEffect } from '@react-navigation/native';
import { useGetUniversalSearch } from '@api/search';
import { fetchCountryUserData, useGetListCountriesQuery } from '@api/countries';
import SearchModal from './UniversalSearch';
import EditModal from '../TravelsScreen/Components/EditSlowModal';

import CheckSvg from 'assets/icons/mark.svg';
import moment from 'moment';
import {
  usePostGetVisitedCountriesIdsQuery,
  usePostGetVisitedDareIdsQuery,
  usePostGetVisitedRegionsIdsQuery,
  usePostGetVisitedSeriesIdsQuery
} from '@api/maps';
import FilterModal from './FilterModal';
import { useGetListDareQuery } from '@api/myDARE';
import { useGetIconsQuery, usePostSetToggleItem } from '@api/series';
import MarkerItem from './MarkerItem';
import { usePostGetUsersLocationQuery, usePostUpdateLocationMutation } from '@api/location';

MapLibreGL.setAccessToken(null);
MapLibreGL.Logger.setLogLevel('error');

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

// to do refactor
let regions_visited = {
  id: 'regions_visited',
  type: 'fill',
  source: 'regions',
  'source-layer': 'regions',
  style: {
    fillColor: 'rgba(255, 126, 0, 1)',
    fillOpacity: 0.6,
    fillOutlineColor: 'rgba(14, 80, 109, 1)'
  },
  filter: generateFilter([]),
  maxzoom: 12
};

let countries_visited = {
  id: 'countries_visited',
  type: 'fill',
  source: 'countries',
  'source-layer': 'countries',
  style: {
    fillColor: 'rgba(255, 126, 0, 1)',
    fillOpacity: 0.6,
    fillOutlineColor: 'rgba(14, 80, 109, 1)'
  },
  filter: generateFilter([]),
  maxzoom: 10
};

let dare_visited = {
  id: 'dare_visited',
  type: 'fill',
  source: 'dare',
  'source-layer': 'dare',
  style: {
    fillColor: 'rgba(255, 126, 0, 1)',
    fillOpacity: 0.6,
    fillOutlineColor: 'rgba(255, 126, 0, 1)'
  },
  filter: generateFilter([]),
  maxzoom: 12
};

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

let countries = {
  id: 'countries',
  type: 'fill',
  source: 'countries',
  'source-layer': 'countries',
  style: {
    fillColor: 'rgba(15, 63, 79, 0)',
    fillOutlineColor: 'rgba(14, 80, 109, 1)'
  },
  filter: ['all'],
  maxzoom: 16
};

let dare = {
  id: 'dare',
  type: 'fill',
  source: 'dare',
  'source-layer': 'dare',
  style: {
    fillColor: 'rgba(14, 80, 109, 0.6)',
    fillOutlineColor: 'rgba(14, 80, 109, 1)'
  },
  filter: ['all'],
  maxzoom: 16
};

let selected_region = {
  id: 'selected_region',
  type: 'fill',
  source: 'regions',
  'source-layer': 'regions',
  style: {
    fillColor: 'rgba(57, 115, 172, 0.3)',
    fillOutlineColor: '#3973ac'
  },
  maxzoom: 12
};

let series_layer = {
  id: 'series_layer',
  type: 'symbol',
  source: 'nomadmania_series',
  'source-layer': 'series',
  layout: {
    'icon-image': '{series_id}',
    'icon-size': 0.1,
    'text-anchor': 'top',
    'text-field': '{series_name} - {name}',
    'text-font': ['Noto Sans Regular'],
    'text-max-width': 9,
    'text-offset': [0, 0.6],
    'text-padding': 2,
    'text-size': 12,
    visibility: 'visible',
    'text-optional': true,
    'text-ignore-placement': true,
    'text-allow-overlap': true
  },
  paint: {
    'text-color': '#666',
    'text-halo-blur': 0.5,
    'text-halo-color': '#ffffff',
    'text-halo-width': 1
  },
  filter: generateFilter([])
};

let series_visited = {
  id: 'series_visited',
  type: 'symbol',
  source: 'nomadmania_series',
  'source-layer': 'series',
  layout: {
    'icon-image': '{series_id}v',
    'icon-size': 0.15,
    'text-anchor': 'top',
    'text-field': '{series_name} - {name}',
    'text-font': ['Noto Sans Regular'],
    'text-max-width': 9,
    'text-offset': [0, 0.6],
    'text-padding': 2,
    'text-size': 12,
    visibility: 'visible',
    'text-optional': true,
    'text-ignore-placement': true,
    'text-allow-overlap': true
  },
  paint: {
    'text-color': '#666',
    'text-halo-blur': 0.5,
    'text-halo-color': '#ffffff',
    'text-halo-width': 1
  },
  filter: generateFilter([])
};

const INITIAL_REGION = {
  latitude: 0,
  longitude: 0,
  latitudeDelta: 180,
  longitudeDelta: 180
};

const MapScreen: any = ({ navigation, route }: { navigation: any; route: any }) => {
  const userId = storage.get('uid', StoreType.STRING) as string;
  const token = storage.get('token', StoreType.STRING) as string;

  const { data: regionsList } = useGetListRegionsQuery(true);
  const { data: countriesList } = useGetListCountriesQuery(true);
  const { data: dareList } = useGetListDareQuery(true);

  const [tilesType, setTilesType] = useState({ label: 'NM regions', value: 0 });
  const tilesTypes = [
    { label: 'NM regions', value: 0 },
    { label: 'UN countries', value: 1 },
    { label: 'DARE places', value: 2 }
  ];
  const [type, setType] = useState<'regions' | 'countries' | 'dare'>('regions');
  const [seriesFilter, setSeriesFilter] = useState<any>({
    visible: true,
    groups: [],
    applied: false,
    status: -1
  });
  const [regionsFilter, setRegionsFilter] = useState<any>({
    visitedLabel: 'by',
    year: moment().year()
  });
  const [showNomads, setShowNomads] = useState(
    (storage.get('showNomads', StoreType.BOOLEAN) as boolean) ?? false
  );
  const { mutateAsync: updateLocation } = usePostUpdateLocationMutation();
  const { data: visitedRegionIds, refetch: refetchVisitedRegions } =
    usePostGetVisitedRegionsIdsQuery(
      token,
      regionsFilter.visitedLabel,
      regionsFilter.year,
      +userId,
      type === 'regions' && !!userId
    );
  const { data: visitedCountryIds, refetch: refetchVisitedCountries } =
    usePostGetVisitedCountriesIdsQuery(
      token,
      regionsFilter.visitedLabel,
      regionsFilter.year,
      +userId,
      type === 'countries' && !!userId
    );
  const { data: visitedDareIds, refetch: refetchVisitedDare } = usePostGetVisitedDareIdsQuery(
    token,
    +userId,
    type === 'dare' && !!userId
  );
  const { data: visitedSeriesIds } = usePostGetVisitedSeriesIdsQuery(token, !!userId);
  const { data: seriesIcons } = useGetIconsQuery(true);
  const userInfo = storage.get('currentUserData', StoreType.STRING) as string;
  const { mutateAsync: mutateUserData } = fetchUserData();
  const { mutateAsync: mutateUserDataDare } = fetchUserDataDare();
  const { mutateAsync: mutateCountriesData } = fetchCountryUserData();

  const [selectedRegion, setSelectedRegion] = useState<number | null>(null);
  const [initialRegion, setInitialRegion] = useState(INITIAL_REGION);
  const [regionPopupVisible, setRegionPopupVisible] = useState<boolean | null>(false);
  const [regionData, setRegionData] = useState<any | null>(null);
  const [location, setLocation] = useState<any | null>(null);
  const [userAvatars, setUserAvatars] = useState<string[]>([]);
  const [userInfoData, setUserInfoData] = useState<any>(null);
  const [selectedMarker, setSelectedMarker] = useState<any>(null);

  const [askLocationVisible, setAskLocationVisible] = useState<boolean>(false);
  const [openSettingsVisible, setOpenSettingsVisible] = useState<boolean>(false);
  const [isWarningModalVisible, setIsWarningModalVisible] = useState<boolean>(false);
  const [isEditSlowModalVisible, setIsEditSlowModalVisible] = useState<boolean>(false);
  const [isEditModalVisible, setIsEditModalVisible] = useState(false);
  const [isFilterVisible, setIsFilterVisible] = useState(false);

  const [modalState, setModalState] = useState({
    selectedFirstYear: 2021,
    selectedLastYear: 2021,
    selectedQuality: qualityOptions[2],
    selectedNoOfVisits: 1,
    years: [],
    id: null
  });

  const [isConnected, setIsConnected] = useState<boolean | null>(true);
  const [isExpanded, setIsExpanded] = useState(false);
  const [search, setSearch] = useState('');
  const { data: searchData } = useGetUniversalSearch(search, search.length > 0);
  const [searchInput, setSearchInput] = useState('');
  const [searchVisible, setSearchVisible] = useState<boolean>(false);
  const [index, setIndex] = useState<number>(0);
  const width = useSharedValue(48);
  const usableWidth = Dimensions.get('window').width - 32;

  const { handleUpdateNM, handleUpdateDare, handleUpdateSlow, userData, setUserData } = useRegion();

  const [db1, setDb1] = useState<SQLiteDatabase | null>(null);
  const [db2, setDb2] = useState<SQLiteDatabase | null>(null);
  const [db3, setDb3] = useState<SQLiteDatabase | null>(null);

  const [regionsVisitedFilter, setRegionsVisitedFilter] = useState(generateFilter([]));
  const [countriesVisitedFilter, setCountriesVisitedFilter] = useState(generateFilter([]));
  const [dareVisitedFilter, setDareVisitedFilter] = useState(generateFilter([]));
  const [seriesVisitedFilter, setSeriesVisitedFilter] = useState(generateFilter([]));
  const [seriesNotVisitedFilter, setSeriesNotVisitedFilter] = useState(generateFilter([]));
  const [regionsVisited, setRegionsVisited] = useState<any[]>([]);
  const [countriesVisited, setCountriesVisited] = useState<any[]>([]);
  const [dareVisited, setDareVisited] = useState<any[]>([]);
  const [seriesVisited, setSeriesVisited] = useState<any[]>([]);
  const [images, setImages] = useState<any>({});
  const { mutateAsync: updateSeriesItem } = usePostSetToggleItem();
  const [nomads, setNomads] = useState<GeoJSON.FeatureCollection | null>(null);
  const { data: usersLocation } = usePostGetUsersLocationQuery(
    token,
    !!token && showNomads && Boolean(location)
  );

  useEffect(() => {
    if (!showNomads) {
      setNomads(null);
    }
  }, [showNomads]);

  useEffect(() => {
    if (usersLocation) {
      console.log('usersLocation', usersLocation);
      setNomads(usersLocation.geojson);
    }
  }, [usersLocation]);

  useEffect(() => {
    let loadedImages: any = {};

    if (seriesIcons) {
      seriesIcons.data.forEach(async (icon) => {
        const id = icon.id;
        const img = API_HOST + '/static/img/series_new2/' + icon.new_icon_png;
        const imgVisited = API_HOST + '/static/img/series_new2/' + icon.new_icon_visited_png;
        if (!img || !imgVisited) return;
        try {
          const iconImage = { uri: img };
          const visitedIconImage = { uri: imgVisited };

          loadedImages[id] = iconImage;
          loadedImages[`${id}v`] = visitedIconImage;
        } catch (error) {
          console.error(`Error loading icon for series_id ${id}:`, error);
        }
      });
    }

    if (nomads && nomads.features) {
      nomads.features.forEach((feature) => {
        const user_id = `user_${feature.properties?.id}`;
        const avatarUrl = `${API_HOST}${feature.properties?.avatar}`;
        if (avatarUrl) {
          loadedImages[user_id] = { uri: avatarUrl };
          if (feature.properties) {
            feature.properties.icon_key = user_id;
          }
        }
      });
    }

    setImages(loadedImages);
  }, [nomads, seriesIcons]);

  useEffect(() => {
    const loadDatabases = async () => {
      const firstDb = await getFirstDatabase();
      const secondDb = await getSecondDatabase();
      const countriesDb = await getCountriesDatabase();

      setDb1(firstDb);
      setDb2(secondDb);
      setDb3(countriesDb);
    };

    if (!db1 || !db2 || !db3) {
      loadDatabases();
    }
  }, [db1, db2, db3]);

  useEffect(() => {
    const savedFilterSettings = storage.get('filterSettings', StoreType.STRING) as string;
    if (savedFilterSettings) {
      const filterSettings = JSON.parse(savedFilterSettings);
      setTilesType(filterSettings.tilesType);
      setType(filterSettings.type);
      setRegionsFilter({
        visitedLabel: filterSettings.selectedVisible.value === 1 ? 'in' : 'by',
        year: filterSettings.selectedYear.value
      });
      setSeriesFilter(filterSettings.seriesFilter);
    }
  }, []);

  useFocusEffect(
    useCallback(() => {
      if (token) {
        refetchVisitedRegions();
        refetchVisitedCountries();
        refetchVisitedDare();
      }
    }, [navigation])
  );

  // to do refactor
  useEffect(() => {
    if (visitedRegionIds) {
      setRegionsVisited(visitedRegionIds.ids);
    }
  }, [visitedRegionIds]);

  useEffect(() => {
    if (visitedCountryIds) {
      setCountriesVisited(visitedCountryIds.ids);
    }
  }, [visitedCountryIds]);

  useEffect(() => {
    if (visitedDareIds) {
      setDareVisited(visitedDareIds.ids);
    }
  }, [visitedDareIds]);

  useEffect(() => {
    if (visitedSeriesIds && token) {
      setSeriesVisited(visitedSeriesIds.ids);
    }
  }, [visitedSeriesIds]);

  useEffect(() => {
    if (regionsVisited && regionsVisited.length) {
      setRegionsVisitedFilter(generateFilter(regionsVisited));
    }
  }, [regionsVisited]);

  useEffect(() => {
    if (countriesVisited && countriesVisited.length) {
      setCountriesVisitedFilter(generateFilter(countriesVisited));
    }
  }, [countriesVisited]);

  useEffect(() => {
    if (dareVisited && dareVisited.length) {
      setDareVisitedFilter(generateFilter(dareVisited));
    }
  }, [dareVisited]);

  useEffect(() => {
    if (!seriesFilter.visible) {
      setSeriesVisitedFilter(generateFilter([]));
      setSeriesNotVisitedFilter(generateFilter([]));
      return;
    }

    if (seriesFilter.applied) {
      if (seriesVisited?.length) {
        setSeriesVisitedFilter([
          'all',
          ['any', ...seriesVisited.map((id) => ['==', 'id', id])],
          ['any', ...seriesFilter.groups.map((groupId: number) => ['==', 'series_id', groupId])]
        ]);
        setSeriesNotVisitedFilter([
          'all',
          ['all', ...seriesVisited.map((id) => ['!=', 'id', id])],
          ['any', ...seriesFilter.groups.map((groupId: number) => ['==', 'series_id', groupId])]
        ]);
      } else {
        setSeriesNotVisitedFilter([
          'any',
          ...seriesFilter.groups.map((groupId: number) => ['==', 'series_id', groupId])
        ]);
      }
    } else {
      setSeriesVisitedFilter(['any', ...seriesVisited.map((id) => ['==', 'id', id])]);
      setSeriesNotVisitedFilter(['all', ...seriesVisited.map((id) => ['!=', 'id', id])]);
    }
  }, [seriesVisited, seriesFilter]);

  useEffect(() => {
    if (route.params?.id && route.params?.type && db1 && db2 && db3) {
      handleFindRegion(route.params?.id, route.params?.type);
    }
  }, [route, db1, db2, db3]);

  useEffect(() => {
    if (selectedRegion) {
      mapRef.current;
    }
  }, [selectedRegion]);

  useEffect(() => {
    (async () => {
      let { status } = await Location.getForegroundPermissionsAsync();
      if (status !== 'granted') {
        setShowNomads(false);
        storage.set('showNomads', false);
        return;
      }

      let currentLocation = await Location.getCurrentPositionAsync({
        accuracy: Location.Accuracy.Balanced
      });
      setLocation(currentLocation.coords);
      updateLocation({
        token,
        lat: currentLocation.coords.latitude,
        lng: currentLocation.coords.longitude
      });
    })();
  }, []);

  useEffect(() => {
    const currentYear = moment().year();
    let yearSelector: { label: string; value: number }[] = [{ label: 'visited', value: 1 }];
    for (let i = currentYear; i >= 1951; i--) {
      yearSelector.push({ label: i.toString(), value: i });
    }
    handleModalStateChange({ years: yearSelector });
  }, []);

  useFocusEffect(
    useCallback(() => {
      navigation.getParent()?.setOptions({
        tabBarStyle: {
          display: regionPopupVisible ? 'none' : 'flex',
          position: 'absolute',
          ...Platform.select({
            android: {
              height: 58
            }
          })
        }
      });
    }, [regionPopupVisible, navigation])
  );

  const mapRef = useRef<MapViewRef>(null);
  const cameraRef = useRef<CameraRef>(null);

  useEffect(() => {
    if (userInfo) {
      setUserInfoData(JSON.parse(userInfo));
    }
  }, [userInfo]);

  const handlePress = () => {
    if (isExpanded) {
      setIndex(0);
      setSearchInput('');
    }
    setIsExpanded((prev) => !prev);
    width.value = withTiming(isExpanded ? 48 : usableWidth, {
      duration: 300,
      easing: Easing.inOut(Easing.ease)
    });
  };

  const animatedStyle = useAnimatedStyle(() => {
    return {
      width: width.value
    };
  });

  const loadInitialRegion = () => {
    try {
      const savedInitialRegion = storage.get('initialRegion', StoreType.STRING) as string;
      if (savedInitialRegion) {
        const region = JSON.parse(savedInitialRegion);
        setInitialRegion(region);
      }
    } catch (e) {
      console.error('Failed to load saved initial region:', e);
    }
  };

  useEffect(() => {
    loadInitialRegion();
  }, []);

  useEffect(() => {
    if (initialRegion && !route.params?.id) {
      setTimeout(() => {
        cameraRef.current?.setCamera({
          centerCoordinate: [initialRegion.longitude, initialRegion.latitude],
          zoomLevel: Math.log2(360 / initialRegion.latitudeDelta),
          animationDuration: 500
        });
      }, 500);
    }
  }, [initialRegion]);

  const onMapPress = async (event: any) => {
    if (!mapRef.current) return;
    if (selectedMarker) {
      closeCallout();
      return;
    }
    try {
      const { screenPointX, screenPointY } = event.properties;

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

      if (features?.length) {
        const region = features[0];
        if (selectedRegion === region.properties?.id) return;

        let db = type === 'regions' ? db1 : type === 'countries' ? db3 : db2;
        let tableName = type === 'dare' ? 'places' : type;
        let foundRegion = region.properties?.id;

        setSelectedRegion(region.properties?.id);

        await getData(db, foundRegion, tableName, handleRegionData)
          .then(() => {
            setRegionPopupVisible(true);
          })
          .catch((error) => {
            console.error('Error fetching data', error);
            refreshDatabases();
          });

        if (tableName === 'regions') {
          token
            ? await mutateUserData(
                { region_id: +foundRegion, token: String(token) },
                {
                  onSuccess: (data) => {
                    setUserData({ type: 'nm', id: +foundRegion, ...data });
                  }
                }
              )
            : setUserData({ type: 'nm', id: +foundRegion });
          if (regionsList) {
            const region = regionsList.data.find((region) => region.id === +foundRegion);
            if (region) {
              const bounds = turf.bbox(region.bbox);
              cameraRef.current?.fitBounds(
                [bounds[2], bounds[3]],
                [bounds[0], bounds[1]],
                [10, 10, 50, 10],
                1000
              );
            }
          }
        } else if (tableName === 'countries') {
          token
            ? await mutateCountriesData(
                { id: +foundRegion, token },
                {
                  onSuccess: (data) => {
                    setUserData({ type: 'countries', id: +foundRegion, ...data.data });
                  }
                }
              )
            : setUserData({ type: 'countries', id: +foundRegion });
          if (countriesList) {
            const region = countriesList.data.find((region) => region.id === +foundRegion);
            if (region) {
              const bounds = turf.bbox(region.bbox);
              cameraRef.current?.fitBounds(
                [bounds[2], bounds[3]],
                [bounds[0], bounds[1]],
                [10, 10, 50, 10],
                1000
              );
            }
          }
        } else {
          token
            ? await mutateUserDataDare(
                { dare_id: +foundRegion, token: String(token) },
                {
                  onSuccess: (data) => {
                    setUserData({ type: 'dare', id: +foundRegion, ...data });
                  }
                }
              )
            : setUserData({ type: 'dare', id: +foundRegion });
          if (dareList) {
            const region = dareList.data.find((region) => region.id === +foundRegion);
            if (region) {
              const bounds = turf.bbox(region.bbox);
              cameraRef.current?.fitBounds(
                [bounds[2], bounds[3]],
                [bounds[0], bounds[1]],
                [10, 10, 50, 10],
                1000
              );
            }
          }
        }
      } else {
        handleClosePopup();
      }
    } catch (error) {
      console.error('Error onMapPress features:', error);
    }
  };

  const handleRegionDidChange = async (feature: GeoJSON.Feature<GeoJSON.Point, RegionPayload>) => {
    if (!feature) return;
    const { zoomLevel } = feature.properties;
    const { coordinates } = feature.geometry;
    if (!zoomLevel || !coordinates) return;

    const latitudeDelta = 360 / 2 ** zoomLevel;
    const longitudeDelta = latitudeDelta;

    const region = {
      latitude: coordinates[1],
      longitude: coordinates[0],
      latitudeDelta,
      longitudeDelta
    };

    storage.set('initialRegion', JSON.stringify(region));
  };

  const handleClosePopup = async () => {
    setSelectedRegion(null);
    setRegionPopupVisible(false);
    setRegionData(null);
  };

  const handleGetLocation = async () => {
    let { status, canAskAgain } = await Location.getForegroundPermissionsAsync();

    if (status === 'granted') {
      getLocation();
    } else if (!canAskAgain) {
      setOpenSettingsVisible(true);
    } else {
      setAskLocationVisible(true);
    }
  };

  const getLocation = async () => {
    let currentLocation = await Location.getCurrentPositionAsync({
      accuracy: Location.Accuracy.Balanced
    });
    setLocation(currentLocation.coords);
    updateLocation({
      token,
      lat: currentLocation.coords.latitude,
      lng: currentLocation.coords.longitude
    });
    if (currentLocation.coords) {
      cameraRef.current?.flyTo(
        [currentLocation.coords.longitude, currentLocation.coords.latitude],
        1000
      );
    }

    handleClosePopup();
  };

  const handleAcceptPermission = async () => {
    setAskLocationVisible(false);
    let { status, canAskAgain } = await Location.requestForegroundPermissionsAsync();

    if (status === 'granted') {
      getLocation();
    } else if (!canAskAgain) {
      setOpenSettingsVisible(true);
    }
  };

  const handleOpenEditModal = () => {
    handleModalStateChange({
      selectedFirstYear: userData?.first_visit_year,
      selectedLastYear: userData?.last_visit_year,
      selectedQuality:
        qualityOptions.find((quality) => quality.id === userData?.best_visit_quality) ||
        qualityOptions[2],
      selectedNoOfVisits: userData?.no_of_visits || 1,
      id: regionData?.id
    });
    setIsEditModalVisible(true);
  };

  const handleOpenEditSlowModal = () => {
    setIsEditSlowModalVisible(true);
  };

  const handleSearch = async () => {
    setSearch(searchInput);
    setSearchVisible(true);
  };

  const handleCloseModal = () => {
    setSearchInput('');
    setSearchVisible(false);
    handlePress();
  };

  const handleRegionData = (regionData: any, avatars: string[]) => {
    setRegionData(regionData);
    setUserAvatars(avatars);
  };

  const handleFindRegion = async (id: number, type: 'regions' | 'countries' | 'places') => {
    setType(type === 'places' ? 'dare' : type);
    if (!db1 || !db2 || !db3) {
      return;
    }
    const db = type === 'regions' ? db1 : type === 'countries' ? db3 : db2;

    if (id) {
      setSelectedRegion(id);

      await getData(db, id, type, handleRegionData)
        .then(() => {
          setRegionPopupVisible(true);
        })
        .catch((error) => {
          console.error('Error fetching data', error);
          refreshDatabases();
        });

      if (type === 'regions') {
        token
          ? await mutateUserData(
              { region_id: id, token: String(token) },
              {
                onSuccess: (data) => {
                  setUserData({ type: 'nm', id, ...data });
                }
              }
            )
          : setUserData({ type: 'nm', id });

        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]],
              [10, 10, 50, 10],
              1000
            );
          }
        }
      } else if (type === 'countries') {
        token
          ? await mutateCountriesData(
              { id, token },
              {
                onSuccess: (data) => {
                  setUserData({ type: 'countries', id, ...data.data });
                }
              }
            )
          : setUserData({ type: 'countries', id });

        if (countriesList) {
          const region = countriesList.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]],
              [10, 10, 50, 10],
              1000
            );
          }
        }
      } else {
        token
          ? await mutateUserDataDare(
              { dare_id: +id, token: String(token) },
              {
                onSuccess: (data) => {
                  setUserData({ type: 'dare', id: +id, ...data });
                }
              }
            )
          : setUserData({ type: 'dare', id: +id });

        if (dareList) {
          const region = dareList.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]],
              [10, 10, 50, 10],
              1000
            );
          }
        }
      }
    } else {
      handleClosePopup();
    }
  };

  const handleMarkerPress = async (event: any) => {
    const { features } = event;
    if (features?.length) {
      const selectedFeature = features[0];
      const { coordinates } = selectedFeature.geometry;
      const visited = seriesVisited.includes(selectedFeature.properties.id) ? 1 : 0;
      const icon = images[selectedFeature.properties.series_id];

      const { name, description, series_name, series_id, id } = selectedFeature.properties;

      setSelectedMarker({
        coordinates,
        name,
        icon,
        description,
        series_name,
        visited,
        series_id,
        id
      });
    }
  };

  const closeCallout = () => {
    setSelectedMarker(null);
  };

  const toggleSeries = useCallback(
    async (item: any) => {
      if (!token) {
        setIsWarningModalVisible(true);
        return;
      }

      const itemData = {
        token,
        series_id: item.series_id,
        item_id: item.id,
        checked: (item.visited === 0 ? 1 : 0) as 0 | 1,
        double: 0 as 0 | 1
      };

      try {
        updateSeriesItem(itemData);
        if (item.visited === 1) {
          setSeriesVisited((current) => current.filter((id) => id !== item.id));
          setSelectedMarker((current: any) => ({ ...current, visited: 0 }));
        } else {
          setSeriesVisited((current) => [...current, item.id]);
          setSelectedMarker((current: any) => ({ ...current, visited: 1 }));
        }
      } catch (error) {
        console.error('Failed to update series state', error);
      }
    },
    [token, updateSeriesItem]
  );

  const handleModalStateChange = (updates: { [key: string]: any }) => {
    setModalState((prevState) => ({ ...prevState, ...updates }));
  };

  return (
    <SafeAreaView style={{ height: '100%' }}>
      <StatusBar translucent backgroundColor="transparent" />

      <MapLibreGL.MapView
        ref={mapRef}
        style={styles.map}
        styleJSON={VECTOR_MAP_HOST + '/nomadmania-maps.json'}
        rotateEnabled={false}
        attributionEnabled={false}
        onPress={onMapPress}
        onRegionDidChange={handleRegionDidChange}
      >
        <MapLibreGL.Images images={images}>
          <View />
        </MapLibreGL.Images>

        {type === 'regions' && (
          <>
            <MapLibreGL.FillLayer
              id={regions.id}
              sourceID={regions.source}
              sourceLayerID={regions['source-layer']}
              filter={regions.filter as any}
              style={regions.style}
              maxZoomLevel={regions.maxzoom}
              belowLayerID={regions_visited.id}
            />
            <MapLibreGL.FillLayer
              id={regions_visited.id}
              sourceID={regions_visited.source}
              sourceLayerID={regions_visited['source-layer']}
              filter={regionsVisitedFilter as any}
              style={regions_visited.style}
              maxZoomLevel={regions_visited.maxzoom}
              belowLayerID="waterway-name"
            />
          </>
        )}
        {type === 'countries' && (
          <>
            <MapLibreGL.FillLayer
              id={countries.id}
              sourceID={countries.source}
              sourceLayerID={countries['source-layer']}
              filter={countries.filter as any}
              style={countries.style}
              maxZoomLevel={countries.maxzoom}
              belowLayerID={countries_visited.id}
            />
            <MapLibreGL.FillLayer
              id={countries_visited.id}
              sourceID={countries_visited.source}
              sourceLayerID={countries_visited['source-layer']}
              filter={countriesVisitedFilter as any}
              style={countries_visited.style}
              maxZoomLevel={countries_visited.maxzoom}
              belowLayerID="waterway-name"
            />
          </>
        )}
        {type === 'dare' && (
          <>
            <MapLibreGL.FillLayer
              id={dare.id}
              sourceID={dare.source}
              sourceLayerID={dare['source-layer']}
              filter={dare.filter as any}
              style={dare.style}
              maxZoomLevel={dare.maxzoom}
              belowLayerID={dare_visited.id}
            />
            <MapLibreGL.FillLayer
              id={dare_visited.id}
              sourceID={dare_visited.source}
              sourceLayerID={dare_visited['source-layer']}
              filter={dareVisitedFilter as any}
              style={dare_visited.style}
              maxZoomLevel={dare_visited.maxzoom}
              belowLayerID="waterway-name"
            />
          </>
        )}
        {selectedRegion && type && (
          <MapLibreGL.FillLayer
            id={selected_region.id}
            sourceID={type}
            sourceLayerID={type}
            filter={['==', 'id', selectedRegion]}
            style={selected_region.style}
            maxZoomLevel={selected_region.maxzoom}
            belowLayerID="waterway-name"
          />
        )}

        <MapLibreGL.VectorSource
          id="nomadmania_series"
          tileUrlTemplates={[MAP_HOST + '/tileserver/series/{z}/{x}/{y}.pbf']}
          onPress={handleMarkerPress}
        >
          {seriesFilter.status !== 1 ? (
            <MapLibreGL.SymbolLayer
              id={series_layer.id}
              sourceID={series_layer.source}
              sourceLayerID={series_layer['source-layer']}
              belowLayerID={Platform.OS === 'android' ? 'waterway-name' : undefined}
              filter={seriesNotVisitedFilter as any}
              style={{
                iconImage: ['get', 'series_id'],
                iconSize: 0.18,
                visibility: 'visible',
                iconColor: '#666',
                iconOpacity: 1,
                iconHaloColor: '#ffffff',
                iconHaloWidth: 1,
                iconHaloBlur: 0.5
              }}
            />
          ) : (
            <></>
          )}

          {seriesFilter.status !== 0 ? (
            <MapLibreGL.SymbolLayer
              id={series_visited.id}
              sourceID={series_visited.source}
              sourceLayerID={series_visited['source-layer']}
              belowLayerID={Platform.OS === 'android' ? 'waterway-name' : undefined}
              filter={seriesVisitedFilter as any}
              style={{
                iconImage: '{series_id}v',
                iconSize: 0.18,
                visibility: 'visible',
                iconColor: '#666',
                iconOpacity: 1,
                iconHaloColor: '#ffffff',
                iconHaloWidth: 1,
                iconHaloBlur: 0.5
              }}
            />
          ) : (
            <></>
          )}
        </MapLibreGL.VectorSource>

        {nomads && (
          <MapLibreGL.ShapeSource
            id="nomads"
            shape={nomads}
            onPress={(event) => console.log(event.features)}
          >
            <MapLibreGL.SymbolLayer
              id="nomads_symbol"
              style={{
                iconImage: ['get', 'icon_key'],
                iconSize: 0.15,
                iconAllowOverlap: true
              }}
            ></MapLibreGL.SymbolLayer>
          </MapLibreGL.ShapeSource>
        )}

        {selectedMarker && (
          <MarkerItem marker={selectedMarker} toggleSeries={toggleSeries} token={token} />
        )}
        <MapLibreGL.Camera ref={cameraRef} />
        {location && (
          <MapLibreGL.UserLocation animated={true} showsUserHeadingIndicator={true}>
            {/* to do custom user location */}
          </MapLibreGL.UserLocation>
        )}
      </MapLibreGL.MapView>

      {regionPopupVisible && regionData ? (
        <>
          <TouchableOpacity
            style={[styles.cornerButton, styles.topLeftButton, styles.closeLeftButton]}
            onPress={handleClosePopup}
          >
            <CloseSvg fill="white" width={13} height={13} />
            <Text style={styles.textClose}>Close</Text>
          </TouchableOpacity>

          <TouchableOpacity
            onPress={handleGetLocation}
            style={[styles.cornerButton, styles.topRightButton, styles.bottomButton]}
          >
            <LocationIcon />
          </TouchableOpacity>

          <RegionPopup
            region={regionData}
            userAvatars={userAvatars}
            userData={userData}
            openEditModal={handleOpenEditModal}
            updateNM={(id, first, last, visits, quality) => {
              if (!token) {
                setIsWarningModalVisible(true);
                return;
              }
              handleUpdateNM(id, first, last, visits, quality);

              const updatedIds = regionsVisited.includes(id)
                ? regionsVisited.filter((visitedId) => visitedId !== id)
                : [...regionsVisited, id];
              setRegionsVisited(updatedIds);
              refetchVisitedCountries();
            }}
            updateDare={(id, visits) => {
              if (!token) {
                setIsWarningModalVisible(true);
                return;
              }
              handleUpdateDare(id, visits);

              const updatedIds = dareVisited.includes(id)
                ? dareVisited.filter((visitedId) => visitedId !== id)
                : [...dareVisited, id];
              setDareVisited(updatedIds);
            }}
            disabled={!token || !isConnected}
            updateSlow={(id, v, s11, s31, s101) => {
              if (!token) {
                setIsWarningModalVisible(true);
                return;
              }
              handleUpdateSlow(id, v, s11, s31, s101);

              const updatedIds = countriesVisited.includes(id)
                ? countriesVisited.filter((visitedId) => visitedId !== id)
                : [...countriesVisited, id];
              setCountriesVisited(updatedIds);
            }}
            openEditSlowModal={handleOpenEditSlowModal}
          />
        </>
      ) : (
        <>
          {!isExpanded ? (
            <TouchableOpacity
              style={[styles.cornerButton, styles.topRightButton]}
              onPress={() => navigation.navigate(NAVIGATION_PAGES.PROFILE_TAB)}
            >
              {token ? (
                userInfoData?.avatar ? (
                  <Image
                    style={styles.avatar}
                    source={{ uri: API_HOST + '/img/avatars/' + userInfoData?.avatar }}
                  />
                ) : (
                  <AvatarWithInitials
                    text={`${userInfoData?.first_name ? userInfoData?.first_name[0] : ''}${userInfoData?.last_name ? userInfoData?.last_name[0] : ''}`}
                    flag={API_HOST + '/img/flags_new/' + userInfoData?.homebase_flag}
                    size={48}
                    borderColor={Colors.WHITE}
                  />
                )
              ) : (
                <ProfileIcon fill={Colors.DARK_BLUE} />
              )}
            </TouchableOpacity>
          ) : null}

          <Animated.View
            style={[
              styles.searchContainer,
              styles.cornerButton,
              styles.topLeftButton,
              animatedStyle,
              { padding: 5 }
            ]}
          >
            {isExpanded ? (
              <>
                <TouchableOpacity onPress={handlePress} style={styles.iconButton}>
                  <CloseSvg fill={'#0F3F4F'} />
                </TouchableOpacity>
                <TextInput
                  style={styles.input}
                  placeholder="Search regions, places, nomads"
                  placeholderTextColor={Colors.LIGHT_GRAY}
                  value={searchInput}
                  onChangeText={(text) => setSearchInput(text)}
                  onSubmitEditing={handleSearch}
                />
                <TouchableOpacity onPress={handleSearch} style={styles.iconButton}>
                  <SearchIcon fill={'#0F3F4F'} />
                </TouchableOpacity>
              </>
            ) : (
              <TouchableOpacity onPress={handlePress} style={[styles.iconButton]}>
                <SearchIcon fill={'#0F3F4F'} />
              </TouchableOpacity>
            )}
          </Animated.View>

          <TouchableOpacity
            style={[styles.cornerButton, styles.bottomButton, styles.bottomLeftButton]}
            onPress={() => {
              setIsFilterVisible(true);
              closeCallout();
            }}
          >
            <FilterIcon />
          </TouchableOpacity>

          <TouchableOpacity
            onPress={handleGetLocation}
            style={[styles.cornerButton, styles.bottomButton, styles.bottomRightButton]}
          >
            <LocationIcon />
          </TouchableOpacity>
        </>
      )}

      <SearchModal
        searchVisible={searchVisible}
        handleCloseModal={handleCloseModal}
        handleFindRegion={handleFindRegion}
        index={index}
        searchData={searchData}
        setIndex={setIndex}
        token={token}
      />
      <WarningModal
        type={'unauthorized'}
        isVisible={isWarningModalVisible}
        onClose={() => setIsWarningModalVisible(false)}
      />
      <EditNmModal
        isVisible={isEditModalVisible}
        onClose={() => setIsEditModalVisible(false)}
        modalState={modalState}
        updateModalState={handleModalStateChange}
        updateNM={handleUpdateNM}
      />
      <FilterModal
        isFilterVisible={isFilterVisible}
        setIsFilterVisible={setIsFilterVisible}
        tilesTypes={tilesTypes}
        tilesType={tilesType}
        setTilesType={setTilesType}
        setType={setType}
        userId={userId ? +userId : 0}
        setRegionsFilter={setRegionsFilter}
        setSeriesFilter={setSeriesFilter}
        setShowNomads={setShowNomads}
        showNomads={showNomads}
        isPublicView={false}
        isLogged={token ? true : false}
      />
      <EditModal
        isVisible={isEditSlowModalVisible}
        onClose={() => setIsEditSlowModalVisible(false)}
        item={{ ...userData, country_id: regionData?.id }}
        updateSlow={(id, v, s11, s31, s101) => handleUpdateSlow(id, v, s11, s31, s101)}
      />
      <WarningModal
        type={'success'}
        isVisible={askLocationVisible}
        onClose={() => setAskLocationVisible(false)}
        action={handleAcceptPermission}
        message="To use this feature we need your permission to access your location. If you press OK your system will ask you to approve location sharing with NomadMania app."
      />
      <WarningModal
        type={'success'}
        isVisible={openSettingsVisible}
        onClose={() => setOpenSettingsVisible(false)}
        action={() =>
          Platform.OS === 'ios' ? Linking.openURL('app-settings:') : Linking.openSettings()
        }
        message="NomadMania app needs location permissions to function properly. Open settings?"
      />
    </SafeAreaView>
  );
};

export default MapScreen;
