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

import * as MapLibreRN 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 * as turf from '@turf/turf';
import * as Location from 'expo-location';
import { Image as ExpoImage } from 'expo-image';

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, VECTOR_MAP_HOST } from 'src/constants';
import { NAVIGATION_PAGES } from 'src/types';
import Animated, {
  configureReanimatedLogger,
  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';
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 * as FileSystem from 'expo-file-system/legacy';

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 {
  usePostGetSettingsQuery,
  usePostGetUsersCountQuery,
  usePostGetUsersLocationFilteredMutation,
  usePostGetUsersLocationQuery,
  usePostUpdateLocationMutation
} from '@api/location';
import UserItem from './UserItem';
import { useConnection } from 'src/contexts/ConnectionContext';

import TravelsIcon from 'assets/icons/bottom-navigation/globe-solid.svg';
import SeriesIcon from 'assets/icons/travels-section/series.svg';
import NomadsIcon from 'assets/icons/bottom-navigation/travellers.svg';
import { useBottomTabBarHeight } from '@react-navigation/bottom-tabs';
import MapButton from 'src/components/MapButton';
import { useAvatarStore } from 'src/stores/avatarVersionStore';
import _ from 'lodash';
import ScaleBar from 'src/components/ScaleBar';
import MessagesDot from 'src/components/MessagesDot';
import {
  restartBackgroundLocationUpdates,
  startBackgroundLocationUpdates,
  stopBackgroundLocationUpdates
} from 'src/utils/backgroundLocation';
import { SheetManager } from 'react-native-actions-sheet';
import MultipleSeriesModal from './MultipleSeriesModal';
import { useSubscription } from 'src/screens/OfflineMapsScreen/useSubscription';

configureReanimatedLogger({
  strict: false
});

const clusteredUsersIcon = require('assets/icons/icon-clustered-users.png');
const defaultUserAvatar = require('assets/icon-user-share-location-solid.png');
const logo = require('assets/logo-world.png');
const defaultSeriesIcon = require('assets/series-default.png');

MapLibreRN.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, 0)'
  },
  filter: generateFilter([]),
  maxzoom: 10
};

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, 0)'
  },
  filter: generateFilter([]),
  maxzoom: 10
};

let dare_visited = {
  id: 'dare_visited',
  type: 'fill',
  source: 'dare',
  'source-layer': 'dare',
  style: {
    fillColor: 'rgba(255, 126, 0, 0.6)',
    fillOutlineColor: 'rgba(255, 126, 0, 0)'
  },
  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, 0)'
  },
  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, 0)'
  },
  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, 0)'
  },
  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)'
  },
  maxzoom: 12
};

let selected_region_outline = {
  id: 'selected_region_outline',
  type: 'line',
  source: 'regions',
  'source-layer': 'regions',
  style: {
    lineColor: '#ED9334',
    lineTranslate: [0, 0],
    lineTranslateAnchor: 'map',
    lineWidth: ['interpolate', ['linear'], ['zoom'], 0, 2, 4, 3, 5, 4, 12, 5]
  },
  maxzoom: 12
};

