import {
  Dimensions,
  Linking,
  Platform,
  Text,
  TextInput,
  TouchableOpacity,
  View,
  Image,
  StatusBar,
  ActivityIndicator,
  ScrollView
} from 'react-native';
import React, { useEffect, useRef, useState, useCallback, useMemo } 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 SearchIcon from 'assets/icons/search.svg';
import LocationIcon from 'assets/icons/location.svg';
import CloseSvg from 'assets/icons/close.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 { FileSystem } from 'src/utils';

import moment from 'moment';
import {
  usePostGetVisitedCountriesIdsQuery,
  usePostGetVisitedDareIdsQuery,
  usePostGetVisitedRegionsIdsQuery,
  usePostGetVisitedSeriesIdsQuery
} from '@api/maps';
import FilterModal, { FilterModalRef } 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 { stopBackgroundLocationUpdates } from 'src/utils/backgroundLocation';
import { SheetManager } from 'react-native-actions-sheet';
import MultipleSeriesModal from './MultipleSeriesModal';
import { useSubscription } from 'src/screens/OfflineMapsScreen/useSubscription';
import { point } from '@turf/turf';
import { booleanPointInPolygon } from '@turf/turf';
import { area } from '@turf/turf';

configureReanimatedLogger({
  strict: false
});

const clusteredUsersIcon = require('assets/icons/icon-clustered-users.png');
const logo = require('assets/logo-world.png');

MapLibreRN.Logger.setLogLevel('error');

const isValidNumber = (val: any) => typeof val === 'number' && !isNaN(val) && isFinite(val);

const sanitizeNomadsGeoJSON = (
  collection: GeoJSON.FeatureCollection
): GeoJSON.FeatureCollection => {
  const validFeatures = collection.features.filter((feature) => {
    if (!feature || !feature.geometry || !feature.properties) return false;

    const geom = feature.geometry;
    if (geom.type !== 'Point') return false;

    const coords = (geom as GeoJSON.Point).coordinates;
    if (!Array.isArray(coords) || coords.length < 2) return false;

    const [lng, lat] = coords;
    if (lng == null || lat == null) return false;
    if (!isValidNumber(lng) || !isValidNumber(lat)) return false;
    if (lng < -180 || lng > 180 || lat < -90 || lat > 90) return false;

    return true;
  });

  return { type: 'FeatureCollection', features: validFeatures };
};