let series_layer = {
  id: 'series_layer',
  type: 'symbol',
  source: 'nomadmania_series',
  'source-layer': 'series',
  minzoom: 6,
  maxzoom: 60,
  layout: {
    'symbol-spacing': 1,
    'icon-image': '{series_id}',
    'icon-size': 0.15,
    'icon-allow-overlap': true,
    'icon-ignore-placement': true,
    'text-anchor': 'top',
    'text-field': '{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': false,
    'text-allow-overlap': false
  },
  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',
  minzoom: 6,
  maxzoom: 60,
  layout: {
    'symbol-spacing': 1,
    'icon-image': '{series_id}v',
    'icon-size': 0.15,
    'icon-allow-overlap': true,
    'icon-ignore-placement': true,
    'text-anchor': 'top',
    'text-field': '{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': false,
    'text-allow-overlap': false
  },
  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 ICONS_DIR = FileSystem.documentDirectory + 'series_icons/';

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

  const [isConnected, setIsConnected] = useState<boolean>(true);
  const netInfo = useConnection();
  const { avatarVersion } = useAvatarStore();

  const { data: usersOnMapCount } = usePostGetUsersCountQuery(token, !!token && isConnected);
  const { data: regionsList } = useGetListRegionsQuery(isConnected);
  const { data: countriesList } = useGetListCountriesQuery(isConnected);
  const { data: dareList } = useGetListDareQuery(isConnected);

  const [usersCount, setUsersCount] = useState(0);

  const [tilesType, setTilesType] = useState({ label: 'NM regions', value: 0 });
  const tilesTypes = [
    { label: 'Blank', value: -1 },
    { label: 'NM regions', value: 0 },
    { label: 'UN countries', value: 1 },
    { label: 'DARE places', value: 2 }
  ];
  const [type, setType] = useState<'regions' | 'countries' | 'dare' | 'blank'>('regions');
  const [seriesFilter, setSeriesFilter] = useState<any>({
    visible: true,
    groups: [],
    applied: false,
    status: -1
  });
  const [regionsFilter, setRegionsFilter] = useState<any>({
    visitedLabel: 'by',
    year: moment().year()
  });
  const [nomadsFilter, setNomadsFilter] = useState<any>({
    friends: 0,
    trusted: 0,
    countries: []
  });
  const [showNomads, setShowNomads] = useState(
    (storage.get('showNomads', StoreType.BOOLEAN) as boolean) ?? false
  );
  const { data: locationSettings, refetch } = usePostGetSettingsQuery(
    token,
    !!token && isConnected
  );
  const { mutateAsync: updateLocation } = usePostUpdateLocationMutation();
  const [forceRefetch, setForceRefetch] = useState(0);
  const { data: visitedRegionIds, refetch: refetchVisitedRegions } =
    usePostGetVisitedRegionsIdsQuery(
      token,
      regionsFilter.visitedLabel,
      regionsFilter.year,
      +userId,
      type === 'regions' && !!userId && isConnected,
      forceRefetch
    );
  const { data: visitedCountryIds, refetch: refetchVisitedCountries } =
    usePostGetVisitedCountriesIdsQuery(
      token,
      regionsFilter.visitedLabel,
      regionsFilter.year,
      +userId,
      type === 'countries' && !!userId && isConnected
    );
  const { data: visitedDareIds, refetch: refetchVisitedDare } = usePostGetVisitedDareIdsQuery(
    token,
    +userId,
    type === 'dare' && !!userId && isConnected
  );
  const { data: visitedSeriesIds } = usePostGetVisitedSeriesIdsQuery(
    token,
    !!userId && isConnected
  );
  const { data: seriesIcons } = useGetIconsQuery(isConnected);
  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<string | null>(null);
  const [isLocationLoading, setIsLocationLoading] = useState(false);

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

  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, refetch: refetchUsersLocation } = usePostGetUsersLocationQuery(
    token,
    !!token && showNomads && Boolean(location) && isConnected
  );
  const { mutateAsync: getLocationFiltered } = usePostGetUsersLocationFilteredMutation();
  const [selectedUser, setSelectedUser] = useState<any>(null);
  const [zoom, setZoom] = useState(0);
  const [center, setCenter] = useState<number[] | null>(null);
  const [isZooming, setIsZooming] = useState(true);
  const hideTimer = useRef<ReturnType<typeof setTimeout> | null>(null);
  const [renderCamera, setRenderCamera] = useState(Platform.OS === 'ios');
  const isAnimatingRef = useRef(false);
  const animationTimeoutRef = useRef<NodeJS.Timeout | null>(null);

  const [markerCoords, setMarkerCoords] = useState<any>(null);
  const [refreshInterval, setRefreshInterval] = useState(0);

  const isSmallScreen = Dimensions.get('window').width < 383;
  const processedImages = useRef(new Set<string>());

  const [didFinishLoadingStyle, setDidFinishLoadingStyle] = useState(false);

  const { isPremium, loading } = useSubscription();

  useEffect(() => {
    if (netInfo && netInfo.isConnected !== null) {
      setIsConnected(netInfo.isConnected);
    }
  }, [netInfo]);

  useEffect(() => {
    if (showNomads) {
      refetchUsersLocation();
    }
  }, [showNomads]);

  useEffect(() => {
    if (usersLocation && usersLocation.geojson && showNomads) {
      const filteredNomads: GeoJSON.FeatureCollection = {
        type: 'FeatureCollection',
        features: usersLocation.geojson.features.filter(
          (feature: GeoJSON.Feature) => feature.properties?.id !== +userId
        )
      };

      if (!nomads || JSON.stringify(filteredNomads) !== JSON.stringify(nomads)) {
        setNomads(filteredNomads);
      }
      if (usersOnMapCount && usersOnMapCount.count) {
        setUsersCount(usersOnMapCount.count);
      }
    }
  }, [usersLocation, showNomads, refreshInterval]);

  useEffect(() => {
    if (
      usersOnMapCount &&
      usersOnMapCount.count &&
      !nomadsFilter.friends &&
      !nomadsFilter.countries?.length
    ) {
      setUsersCount(usersOnMapCount.count);
    }
  }, [usersOnMapCount]);

  useEffect(() => {
    const loadCachedIcons = async () => {
      try {
        const dirInfo = await FileSystem.getInfoAsync(ICONS_DIR);
        if (!dirInfo.exists) return;

        const files = await FileSystem.readDirectoryAsync(ICONS_DIR);
        const cachedImages: Record<string, { uri: string }> = {};

        files.forEach((fileName) => {
          if (!fileName.endsWith('.png')) return;

          const key = fileName.replace('.png', '');
          cachedImages[key] = {
            uri: ICONS_DIR + fileName
          };

          processedImages.current.add(key);
        });

        setImages((prev: any) => ({ ...prev, ...cachedImages }));
      } catch (e) {
        console.warn('Error loading cached icons:', e);
      }
    };

    didFinishLoadingStyle && loadCachedIcons();
  }, [didFinishLoadingStyle]);

  useEffect(() => {
    if (!seriesIcons || !didFinishLoadingStyle) return;

    const updateCacheFromAPI = async () => {
      const loadedImages: Record<string, { uri: string }> = {};

      const dirInfo = await FileSystem.getInfoAsync(ICONS_DIR);
      if (!dirInfo.exists) {
        await FileSystem.makeDirectoryAsync(ICONS_DIR, { intermediates: true });
      }

      const promises = seriesIcons.data.map(async (icon) => {
        const id = icon.id?.toString();
        if (!id || processedImages.current.has(id)) return;

        const imgUrl = `${API_HOST}/static/img/series_new2_small/${icon.new_icon_png}`;
        const imgVisitedUrl = `${API_HOST}/static/img/series_new2_small/${icon.new_icon_visited_png}`;

        const localPath = `${ICONS_DIR}${id}.png`;
        const localPathVisited = `${ICONS_DIR}${id}v.png`;

        const [imgInfo, visitedInfo] = await Promise.all([
          FileSystem.getInfoAsync(localPath),
          FileSystem.getInfoAsync(localPathVisited)
        ]);

        try {
          if (!imgInfo.exists) {
            await FileSystem.downloadAsync(imgUrl, localPath);
          }
          if (!visitedInfo.exists) {
            await FileSystem.downloadAsync(imgVisitedUrl, localPathVisited);
          }
        } catch (e) {
          console.warn(`Download failed for ${id}:`, e);
          return;
        }

        processedImages.current.add(id);
        processedImages.current.add(`${id}v`);

        loadedImages[id] = { uri: localPath };
        loadedImages[`${id}v`] = { uri: localPathVisited };
      });

      await Promise.all(promises);
      setImages((prev: any) => ({ ...prev, ...loadedImages }));
    };

    updateCacheFromAPI();
  }, [seriesIcons, didFinishLoadingStyle]);

  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;
    const storageShowNomads = storage.get('showNomads', StoreType.BOOLEAN) as boolean;
    if (savedFilterSettings) {
      const filterSettings = JSON.parse(savedFilterSettings);
      setTilesType(filterSettings.tilesType);
      setType(filterSettings.type);
      setRegionsFilter({
        visitedLabel:
          filterSettings.selectedVisible?.value && filterSettings.selectedVisible.value === 1
            ? 'in'
            : 'by',
        year: filterSettings.selectedYear?.value ?? moment().year()
      });
      setShowNomads(storageShowNomads ?? false);
      setNomadsFilter({
        friends: filterSettings.nomadsFilter ? filterSettings.nomadsFilter.friends : 0,
        trusted: filterSettings.nomadsFilter ? filterSettings.nomadsFilter.trusted : 0,
        countries: filterSettings.nomadsFilter ? filterSettings.nomadsFilter.countries : undefined
      });
      setSeriesFilter(filterSettings.seriesFilter);
    }
  }, []);

  useFocusEffect(
    useCallback(() => {
      if (token) {
        setForceRefetch((prev) => prev + 1);
        refetchVisitedCountries();
        refetchVisitedDare();
      }
    }, [navigation, token])
  );

  useEffect(() => {
    if (visitedRegionIds) {
      setRegionsVisited(visitedRegionIds.ids);
      storage.set('visitedRegions', JSON.stringify(visitedRegionIds.ids));
    } else {
      const storedVisited = storage.get('visitedRegions', StoreType.STRING) as string;
      setRegionsVisited(storedVisited ? JSON.parse(storedVisited) : []);
    }
  }, [visitedRegionIds]);

  useEffect(() => {
    if (visitedCountryIds) {
      setCountriesVisited(visitedCountryIds.ids);
      storage.set('visitedCountries', JSON.stringify(visitedCountryIds.ids));
    } else {
      const storedVisited = storage.get('visitedCountries', StoreType.STRING) as string;
      setCountriesVisited(storedVisited ? JSON.parse(storedVisited) : []);
    }
  }, [visitedCountryIds]);

  useEffect(() => {
    if (visitedDareIds) {
      setDareVisited(visitedDareIds.ids);
      storage.set('visitedDares', JSON.stringify(visitedDareIds.ids));
    } else {
      const storedVisited = storage.get('visitedDares', StoreType.STRING) as string;
      setDareVisited(storedVisited ? JSON.parse(storedVisited) : []);
    }
  }, [visitedDareIds]);

  useEffect(() => {
    if (visitedSeriesIds && token) {
      setSeriesVisited(visitedSeriesIds.ids);
      storage.set('visitedSeries', JSON.stringify(visitedSeriesIds.ids));
    } else {
      const storedVisited = storage.get('visitedSeries', StoreType.STRING) as string;
      setSeriesVisited(storedVisited ? JSON.parse(storedVisited) : []);
    }
  }, [visitedSeriesIds]);

  useEffect(() => {
    if (regionsVisited && regionsVisited.length) {
      setRegionsVisitedFilter(generateFilter(regionsVisited));
    } else {
      setRegionsVisitedFilter(['==', 'id', -1]);
    }
  }, [regionsVisited]);

  useEffect(() => {
    if (countriesVisited && countriesVisited.length) {
      setCountriesVisitedFilter(generateFilter(countriesVisited));
    } else {
      setCountriesVisitedFilter(['==', 'id', -1]);
    }
  }, [countriesVisited]);

  useEffect(() => {
    if (dareVisited && dareVisited.length) {
      setDareVisitedFilter(generateFilter(dareVisited));
    } else {
      setDareVisitedFilter(['==', 'id', -1]);
    }
  }, [dareVisited]);

  useEffect(() => {
    if (loading) return;

    if (
      !isPremium ||
      !token ||
      showNomads ||
      (!nomadsFilter.friends && !nomadsFilter.countries?.length)
    )
      return;
    const countriesFilter = nomadsFilter.countries
      ? nomadsFilter.countries.map((country: any) => country.country)
      : [];

    getLocationFiltered(
      {
        token,
        friends: nomadsFilter.friends,
        trusted: nomadsFilter.trusted,
        countries: nomadsFilter.countries ? JSON.stringify(countriesFilter) : undefined
      },
      {
        onSuccess: (data) => {
          if (data && data?.geojson) {
            setUsersCount(data.geojson.features?.length);
            const filteredNomads: GeoJSON.FeatureCollection = {
              type: 'FeatureCollection',
              features: data.geojson.features.filter(
                (feature: GeoJSON.Feature) => feature.properties?.id !== +userId
              )
            };

            if (!nomads || JSON.stringify(filteredNomads) !== JSON.stringify(nomads)) {
              setNomads(filteredNomads);
            }
          } else {
            setNomads(null);
          }
        },
        onError: (error) => {
          console.error('Error fetching filtered users location:', error);
        }
      }
    );
  }, [nomadsFilter, loading]);

  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?.lon && route.params?.lat) {
      setMarkerCoords([route.params.lon, route.params.lat]);
      const timeoutId = setTimeout(() => {
        if (cameraRef.current) {
          cameraController.setCamera({
            centerCoordinate: [route.params?.lon, route.params?.lat],
            zoomLevel: 15,
            animationDuration: 800,
            animationMode: 'flyTo'
          });
        } else {
          console.warn('Camera ref is not available.');
        }
      }, 800);

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

  useFocusEffect(
    useCallback(() => {
      if (token) {
        refetch();
      }
    }, [])
  );

  useEffect(() => {
    if (refreshInterval > 0 && showNomads) {
      const intervalId = setInterval(() => {
        refetchUsersLocation();
      }, refreshInterval);

      return () => clearInterval(intervalId);
    }
  }, [refreshInterval, showNomads]);

  useEffect(() => {
    (async () => {
      let { status } = await Location.getForegroundPermissionsAsync();
      const isServicesEnabled = await Location.hasServicesEnabledAsync();

      if (locationSettings && locationSettings.sharing_refresh_interval) {
        setRefreshInterval(locationSettings.sharing_refresh_interval * 1000);
      }

      if (
        status !== 'granted' ||
        !token ||
        (locationSettings && locationSettings.sharing === 0) ||
        !isServicesEnabled
      ) {
        setShowNomads(false);
        storage.set('showNomads', false);
        await stopBackgroundLocationUpdates();
        return;
      }

      const bgStatus = await Location.getBackgroundPermissionsAsync();
      if (bgStatus.status !== 'granted') {
        // const { status } = await requestBackgroundPermissionSafe();
        // if (status === Location.PermissionStatus.GRANTED) {
        //   await startBackgroundLocationUpdates();
        // } else {
        await stopBackgroundLocationUpdates();
        // }
      } else {
        // await startBackgroundLocationUpdates();
        await restartBackgroundLocationUpdates();
      }

      try {
        let currentLocation = await Location.getCurrentPositionAsync({
          accuracy: Location.Accuracy.Balanced
        });
        setLocation(currentLocation.coords);

        if (locationSettings && locationSettings.sharing === 1 && token) {
          updateLocation({
            token,
            lat: currentLocation.coords.latitude,
            lng: currentLocation.coords.longitude
          });

          showNomads && refetchUsersLocation();
        }
      } catch (error) {
        console.error('Error fetching user location:', error);
      }
    })();
  }, [locationSettings]);

  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<MapLibreRN.MapViewRef>(null);
  const cameraRef = useRef<MapLibreRN.CameraRef>(null);
  const shapeSourceRef = useRef<MapLibreRN.ShapeSourceRef>(null);

  const cameraController = {
    setCamera: useCallback((config: any) => {
      isAnimatingRef.current = true;

      if (animationTimeoutRef.current) {
        clearTimeout(animationTimeoutRef.current);
      }

      if (Platform.OS === 'android') {
        setRenderCamera(true);

        requestAnimationFrame(() => {
          cameraRef.current?.setCamera(config);
        });

        animationTimeoutRef.current = setTimeout(
          () => {
            isAnimatingRef.current = false;
            setRenderCamera(false);
          },
          (config.animationDuration || 1000) + 200
        );
      } else {
        cameraRef.current?.setCamera(config);

        animationTimeoutRef.current = setTimeout(
          () => {
            isAnimatingRef.current = false;
          },
          (config.animationDuration || 1000) + 100
        );
      }
    }, []),

    fitBounds: useCallback((ne: number[], sw: number[], padding: number[], duration: number) => {
      isAnimatingRef.current = true;

      if (animationTimeoutRef.current) {
        clearTimeout(animationTimeoutRef.current);
      }

      if (Platform.OS === 'android') {
        setRenderCamera(true);

        requestAnimationFrame(() => {
          cameraRef.current?.fitBounds(ne, sw, padding, duration);
        });

        animationTimeoutRef.current = setTimeout(() => {
          isAnimatingRef.current = false;
          setRenderCamera(false);
        }, duration + 200);
      } else {
        cameraRef.current?.fitBounds(ne, sw, padding, duration);

        animationTimeoutRef.current = setTimeout(() => {
          isAnimatingRef.current = false;
        }, duration + 100);
      }
    }, []),

    flyTo: useCallback((coordinates: number[], duration: number = 1000) => {
      isAnimatingRef.current = true;

      if (animationTimeoutRef.current) {
        clearTimeout(animationTimeoutRef.current);
      }

      if (Platform.OS === 'android') {
        setRenderCamera(true);

        requestAnimationFrame(() => {
          cameraRef.current?.flyTo(coordinates, duration);
        });

        animationTimeoutRef.current = setTimeout(() => {
          isAnimatingRef.current = false;
          setRenderCamera(false);
        }, duration + 200);
      } else {
        cameraRef.current?.flyTo(coordinates, duration);

        animationTimeoutRef.current = setTimeout(() => {
          isAnimatingRef.current = false;
        }, duration + 100);
      }
    }, []),

    moveTo: useCallback((coordinates: number[], duration: number = 0) => {
      isAnimatingRef.current = true;

      if (animationTimeoutRef.current) {
        clearTimeout(animationTimeoutRef.current);
      }

      if (Platform.OS === 'android') {
        setRenderCamera(true);

        requestAnimationFrame(() => {
          cameraRef.current?.moveTo(coordinates, duration);
        });

        animationTimeoutRef.current = setTimeout(() => {
          isAnimatingRef.current = false;
          setRenderCamera(false);
        }, duration + 200);
      } else {
        cameraRef.current?.moveTo(coordinates, duration);

        animationTimeoutRef.current = setTimeout(() => {
          isAnimatingRef.current = false;
        }, duration + 100);
      }
    }, []),

    zoomTo: useCallback((zoomLevel: number, duration: number = 1000) => {
      isAnimatingRef.current = true;

      if (animationTimeoutRef.current) {
        clearTimeout(animationTimeoutRef.current);
      }

      if (Platform.OS === 'android') {
        setRenderCamera(true);

        requestAnimationFrame(() => {
          cameraRef.current?.zoomTo(zoomLevel, duration);
        });

        animationTimeoutRef.current = setTimeout(() => {
          isAnimatingRef.current = false;
          setRenderCamera(false);
        }, duration + 200);
      } else {
        cameraRef.current?.zoomTo(zoomLevel, duration);

        animationTimeoutRef.current = setTimeout(() => {
          isAnimatingRef.current = false;
        }, duration + 100);
      }
    }, [])
  };

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

  const requestBackgroundPermissionSafe = async () => {
    await new Promise((resolve) => setTimeout(resolve, 300));
    return await Location.requestBackgroundPermissionsAsync();
  };

  const handlePress = () => {
    if (isExpanded) {
      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) {
      const timeoutId = setTimeout(() => {
        if (cameraRef.current) {
          cameraController.setCamera({
            centerCoordinate: [initialRegion.longitude, initialRegion.latitude],
            zoomLevel: Math.log2(360 / initialRegion.latitudeDelta),
            animationDuration: 500,
            animationMode: 'flyTo'
          });
        } else {
          console.warn('Camera ref is not available.');
        }
      }, 500);

      return () => clearTimeout(timeoutId);
    }
  }, [initialRegion]);

  const handleMapChange = async () => {
    if (!mapRef.current || isAnimatingRef.current) return;
    if (hideTimer.current) clearTimeout(hideTimer.current);

    setIsZooming(true);

    const newZoom = await mapRef.current.getZoom();
    const newCenter = await mapRef.current.getCenter();

    setZoom((prevZoom) => {
      if (prevZoom !== newZoom) return newZoom;
      return prevZoom;
    });

    setCenter((prevCenter) => {
      if (!prevCenter || prevCenter[0] !== newCenter[0] || prevCenter[0] !== newCenter[0]) {
        return newCenter;
      }
      return prevCenter;
    });
  };

  useEffect(() => {
    return () => {
      if (animationTimeoutRef.current) {
        clearTimeout(animationTimeoutRef.current);
      }
    };
  }, []);

  const onMapPress = async (event: any) => {
    if (!mapRef.current) return;
    if (selectedMarker || selectedUser) {
      closeCallout();
      return;
    }
    if (type === 'blank') 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 && regionsList.data) {
            const region = regionsList.data.find((region) => region.id === +foundRegion);
            if (region) {
              const bounds = turf.bbox(region.bbox);
              cameraController.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 && countriesList.data) {
            const region = countriesList.data.find((region) => region.id === +foundRegion);
            if (region) {
              const bounds = turf.bbox(region.bbox);
              cameraController.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 && dareList.data) {
            const region = dareList.data.find((region) => region.id === +foundRegion);
            if (region) {
              const bounds = turf.bbox(region.bbox);
              cameraController.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, any>) => {
    hideTimer.current = setTimeout(() => {
      setIsZooming(false);
    }, 2000);
    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 () => {
    setIsLocationLoading(true);
    try {
      let { status, canAskAgain } = await Location.getForegroundPermissionsAsync();
      const isServicesEnabled = await Location.hasServicesEnabledAsync();

      if (status === 'granted' && isServicesEnabled) {
        const bgStatus = await Location.getBackgroundPermissionsAsync();
        if (bgStatus.status !== 'granted') {
          // const { status } = await requestBackgroundPermissionSafe();
          // if (status === Location.PermissionStatus.GRANTED) {
          //   await startBackgroundLocationUpdates();
          // } else {
          await stopBackgroundLocationUpdates();
          // }
        } else {
          await startBackgroundLocationUpdates();
        }

        await getLocation();
      } else if (!canAskAgain || !isServicesEnabled) {
        setOpenSettingsVisible(true);
      } else {
        setAskLocationVisible(true);
      }
    } finally {
      setIsLocationLoading(false);
    }
  };

  const getLocation = async () => {
    try {
      let currentLocation = await Location.getCurrentPositionAsync({
        accuracy: Platform.OS === 'ios' ? Location.Accuracy.Balanced : Location.Accuracy.Low
      });
      setLocation(currentLocation.coords);

      if (currentLocation.coords) {
        cameraController.flyTo(
          [currentLocation.coords.longitude, currentLocation.coords.latitude],
          1000
        );
      }

      if (locationSettings && locationSettings.sharing === 1 && token) {
        updateLocation({
          token,
          lat: currentLocation.coords.latitude,
          lng: currentLocation.coords.longitude
        });

        showNomads && refetchUsersLocation();
      }

      handleClosePopup();
    } catch (error) {
      console.error('Error fetching user location:', error);
    }
  };

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

    if (status === 'granted' && isServicesEnabled) {
      getLocation();
    } else if (!canAskAgain || !isServicesEnabled) {
      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);
    navigation.navigate(NAVIGATION_PAGES.EDIT_NM_DATA, { regionId: regionData?.id });
  };

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

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

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

  const handleRegionData = async (regionData: any, avatars: string[]) => {
    if (!regionData) {
      await refreshDatabases();
    }
    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 && regionsList.data) {
          const region = regionsList.data.find((region) => region.id === +id);
          if (region) {
            const bounds = turf.bbox(region.bbox);
            cameraController.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 && countriesList.data) {
          const region = countriesList.data.find((region) => region.id === +id);
          if (region) {
            const bounds = turf.bbox(region.bbox);
            cameraController.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 && dareList.data) {
          const region = dareList.data.find((region) => region.id === +id);
          if (region) {
            const bounds = turf.bbox(region.bbox);
            cameraController.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) {
      if (features.length > 1) {
        const markers = features
          .map((f: any) => {
            const markerCoordinates = f.geometry.coordinates;
            if (!markerCoordinates) return null;

            return {
              coordinates: markerCoordinates,
              name: f.properties.name,
              icon: images[f.properties.series_id],
              description: f.properties.description,
              series_name: f.properties.series_name,
              visited: seriesVisited.includes(f.properties.id) ? 1 : 0,
              series_id: f.properties.series_id,
              id: f.properties.id
            };
          })
          .sort((a: any, b: any) => a.visited - b.visited);

        SheetManager.show('multiple-series-modal', {
          payload: {
            markers,
            token,
            toggleSeries,
            setSelectedMarker,
            setIsWarningModalVisible
          } as any
        });

        setSelectedUser(null);
        return;
      }

      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;

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

  const closeCallout = () => {
    setSelectedMarker(null);
    setSelectedUser(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 }));
  };

  const handleUserPress = (event: any) => {
    const selectedFeature = event.features[0];
    const { coordinates } = selectedFeature.geometry;
    const { avatar, first_name, last_name, flag, id, last_seen } = selectedFeature.properties;
    if (selectedFeature) {
      setSelectedUser({
        coordinates,
        avatar: avatar ? { uri: API_HOST + avatar } : logo,
        first_name,
        last_name,
        flag: { uri: API_HOST + flag },
        id,
        last_seen
      });
      setSelectedMarker(null);
    }
  };

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

      <MapLibreRN.MapView
        ref={mapRef}
        style={styles.map}
        mapStyle={VECTOR_MAP_HOST + '/nomadmania-maps2025.json'}
        rotateEnabled={false}
        attributionEnabled={false}
        onPress={onMapPress}
        onRegionDidChange={handleRegionDidChange}
        onRegionWillChange={_.debounce(handleMapChange, 200)}
        onDidFinishLoadingStyle={() => setDidFinishLoadingStyle(true)}
      >
        {/* <MapLibreRN.Images
          images={{
            ...images,
            'default-series-icon': defaultSeriesIcon
          }}
          onImageMissing={(image) => {
            try {
              if (processedImages.current.has(image)) {
                return;
              }

              processedImages.current.add(image);

              setImages((prevImages: any) => ({
                ...prevImages,
                [image]: defaultSeriesIcon
              }));
            } catch (error) {
              console.error('Error in onImageMissing:', error);
            }
          }}
        >
          <View />
        </MapLibreRN.Images> */}

        {markerCoords && (
          <MapLibreRN.PointAnnotation id="marker" coordinate={markerCoords}>
            <View
              style={{
                height: 24,
                width: 24,
                backgroundColor: Colors.ORANGE,
                borderRadius: 12,
                borderColor: Colors.WHITE,
                borderWidth: 2
              }}
            />
          </MapLibreRN.PointAnnotation>
        )}

        <>
          <MapLibreRN.LineLayer
            id="nm-regions-line-layer"
            sourceID={regions.source}
            sourceLayerID={regions['source-layer']}
            filter={regions.filter as any}
            maxZoomLevel={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 },
              visibility: type === 'regions' ? 'visible' : 'none'
            }}
            belowLayerID="waterway-name"
          />
          <MapLibreRN.FillLayer
            id={regions.id}
            sourceID={regions.source}
            sourceLayerID={regions['source-layer']}
            filter={regions.filter as any}
            style={{
              ...regions.style,
              visibility: type === 'regions' ? 'visible' : 'none'
            }}
            maxZoomLevel={regions.maxzoom}
            belowLayerID={regions_visited.id}
          />
          <MapLibreRN.FillLayer
            id={regions_visited.id}
            sourceID={regions_visited.source}
            sourceLayerID={regions_visited['source-layer']}
            filter={regionsVisitedFilter as any}
            style={{
              ...regions_visited.style,
              visibility: type === 'regions' ? 'visible' : 'none'
            }}
            maxZoomLevel={regions_visited.maxzoom}
            belowLayerID="waterway-name"
          />
        </>

        <>
          <MapLibreRN.LineLayer
            id="countries-line-layer"
            sourceID={countries.source}
            sourceLayerID={countries['source-layer']}
            filter={countries.filter as any}
            maxZoomLevel={countries.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 },
              visibility: type === 'countries' ? 'visible' : 'none'
            }}
            belowLayerID="waterway-name"
          />
          <MapLibreRN.FillLayer
            id={countries.id}
            sourceID={countries.source}
            sourceLayerID={countries['source-layer']}
            filter={countries.filter as any}
            style={{
              ...countries.style,
              visibility: type === 'countries' ? 'visible' : 'none'
            }}
            maxZoomLevel={countries.maxzoom}
            belowLayerID={countries_visited.id}
          />
          <MapLibreRN.FillLayer
            id={countries_visited.id}
            sourceID={countries_visited.source}
            sourceLayerID={countries_visited['source-layer']}
            filter={countriesVisitedFilter as any}
            style={{
              ...countries_visited.style,
              visibility: type === 'countries' ? 'visible' : 'none'
            }}
            maxZoomLevel={countries_visited.maxzoom}
            belowLayerID="waterway-name"
          />
        </>

        <>
          <MapLibreRN.FillLayer
            id={dare.id}
            sourceID={dare.source}
            sourceLayerID={dare['source-layer']}
            filter={dare.filter as any}
            style={{
              ...dare.style,
              visibility: type === 'dare' ? 'visible' : 'none'
            }}
            maxZoomLevel={dare.maxzoom}
            belowLayerID={dare_visited.id}
          />
          <MapLibreRN.FillLayer
            id={dare_visited.id}
            sourceID={dare_visited.source}
            sourceLayerID={dare_visited['source-layer']}
            filter={dareVisitedFilter as any}
            style={{
              ...dare_visited.style,
              visibility: type === 'dare' ? 'visible' : 'none'
            }}
            maxZoomLevel={dare_visited.maxzoom}
            belowLayerID="waterway-name"
          />
        </>

        {selectedRegion && type && (
          <>
            <MapLibreRN.FillLayer
              id={selected_region.id}
              sourceID={type}
              sourceLayerID={type}
              filter={['==', 'id', selectedRegion]}
              style={selected_region.style}
              maxZoomLevel={selected_region.maxzoom}
              belowLayerID="waterway-name"
            />
            <MapLibreRN.LineLayer
              id={selected_region_outline.id}
              sourceID={type}
              sourceLayerID={type}
              filter={['==', 'id', selectedRegion]}
              style={selected_region_outline.style as any}
              maxZoomLevel={selected_region_outline.maxzoom}
              belowLayerID="waterway-name"
            />
          </>
        )}

        <MapLibreRN.VectorSource
          id="nomadmania_series"
          tileUrlTemplates={[VECTOR_MAP_HOST + '/tiles/series/{z}/{x}/{y}.pbf']}
          onPress={handleMarkerPress}
        >
          {seriesFilter.status !== 1
            ? (() => {
                try {
                  return (
                    <MapLibreRN.SymbolLayer
                      id={series_layer.id}
                      sourceID={series_layer.source}
                      sourceLayerID={series_layer['source-layer']}
                      aboveLayerID={Platform.OS === 'android' ? 'waterway-name' : undefined}
                      filter={seriesNotVisitedFilter as any}
                      minZoomLevel={series_layer.minzoom}
                      maxZoomLevel={series_layer.maxzoom}
                      style={{
                        symbolSpacing: 1,
                        iconImage: '{series_id}',
                        iconAllowOverlap: true,
                        iconIgnorePlacement: true,
                        visibility: 'visible',
                        iconColor: '#666',
                        iconOpacity: 1,
                        iconHaloColor: '#ffffff',
                        iconHaloWidth: 1,
                        iconHaloBlur: 0.5
                      }}
                    />
                  );
                } catch (error) {
                  console.warn('SymbolLayer render error:', error);
                  return null;
                }
              })()
            : null}

          {seriesFilter.status !== 0
            ? (() => {
                try {
                  return (
                    <MapLibreRN.SymbolLayer
                      id={series_visited.id}
                      sourceID={series_visited.source}
                      sourceLayerID={series_visited['source-layer']}
                      aboveLayerID={Platform.OS === 'android' ? 'waterway-name' : undefined}
                      filter={seriesVisitedFilter as any}
                      minZoomLevel={series_visited.minzoom}
                      maxZoomLevel={series_visited.maxzoom}
                      style={{
                        symbolSpacing: 1,
                        iconImage: '{series_id}v',
                        iconAllowOverlap: true,
                        iconIgnorePlacement: true,
                        visibility: 'visible',
                        iconColor: '#666',
                        iconOpacity: 1,
                        iconHaloColor: '#ffffff',
                        iconHaloWidth: 1,
                        iconHaloBlur: 0.5
                      }}
                    />
                  );
                } catch (error) {
                  console.warn('SymbolLayer render error:', error);
                  return null;
                }
              })()
            : null}
        </MapLibreRN.VectorSource>

        {nomads && (showNomads || nomadsFilter.friends || nomadsFilter.countries?.length) ? (
          <MapLibreRN.ShapeSource
            ref={shapeSourceRef}
            tolerance={20}
            id="nomads"
            shape={nomads}
            onPress={async (event) => {
              const feature = event.features[0];
              const isCluster = feature.properties?.cluster;

              if (isCluster) {
                const clusterCoordinates = (feature.geometry as GeoJSON.Point).coordinates;

                const zoom = await shapeSourceRef.current?.getClusterExpansionZoom(
                  feature as GeoJSON.Feature<GeoJSON.Geometry>
                );
                const newZoom = zoom ?? 2;

                cameraController.setCamera({
                  centerCoordinate: clusterCoordinates,
                  zoomLevel: newZoom,
                  animationDuration: 500,
                  animationMode: 'flyTo'
                });
                return;
              } else {
                handleUserPress(event);
              }
            }}
            cluster={true}
            clusterRadius={50}
          >
            <MapLibreRN.SymbolLayer
              id="nomads_circle"
              filter={['has', 'point_count']}
              aboveLayerID={Platform.OS === 'android' ? 'place-continent' : undefined}
              style={{
                iconImage: clusteredUsersIcon,
                iconSize: [
                  'interpolate',
                  ['linear'],
                  ['get', 'point_count'],
                  0,
                  0.33,
                  10,
                  0.35,
                  20,
                  0.37,
                  50,
                  0.39,
                  75,
                  0.41,
                  100,
                  0.43
                ],
                iconAllowOverlap: true
              }}
            ></MapLibreRN.SymbolLayer>
            <MapLibreRN.SymbolLayer
              id="nomads_count"
              filter={['has', 'point_count']}
              aboveLayerID={Platform.OS === 'android' ? 'nomads_circle' : undefined}
              style={{
                textField: [
                  'case',
                  ['<', ['get', 'point_count'], 1000],
                  ['get', 'point_count'],
                  ['concat', ['/', ['round', ['/', ['get', 'point_count'], 100]], 10], 'k']
                ],
                textFont: ['Noto Sans Bold'],
                textSize: [
                  'interpolate',
                  ['linear'],
                  ['get', 'point_count'],
                  0,
                  13.5,
                  20,
                  14,
                  75,
                  15
                ],
                textColor: '#FFFFFF',
                textAnchor: 'center',
                textOffset: [
                  'interpolate',
                  ['linear'],
                  ['get', 'point_count'],
                  0,
                  ['literal', [0, 0.85]],
                  20,
                  ['literal', [0, 0.92]],
                  75,
                  ['literal', [0, 1]]
                ],
                textAllowOverlap: true
              }}
            />
            <MapLibreRN.SymbolLayer
              id="nomads_symbol"
              filter={['!', ['has', 'point_count']]}
              aboveLayerID={Platform.OS === 'android' ? 'place-continent' : undefined}
              style={{
                iconImage: [
                  'case',
                  ['==', ['get', 'friend'], 1],
                  '02',
                  // ['==', ['get', 'trusted'], 1],
                  // '01',
                  '00'
                ],
                // iconSize: [
                //   'interpolate',
                //   ['linear'],
                //   ['zoom'],
                //   0,
                //   0.24,
                //   5,
                //   0.28,
                //   10,
                //   0.33,
                //   15,
                //   0.38,
                //   20,
                //   0.42
                // ],
                iconAllowOverlap: true
              }}
            ></MapLibreRN.SymbolLayer>
          </MapLibreRN.ShapeSource>
        ) : null}

        {selectedUser && <UserItem marker={selectedUser} />}

        {selectedMarker && (
          <MarkerItem marker={selectedMarker} toggleSeries={toggleSeries} token={token} />
        )}
        {(renderCamera || Platform.OS === 'ios') && (
          <MapLibreRN.Camera ref={cameraRef} followUserLocation={undefined} animationMode="flyTo" />
        )}
        {location && (
          <MapLibreRN.UserLocation
            animated={true}
            showsUserHeadingIndicator={true}
            onPress={async () => {
              const currentZoom = await mapRef.current?.getZoom();
              const newZoom = (currentZoom || 0) + 2;

              cameraController.setCamera({
                centerCoordinate: [location.longitude, location.latitude],
                zoomLevel: newZoom,
                animationDuration: 500,
                animationMode: 'flyTo'
              });
            }}
          >
            {/* to do custom user location */}
          </MapLibreRN.UserLocation>
        )}
      </MapLibreRN.MapView>

      {center ? (
        <ScaleBar
          zoom={zoom}
          latitude={center[1]}
          isVisible={isZooming}
          bottom={tabBarHeight + 80}
        />
      ) : null}

      {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,
              { bottom: tabBarHeight + 20 }
            ]}
          >
            {isLocationLoading ? (
              <ActivityIndicator size="small" color={Colors.DARK_BLUE} />
            ) : (
              <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 + '?v=' + avatarVersion
                    }}
                  />
                ) : (
                  <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>

          <View style={[styles.tabs, { bottom: tabBarHeight + 20 }]}>
            <ScrollView
              horizontal
              showsHorizontalScrollIndicator={false}
              contentContainerStyle={{
                paddingHorizontal: isSmallScreen ? 8 : 12,
                paddingTop: 6,
                gap: isSmallScreen ? 6 : 10,
                flexDirection: 'row'
              }}
            >
              <MapButton
                onPress={() => {
                  try {
                    setIsFilterVisible('regions');
                    closeCallout();
                  } catch (error) {
                    console.error('Error opening filter:', error);
                  }
                }}
                icon={TravelsIcon}
                text={
                  tilesType.value === 0 || tilesType.value === 1
                    ? token
                      ? `${tilesType.value === 0 ? 'NM' : 'UN'} ${regionsFilter.visitedLabel} ${regionsFilter.year}`
                      : `${tilesType.value === 0 ? 'NM' : 'UN'}`
                    : tilesType.value === 2
                      ? 'DARE'
                      : 'Travels'
                }
                active={type !== 'blank'}
              />
              <MapButton
                onPress={() => {
                  try {
                    setIsFilterVisible('series');
                    closeCallout();
                  } catch (error) {
                    console.error('Error opening filter:', error);
                  }
                }}
                icon={SeriesIcon}
                text="Series"
                active={seriesFilter.visible}
              />
              {token ? (
                <MapButton
                  onPress={() => {
                    try {
                      setIsFilterVisible('nomads');
                      closeCallout();
                    } catch (error) {
                      console.error('Error opening filter:', error);
                    }
                  }}
                  icon={NomadsIcon}
                  text="Nomads"
                  active={showNomads || nomadsFilter.friends || nomadsFilter.countries?.length}
                >
                  {usersCount && usersCount > 0 ? (
                    <MessagesDot
                      messagesCount={usersCount}
                      fullNumber={true}
                      right={-10}
                      top={-8}
                    />
                  ) : null}
                </MapButton>
              ) : null}
            </ScrollView>
          </View>

          <TouchableOpacity
            onPress={handleGetLocation}
            style={[
              styles.cornerButton,
              styles.bottomButton,
              styles.bottomRightButton,
              { bottom: tabBarHeight + 20 }
            ]}
          >
            {isLocationLoading ? (
              <ActivityIndicator size="small" color={Colors.DARK_BLUE} />
            ) : (
              <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}
        setNomadsFilter={setNomadsFilter}
        showNomads={showNomads}
        isPublicView={false}
        isLogged={token ? true : false}
        usersOnMapCount={token && usersOnMapCount?.count ? usersOnMapCount.count : null}
        friendsOnTheMapCount={
          token && usersOnMapCount?.friends_count ? usersOnMapCount.friends_count : null
        }
        isConnected={isConnected}
        isPremium={isPremium}
      />
      <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={async () => {
          const isServicesEnabled = await Location.hasServicesEnabledAsync();

          if (!isServicesEnabled) {
            Platform.OS === 'ios'
              ? Linking.openURL('app-settings:')
              : Linking.sendIntent('android.settings.LOCATION_SOURCE_SETTINGS');
          } else {
            Platform.OS === 'ios' ? Linking.openURL('app-settings:') : Linking.openSettings();
          }
        }}
        message="NomadMania app needs location permissions to function properly. Open settings?"
      />
      <MultipleSeriesModal />
    </SafeAreaView>
  );
};

export default MapScreen;