const generateFilter = (ids: number[]) => {
  const validIds = ids?.filter(isValidNumber) || [];
  return validIds.length ? ['any', ...validIds.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: 5,
  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: 5,
  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 SERIES_ICON_SIZE = [
  'interpolate',
  ['linear'],
  ['zoom'],
  3,
  0.3,
  4,
  0.36,
  5,
  0.43,
  6,
  0.5,
  7,
  0.57,
  8,
  0.63,
  9,
  0.7,
  10,
  0.77,
  11,
  0.84,
  12,
  0.91,
  13,
  0.98,
  14,
  1.05,
  15,
  1.12,
  16,
  1.18,
  17,
  1.25
] as unknown as number;

const SERIES_CIRCLE_RADIUS = [
  'interpolate',
  ['linear'],
  ['zoom'],
  3,
  5,
  4,
  6,
  5,
  7,
  6,
  8,
  7,
  9,
  8,
  10,
  9,
  11,
  10,
  12,
  11,
  13,
  12,
  14,
  13,
  16,
  14,
  17,
  15,
  18,
  16,
  19,
  17,
  20
] as unknown as number;

const SERIES_CIRCLE_STROKE = [
  'interpolate',
  ['linear'],
  ['zoom'],
  3,
  1,
  7,
  1.5,
  13,
  2,
  17,
  2.5
] as unknown as number;

const SERIES_TEXT_SIZE = [
  'interpolate',
  ['linear'],
  ['zoom'],
  3,
  6,
  4,
  7,
  5,
  8,
  6,
  9,
  7,
  10,
  8,
  10,
  9,
  11,
  10,
  11,
  11,
  12,
  12,
  12,
  13,
  13,
  14,
  13,
  15,
  14,
  16,
  14,
  17,
  15
] as unknown as number;

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,
    labelIds: []
  });
  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,
      forceRefetch
    );
  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 filterModalRef = useRef<FilterModalRef>(null);
  const [isLocationLoading, setIsLocationLoading] = useState(false);
  const [premiumModalVisible, setPremiumModalVisible] = 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 (Platform.OS === 'android') {
      MapLibreRN.setConnected(isConnected);
    }
  }, [isConnected])

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

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

      if (!nomads || filteredNomads.features.length !== nomads.features.length) {
        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?.countries ?? []
      });
      setSeriesFilter(filterSettings.seriesFilter);
    }
  }, []);

  useFocusEffect(
    useCallback(() => {
      if (token) {
        setForceRefetch((prev) => prev + 1);
        refetchVisitedCountries();
        refetchVisitedDare();
      }
      if (userData && type === 'regions') {
        handleClosePopup();
      }
    }, [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: any) => {
          if (data && data?.geojson) {
            setUsersCount(data.geojson.features?.length);
            const rawFiltered: GeoJSON.FeatureCollection = {
              type: 'FeatureCollection',
              features: data.geojson.features.filter(
                (feature: GeoJSON.Feature) => feature.properties?.id !== +userId
              )
            };
            const filteredNomads = sanitizeNomadsGeoJSON(rawFiltered);

            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]);

  // const isMustModeEnabled = useMemo(
  //   () => seriesFilter.visible && seriesFilter.groups?.includes(-1),
  //   [seriesFilter]
  // );

  // const isGroupEnabled = useCallback(
  //   (groupId: number) => {
  //     if (!seriesFilter.visible) return false;
  //     if (!seriesFilter.groups?.length) return true;
  //     return seriesFilter.groups.includes(groupId);
  //   },
  //   [seriesFilter]
  // );

  // const seriesGroups = useMemo(() => {
  //   if (!seriesIcons?.data) return [];
  //   return seriesIcons.data.map((icon) => ({
  //     id: icon.id
  //   }));
  // }, [seriesIcons]);

  const seriesTextField = useMemo(() => {
    const ids = seriesFilter.labelIds;
    if (!ids) return ['step', ['zoom'], '', 9, ['get', 'name']] as unknown as string;
    if (ids.length === 0) return '';
    return [
      'step',
      ['zoom'],
      '',
      9,
      ['case', ['in', ['get', 'series_id'], ['literal', ids]], ['get', 'name'], '']
    ] as unknown as string;
  }, [seriesFilter.labelIds]);

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

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

  useEffect(() => {
    if (isValidNumber(route.params?.lon) && isValidNumber(route.params?.lat)) {
      setMarkerCoords([route.params.lon, route.params.lat]);
      const timeoutId = setTimeout(() => {
        cameraController.setCamera({
          centerCoordinate: [route.params?.lon, route.params?.lat],
          zoomLevel: 15,
          animationDuration: 800,
          animationMode: 'flyTo'
        });
      }, 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 androidCancelRef = useRef<null | (() => void)>(null);

  const setCameraAndroid = (config: any) => {
    androidCancelRef.current?.();
    androidCancelRef.current = null;

    setRenderCamera(true);

    let frame = 0;
    let cancelled = false;
    const startedAt = Date.now();
    const MAX_WAIT_MS = 1500;

    const cleanup = () => {
      cancelled = true;
      if (frame) cancelAnimationFrame(frame);
      isAnimatingRef.current = false;
      setRenderCamera(false);
    };

    androidCancelRef.current = cleanup;

    const trySetCamera = () => {
      if (cancelled) return;

      if (cameraRef.current) {
        cameraRef.current.setCamera(config);

        const duration = (config.animationDuration || 1000) + 200;
        animationTimeoutRef.current && clearTimeout(animationTimeoutRef.current);
        animationTimeoutRef.current = setTimeout(() => {
          if (!cancelled) cleanup();
        }, duration);

        return;
      }

      if (Date.now() - startedAt > MAX_WAIT_MS) {
        cleanup();
        return;
      }

      frame = requestAnimationFrame(trySetCamera);
    };

    frame = requestAnimationFrame(trySetCamera);
  };

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

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

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

        setCameraAndroid(config);
        return;
      } 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(() => {
    return () => {
      androidCancelRef.current?.();
      if (animationTimeoutRef.current) clearTimeout(animationTimeoutRef.current);
    };
  }, []);

  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 &&
      isValidNumber(initialRegion.longitude) &&
      isValidNumber(initialRegion.latitude)
    ) {
      const timeoutId = setTimeout(() => {
        cameraController.setCamera({
          centerCoordinate: [initialRegion.longitude, initialRegion.latitude],
          zoomLevel:
            isValidNumber(initialRegion.latitudeDelta) && initialRegion.latitudeDelta > 0
              ? Math.log2(360 / initialRegion.latitudeDelta)
              : 0,
          animationDuration: 500,
          animationMode: 'flyTo'
        });
      }, 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;

    // const { screenPointX, screenPointY } = event.properties;
    // const seriesLayerIds = seriesGroups.flatMap((g) => [
    //   `series-${g.id}-unvisited`,
    //   `series-${g.id}-must-icon`,
    //   `series-${g.id}-visited-normal`,
    //   `series-${g.id}-visited-must`
    // ]);

    // const { features: seriesFeatures } = await mapRef.current.queryRenderedFeaturesAtPoint(
    //   [screenPointX, screenPointY],
    //   undefined,
    //   seriesLayerIds
    // );

    // if (seriesFeatures?.length) {
    //   handleMarkerPress({ features: seriesFeatures });
    //   return;
    // }

    if (selectedMarker || selectedUser) {
      closeCallout();
      return;
    }
    if (type === 'blank') return;
    try {
      const { screenPointX, screenPointY } = event.properties;
      const [lng, lat] = event.geometry?.coordinates;

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

      if (features?.length) {
        let region = features[0];

        try {
          if (typeof lng === 'number' && typeof lat === 'number') {
            const p = point([lng, lat]);

            const inside = features
              .filter(
                (f) => f?.geometry?.type === 'Polygon' || f?.geometry?.type === 'MultiPolygon'
              )
              .filter((f) => booleanPointInPolygon(p, f as any));

            const best = inside.slice().sort((a, b) => area(a as any) - area(b as any))[0];

            if (best) {
              region = best;
            }
          }
        } catch (e) {
          console.warn('region detection failed', e);
        }

        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);

        if (region.properties?.alt_id) {
          setSelectedRegion(region.properties?.alt_id);
          db = db1;
          tableName = 'regions';
        }

        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 && region.bbox) {
              const bounds = turf.bbox(region.bbox);
              if (bounds.every(isValidNumber)) {
                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 && region.bbox) {
              const bounds = turf.bbox(region.bbox);
              if (bounds.every(isValidNumber)) {
                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 && region.bbox) {
              const bounds = turf.bbox(region.bbox);
              if (bounds.every(isValidNumber)) {
                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) {
      await getLocation();
    } else if (!canAskAgain || !isServicesEnabled) {
      setOpenSettingsVisible(true);
    }
  };

  const handleOpenEditModal = () => {
    navigation.navigate(NAVIGATION_PAGES.TRIPS_2025, {
      region: { id: regionData.id, name: regionData.name }
    });
  };

  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 && region.bbox) {
            const bounds = turf.bbox(region.bbox);
            if (bounds.every(isValidNumber)) {
              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 && region.bbox) {
            const bounds = turf.bbox(region.bbox);
            if (bounds.every(isValidNumber)) {
              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 && region.bbox) {
            const bounds = turf.bbox(region.bbox);
            if (bounds.every(isValidNumber)) {
              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) {
      const uniqueFeatures = features
        ? Array.from(new Map(features.map((f: any) => [f.properties.id, f])).values())
        : [];

      if (uniqueFeatures.length > 1) {
        const markers = uniqueFeatures
          .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,
              avatars: f.properties.avatars,
              no_visited: f.properties.no_visited
            };
          })
          .filter(Boolean)
          .sort((a: any, b: any) => a.visited - b.visited);

        SheetManager.show('multiple-series-modal', {
          payload: {
            markers,
            token,
            toggleSeries,
            setSelectedMarker,
            setIsWarningModalVisible,
            setPremiumModalVisible
          } 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, avatars, no_visited } =
        selectedFeature.properties;

      if (coordinates) {
        setSelectedMarker({
          coordinates,
          name,
          icon,
          description,
          series_name,
          visited,
          series_id,
          id,
          avatars,
          no_visited
        });
        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'}
        // mapStyle={VECTOR_MAP_HOST + '/nomadmania-maps2026.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"
            />
          </>
        )}

        {/* {didFinishLoadingStyle &&
          seriesGroups?.length > 0 &&
          seriesGroups.map((group) => {
            const visible = isGroupEnabled(group.id);
            const mustVisible = seriesFilter.visible && (visible || isMustModeEnabled);

            return (
              <React.Fragment key={`series-group-${group.id}`}>
                {seriesFilter.status !== 1
                  ? (() => {
                      try {
                        return [
                          <MapLibreRN.SymbolLayer
                            key={`symbol_unvisited_normal_${group.id}`}
                            id={`series-${group.id}-unvisited`}
                            sourceID={`series-${group.id}`}
                            sourceLayerID={`series-${group.id}`}
                            aboveLayerID={'waterway-name'}
                            filter={['all', seriesNotVisitedFilter, ['!=', 'must', 1]] as any}
                            style={{
                              symbolSpacing: 1,
                              iconImage: '{series_id}',
                              iconAllowOverlap: true,
                              iconIgnorePlacement: true,
                              iconSize: SERIES_ICON_SIZE,
                              visibility: visible ? 'visible' : 'none',
                              iconColor: '#666',
                              iconOpacity: 1,
                              iconHaloColor: '#ffffff',
                              iconHaloWidth: 1,
                              iconHaloBlur: 0.5,
                              textAnchor: 'top',
                              textField: '{name}',
                              textFont: ['Noto Sans Regular'],
                              textMaxWidth: 9,
                              textOffset: [0, 1.3],
                              textPadding: 2,
                              textSize: 12,
                              textOptional: true,
                              textIgnorePlacement: false,
                              textAllowOverlap: false,
                              textColor: '#666',
                              textHaloColor: '#ffffff',
                              textHaloWidth: 1,
                              textHaloBlur: 0.5
                            }}
                          />,
                          <MapLibreRN.CircleLayer
                            key={`circle_unvisited_must_${group.id}`}
                            id={`series-${group.id}-must-wrapper`}
                            sourceID={`series-${group.id}`}
                            sourceLayerID={`series-${group.id}`}
                            aboveLayerID={`series-${group.id}-unvisited`}
                            filter={['all', seriesNotVisitedFilter, ['==', 'must', 1]] as any}
                            style={{
                              circleRadius: SERIES_CIRCLE_RADIUS,
                              circleColor: Colors.ORANGE,
                              circleOpacity: 1,
                              circleStrokeWidth: SERIES_CIRCLE_STROKE,
                              circleStrokeColor: Colors.ORANGE,
                              visibility: mustVisible ? 'visible' : 'none'
                            }}
                          />,
                          <MapLibreRN.SymbolLayer
                            key={`symbol_unvisited_must_${group.id}`}
                            id={`series-${group.id}-must-icon`}
                            sourceID={`series-${group.id}`}
                            sourceLayerID={`series-${group.id}`}
                            aboveLayerID={`series-${group.id}-must-wrapper`}
                            filter={['all', seriesNotVisitedFilter, ['==', 'must', 1]] as any}
                            style={{
                              symbolSpacing: 1,
                              iconImage: '{series_id}',
                              iconAllowOverlap: true,
                              iconIgnorePlacement: true,
                              iconSize: SERIES_ICON_SIZE,
                              visibility: mustVisible ? 'visible' : 'none',
                              iconColor: '#666',
                              iconOpacity: 1,
                              iconHaloColor: '#ffffff',
                              iconHaloWidth: 1,
                              iconHaloBlur: 0.5,
                              textAnchor: 'top',
                              textField: '{name}',
                              textFont: ['Noto Sans Regular'],
                              textMaxWidth: 9,
                              textOffset: [0, 1.3],
                              textPadding: 2,
                              textSize: 12,
                              textOptional: true,
                              textIgnorePlacement: false,
                              textAllowOverlap: false,
                              textColor: '#666',
                              textHaloColor: '#ffffff',
                              textHaloWidth: 1,
                              textHaloBlur: 0.5
                            }}
                          />
                        ];
                      } catch (error) {
                        console.warn('SymbolLayer render error:', error);
                        return null;
                      }
                    })()
                  : null}

                {seriesFilter.status !== 0
                  ? (() => {
                      try {
                        return [
                          <MapLibreRN.SymbolLayer
                            key={`symbol_visited_normal_${group.id}`}
                            id={`series-${group.id}-visited-normal`}
                            sourceID={`series-${group.id}`}
                            sourceLayerID={`series-${group.id}`}
                            aboveLayerID={'waterway-name'}
                            filter={['all', seriesVisitedFilter, ['!=', 'must', 1]] as any}
                            style={{
                              symbolSpacing: 1,
                              iconImage: '{series_id}v',
                              iconAllowOverlap: true,
                              iconIgnorePlacement: true,
                              iconSize: SERIES_ICON_SIZE,
                              visibility: visible ? 'visible' : 'none',
                              iconColor: '#666',
                              iconOpacity: 1,
                              iconHaloColor: '#ffffff',
                              iconHaloWidth: 1,
                              iconHaloBlur: 0.5,
                              textAnchor: 'top',
                              textField: '{name}',
                              textFont: ['Noto Sans Regular'],
                              textMaxWidth: 9,
                              textOffset: [0, 1.3],
                              textPadding: 2,
                              textSize: 12,
                              textOptional: true,
                              textIgnorePlacement: false,
                              textAllowOverlap: false,
                              textColor: '#666',
                              textHaloColor: '#ffffff',
                              textHaloWidth: 1,
                              textHaloBlur: 0.5
                            }}
                          />,
                          <MapLibreRN.CircleLayer
                            key={`circle_visited_must_${group.id}`}
                            id={`series-${group.id}-visited-must-wrapper`}
                            sourceID={`series-${group.id}`}
                            sourceLayerID={`series-${group.id}`}
                            aboveLayerID={`series-${group.id}-visited-normal`}
                            filter={['all', seriesVisitedFilter, ['==', 'must', 1]] as any}
                            style={{
                              circleRadius: SERIES_CIRCLE_RADIUS,
                              circleColor: Colors.ORANGE,
                              circleOpacity: 1,
                              circleStrokeWidth: SERIES_CIRCLE_STROKE,
                              circleStrokeColor: Colors.ORANGE,
                              visibility: mustVisible ? 'visible' : 'none'
                            }}
                          />,
                          <MapLibreRN.SymbolLayer
                            key={`symbol_visited_must_${group.id}`}
                            id={`series-${group.id}-visited-must`}
                            sourceID={`series-${group.id}`}
                            sourceLayerID={`series-${group.id}`}
                            aboveLayerID={`series-${group.id}-visited-must-wrapper`}
                            filter={['all', seriesVisitedFilter, ['==', 'must', 1]] as any}
                            style={{
                              symbolSpacing: 1,
                              iconImage: '{series_id}v',
                              iconAllowOverlap: true,
                              iconIgnorePlacement: true,
                              iconSize: SERIES_ICON_SIZE,
                              visibility: mustVisible ? 'visible' : 'none',
                              iconColor: '#666',
                              iconOpacity: 1,
                              iconHaloColor: '#ffffff',
                              iconHaloWidth: 1,
                              iconHaloBlur: 0.5,
                              textAnchor: 'top',
                              textField: '{name}',
                              textFont: ['Noto Sans Regular'],
                              textMaxWidth: 9,
                              textOffset: [0, 1.3],
                              textPadding: 2,
                              textSize: 12,
                              textOptional: true,
                              textIgnorePlacement: false,
                              textAllowOverlap: false,
                              textColor: '#666',
                              textHaloColor: '#ffffff',
                              textHaloWidth: 1,
                              textHaloBlur: 0.5
                            }}
                          />
                        ];
                      } catch (error) {
                        console.warn('SymbolLayer render error:', error);
                        return null;
                      }
                    })()
                  : null}
              </React.Fragment>
            );
          })} */}
        <MapLibreRN.VectorSource
          id="nomadmania_series"
          tileUrlTemplates={[VECTOR_MAP_HOST + '/tiles/series/{z}/{x}/{y}.pbf']}
          onPress={handleMarkerPress}
        >
          {seriesFilter.status !== 1
            ? (() => {
                try {
                  return [
                    <MapLibreRN.SymbolLayer
                      key="symbol_unvisited_normal"
                      id={`${series_layer.id}_normal`}
                      sourceID={series_layer.source}
                      sourceLayerID={series_layer['source-layer']}
                      aboveLayerID={'waterway-name'}
                      filter={['all', seriesNotVisitedFilter, ['!=', 'must', 1]] as any}
                      minZoomLevel={series_layer.minzoom}
                      maxZoomLevel={series_layer.maxzoom}
                      style={{
                        symbolSpacing: 1,
                        iconImage: '{series_id}',
                        iconAllowOverlap: true,
                        iconIgnorePlacement: true,
                        iconSize: SERIES_ICON_SIZE,
                        visibility: 'visible',
                        iconColor: '#666',
                        iconOpacity: 1,
                        iconHaloColor: '#ffffff',
                        iconHaloWidth: 1,
                        iconHaloBlur: 0.5,
                        textAnchor: 'top',
                        textField: seriesTextField,
                        textFont: ['Noto Sans Regular'],
                        textMaxWidth: 9,
                        textOffset: [0, 1.3],
                        textPadding: 2,
                        textSize: SERIES_TEXT_SIZE,
                        textOptional: true,
                        textIgnorePlacement: false,
                        textAllowOverlap: false,
                        textColor: '#666',
                        textHaloColor: '#ffffff',
                        textHaloWidth: 1,
                        textHaloBlur: 0.5
                      }}
                    />,
                    <MapLibreRN.CircleLayer
                      key="circle_unvisited_must"
                      id={`${series_layer.id}_must_wrapper`}
                      sourceID={series_layer.source}
                      sourceLayerID={series_layer['source-layer']}
                      aboveLayerID={`${series_layer.id}_normal`}
                      filter={['all', seriesNotVisitedFilter, ['==', 'must', 1]] as any}
                      minZoomLevel={series_layer.minzoom}
                      maxZoomLevel={series_layer.maxzoom}
                      style={{
                        circleRadius: SERIES_CIRCLE_RADIUS,
                        circleColor: Colors.ORANGE,
                        circleOpacity: 1,
                        circleStrokeWidth: SERIES_CIRCLE_STROKE,
                        circleStrokeColor: Colors.ORANGE,
                        visibility: 'visible'
                      }}
                    />,
                    <MapLibreRN.SymbolLayer
                      key="symbol_unvisited_must"
                      id={series_layer.id}
                      sourceID={series_layer.source}
                      sourceLayerID={series_layer['source-layer']}
                      aboveLayerID={`${series_layer.id}_must_wrapper`}
                      filter={['all', seriesNotVisitedFilter, ['==', 'must', 1]] as any}
                      minZoomLevel={series_layer.minzoom}
                      maxZoomLevel={series_layer.maxzoom}
                      style={{
                        symbolSpacing: 1,
                        iconImage: '{series_id}',
                        iconAllowOverlap: true,
                        iconIgnorePlacement: true,
                        iconSize: SERIES_ICON_SIZE,
                        visibility: 'visible',
                        iconColor: '#666',
                        iconOpacity: 1,
                        iconHaloColor: '#ffffff',
                        iconHaloWidth: 1,
                        iconHaloBlur: 0.5,
                        textAnchor: 'top',
                        textField: seriesTextField,
                        textFont: ['Noto Sans Regular'],
                        textMaxWidth: 9,
                        textOffset: [0, 1.3],
                        textPadding: 2,
                        textSize: SERIES_TEXT_SIZE,
                        textOptional: true,
                        textIgnorePlacement: false,
                        textAllowOverlap: false,
                        textColor: '#666',
                        textHaloColor: '#ffffff',
                        textHaloWidth: 1,
                        textHaloBlur: 0.5
                      }}
                    />
                  ];
                } catch (error) {
                  console.warn('SymbolLayer render error:', error);
                  return null;
                }
              })()
            : null}

          {seriesFilter.status !== 0
            ? (() => {
                try {
                  return [
                    <MapLibreRN.SymbolLayer
                      key="symbol_visited_normal"
                      id={`${series_visited.id}_normal`}
                      sourceID={series_visited.source}
                      sourceLayerID={series_visited['source-layer']}
                      aboveLayerID={'waterway-name'}
                      filter={['all', seriesVisitedFilter, ['!=', 'must', 1]] as any}
                      minZoomLevel={series_visited.minzoom}
                      maxZoomLevel={series_visited.maxzoom}
                      style={{
                        symbolSpacing: 1,
                        iconImage: '{series_id}v',
                        iconAllowOverlap: true,
                        iconIgnorePlacement: true,
                        iconSize: SERIES_ICON_SIZE,
                        visibility: 'visible',
                        iconColor: '#666',
                        iconOpacity: 1,
                        iconHaloColor: '#ffffff',
                        iconHaloWidth: 1,
                        iconHaloBlur: 0.5,
                        textAnchor: 'top',
                        textField: seriesTextField,
                        textFont: ['Noto Sans Regular'],
                        textMaxWidth: 9,
                        textOffset: [0, 1.3],
                        textPadding: 2,
                        textSize: SERIES_TEXT_SIZE,
                        textOptional: true,
                        textIgnorePlacement: false,
                        textAllowOverlap: false,
                        textColor: '#666',
                        textHaloColor: '#ffffff',
                        textHaloWidth: 1,
                        textHaloBlur: 0.5
                      }}
                    />,
                    <MapLibreRN.CircleLayer
                      key="circle_visited_must"
                      id={`${series_visited.id}_must_wrapper`}
                      sourceID={series_visited.source}
                      sourceLayerID={series_visited['source-layer']}
                      aboveLayerID={`${series_visited.id}_normal`}
                      filter={['all', seriesVisitedFilter, ['==', 'must', 1]] as any}
                      minZoomLevel={series_visited.minzoom}
                      maxZoomLevel={series_visited.maxzoom}
                      style={{
                        circleRadius: SERIES_CIRCLE_RADIUS,
                        circleColor: Colors.ORANGE,
                        circleOpacity: 1,
                        circleStrokeWidth: SERIES_CIRCLE_STROKE,
                        circleStrokeColor: Colors.ORANGE,
                        visibility: 'visible'
                      }}
                    />,
                    <MapLibreRN.SymbolLayer
                      key="symbol_visited_must"
                      id={series_visited.id}
                      sourceID={series_visited.source}
                      sourceLayerID={series_visited['source-layer']}
                      aboveLayerID={`${series_visited.id}_must_wrapper`}
                      filter={['all', seriesVisitedFilter, ['==', 'must', 1]] as any}
                      minZoomLevel={series_visited.minzoom}
                      maxZoomLevel={series_visited.maxzoom}
                      style={{
                        symbolSpacing: 1,
                        iconImage: '{series_id}v',
                        iconAllowOverlap: true,
                        iconIgnorePlacement: true,
                        iconSize: SERIES_ICON_SIZE,
                        visibility: 'visible',
                        iconColor: '#666',
                        iconOpacity: 1,
                        iconHaloColor: '#ffffff',
                        iconHaloWidth: 1,
                        iconHaloBlur: 0.5,
                        textAnchor: 'top',
                        textField: seriesTextField,
                        textFont: ['Noto Sans Regular'],
                        textMaxWidth: 9,
                        textOffset: [0, 1.3],
                        textPadding: 2,
                        textSize: SERIES_TEXT_SIZE,
                        textOptional: true,
                        textIgnorePlacement: false,
                        textAllowOverlap: false,
                        textColor: '#666',
                        textHaloColor: '#ffffff',
                        textHaloWidth: 1,
                        textHaloBlur: 0.5
                      }}
                    />
                  ];
                } catch (error) {
                  console.warn('SymbolLayer render error:', error);
                  return null;
                }
              })()
            : null}
        </MapLibreRN.VectorSource>

        <MapLibreRN.ShapeSource
          ref={shapeSourceRef}
          tolerance={20}
          id="nomads"
          shape={
            nomads && (showNomads || nomadsFilter.friends || nomadsFilter.countries?.length)
              ? nomads
              : { type: 'FeatureCollection', features: [] }
          }
          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', '00'],
              iconAllowOverlap: true
            }}
          ></MapLibreRN.SymbolLayer>
        </MapLibreRN.ShapeSource>

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

        {selectedMarker && (
          <MarkerItem
            marker={selectedMarker}
            toggleSeries={toggleSeries}
            token={token}
            isPremium={isPremium}
            setPremiumModalVisible={setPremiumModalVisible}
          />
        )}
        {(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 {
                    filterModalRef.current?.openFilter('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 {
                    filterModalRef.current?.openFilter('series');
                    closeCallout();
                  } catch (error) {
                    console.error('Error opening filter:', error);
                  }
                }}
                icon={SeriesIcon}
                text="Series"
                active={seriesFilter.visible}
              />
              {token ? (
                <MapButton
                  onPress={() => {
                    try {
                      filterModalRef.current?.openFilter('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
        ref={filterModalRef}
        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?"
      />
      <WarningModal
        type={'success'}
        isVisible={premiumModalVisible}
        message={
          'This feature is available to Premium users. Premium account settings can be managed on our website.'
        }
        action={() => {}}
        onClose={() => setPremiumModalVisible(false)}
        title={'Premium Feature'}
      />
      <MultipleSeriesModal />
    </SafeAreaView>
  );
};

export default MapScreen;
