import {
  Platform,
  TouchableOpacity,
  Image,
  Linking,
  TextInput,
  Dimensions,
  StatusBar,
  ActivityIndicator
} from 'react-native';
import React, { FC, useEffect, useRef, useState } from 'react';
import * as Location from 'expo-location';
import Animated, {
  Easing,
  useSharedValue,
  useAnimatedStyle,
  withTiming
} from 'react-native-reanimated';

import { styles } from './styles';
import { API_HOST, VECTOR_MAP_HOST } from 'src/constants';
import { CommonActions, NavigationProp } from '@react-navigation/native';
import { AvatarWithInitials, LocationPopup } from 'src/components';
import { Colors } from 'src/theme';

import CloseSvg from 'assets/icons/close.svg';
import FilterIcon from 'assets/icons/filter.svg';
import LocationIcon from 'assets/icons/location.svg';
import SearchIcon from 'assets/icons/search.svg';

import FilterModal from '../../MapScreen/FilterModal';
import SearchModal from '../../MapScreen/UniversalSearch';
import { useGetUniversalSearch } from '@api/search';
import { storage, StoreType } from 'src/storage';
import { NAVIGATION_PAGES } from 'src/types';
import { SafeAreaView } from 'react-native-safe-area-context';
import MapLibreGL, { CameraRef, MapViewRef } from '@maplibre/maplibre-react-native';
import {
  usePostGetVisitedCountriesIdsQuery,
  usePostGetVisitedDareIdsQuery,
  usePostGetVisitedRegionsIdsQuery
} from '@api/maps';
import moment from 'moment';

MapLibreGL.setAccessToken(null);

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

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

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

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

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

type Props = {
  navigation: NavigationProp<any>;
  route: any;
};

const UsersMapScreen: FC<Props> = ({ navigation, route }) => {
  const token = storage.get('token', StoreType.STRING) as string;
  const userId = route.params?.userId;
  const data = route.params?.data;

  const [regionsVisitedFilter, setRegionsVisitedFilter] = useState(generateFilter([]));
  const [countriesVisitedFilter, setCountriesVisitedFilter] = useState(generateFilter([]));
  const [dareVisitedFilter, setDareVisitedFilter] = useState(generateFilter([]));

  const [regionsFilter, setRegionsFilter] = useState<any>({
    visitedLabel: 'by',
    year: moment().year()
  });

  const mapRef = useRef<MapViewRef>(null);
  const cameraRef = useRef<CameraRef>(null);
  const [isFilterVisible, setIsFilterVisible] = useState(false);
  const [tilesType, setTilesType] = useState({ label: 'NM regions', value: 0 });
  const tilesTypes = [
    { label: 'NM regions', value: 0 },
    { label: 'UN countries', value: 1 },
    { label: 'DARE places', value: 2 }
  ];
  const [type, setType] = useState('regions');
  const [location, setLocation] = useState<Location.LocationObjectCoords | null>(null);
  const [askLocationVisible, setAskLocationVisible] = useState<boolean>(false);
  const [openSettingsVisible, setOpenSettingsVisible] = useState<boolean>(false);
  const [isExpanded, setIsExpanded] = useState(false);
  const [searchVisible, setSearchVisible] = useState(false);
  const [index, setIndex] = useState<number>(0);
  const width = useSharedValue(48);
  const usableWidth = Dimensions.get('window').width - 32;
  const [search, setSearch] = useState('');
  const [searchInput, setSearchInput] = useState('');
  const { data: searchData } = useGetUniversalSearch(search, search.length > 0);
  const [isLocationLoading, setIsLocationLoading] = useState(false);

  const { data: visitedRegionIds } = usePostGetVisitedRegionsIdsQuery(
    token,
    regionsFilter.visitedLabel,
    regionsFilter.year,
    +userId,
    type === 'regions' && !!userId
  );
  const { data: visitedCountryIds } = usePostGetVisitedCountriesIdsQuery(
    token,
    regionsFilter.visitedLabel,
    regionsFilter.year,
    +userId,
    type === 'countries' && !!userId
  );
  const { data: visitedDareIds } = usePostGetVisitedDareIdsQuery(
    token,
    +userId,
    type === 'dare' && !!userId
  );

  useEffect(() => {
    if (visitedRegionIds) {
      setRegionsVisitedFilter(generateFilter(visitedRegionIds.ids));
    }
  }, [visitedRegionIds]);

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

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

  const handleGetLocation = async () => {
    setIsLocationLoading(true);
    try {
      let { status, canAskAgain } = await Location.getForegroundPermissionsAsync();
      const isServicesEnabled = await Location.hasServicesEnabledAsync();

      if (status === 'granted' && isServicesEnabled) {
        await getLocation();
      } else if (!canAskAgain || !isServicesEnabled) {
        setOpenSettingsVisible(true);
      } else {
        setAskLocationVisible(true);
      }
    } finally {
      setIsLocationLoading(false);
    }
  };

  const getLocation = async () => {
    let currentLocation = await Location.getCurrentPositionAsync({
      accuracy: Location.Accuracy.Balanced
    });
    setLocation(currentLocation.coords);

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

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

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

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

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

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

  const handleGoBack = () => {
    navigation.goBack();
  };

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

  const handleFindRegion = (id: number, type: string) => {
    navigation.dispatch(
      CommonActions.reset({
        index: 1,
        routes: [
          {
            name: NAVIGATION_PAGES.IN_APP_MAP_TAB,
            state: {
              routes: [
                {
                  name: NAVIGATION_PAGES.MAP_TAB,
                  params: { id, type }
                }
              ]
            }
          }
        ]
      })
    );
  };

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

      <MapLibreGL.MapView
        ref={mapRef}
        style={styles.map}
        styleJSON={VECTOR_MAP_HOST + '/nomadmania-maps.json'}
        rotateEnabled={false}
        attributionEnabled={false}
      >
        {type === 'regions' && (
          <>
            <MapLibreGL.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 }
              }}
            />
            <MapLibreGL.FillLayer
              id={regions.id}
              sourceID={regions.source}
              sourceLayerID={regions['source-layer']}
              filter={regions.filter as any}
              style={regions.style}
              maxZoomLevel={regions.maxzoom}
              belowLayerID={regions_visited.id}
            />
            <MapLibreGL.FillLayer
              id={regions_visited.id}
              sourceID={regions_visited.source}
              sourceLayerID={regions_visited['source-layer']}
              filter={regionsVisitedFilter as any}
              style={regions_visited.style}
              maxZoomLevel={regions_visited.maxzoom}
              belowLayerID="waterway-name"
            />
          </>
        )}
        {type === 'countries' && (
          <>
            <MapLibreGL.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 }
              }}
            />
            <MapLibreGL.FillLayer
              id={countries.id}
              sourceID={countries.source}
              sourceLayerID={countries['source-layer']}
              filter={countries.filter as any}
              style={countries.style}
              maxZoomLevel={countries.maxzoom}
              belowLayerID={countries_visited.id}
            />
            <MapLibreGL.FillLayer
              id={countries_visited.id}
              sourceID={countries_visited.source}
              sourceLayerID={countries_visited['source-layer']}
              filter={countriesVisitedFilter as any}
              style={countries_visited.style}
              maxZoomLevel={countries_visited.maxzoom}
              belowLayerID="waterway-name"
            />
          </>
        )}
        {type === 'dare' && (
          <>
            <MapLibreGL.FillLayer
              id={dare.id}
              sourceID={dare.source}
              sourceLayerID={dare['source-layer']}
              filter={dare.filter as any}
              style={dare.style}
              maxZoomLevel={dare.maxzoom}
              belowLayerID={dare_visited.id}
            />
            <MapLibreGL.FillLayer
              id={dare_visited.id}
              sourceID={dare_visited.source}
              sourceLayerID={dare_visited['source-layer']}
              filter={dareVisitedFilter as any}
              style={dare_visited.style}
              maxZoomLevel={dare_visited.maxzoom}
              belowLayerID="waterway-name"
            />
          </>
        )}

        <MapLibreGL.Camera ref={cameraRef} />
        {location && (
          <MapLibreGL.UserLocation
            animated={true}
            showsUserHeadingIndicator={true}
          ></MapLibreGL.UserLocation>
        )}
      </MapLibreGL.MapView>

      {!isExpanded ? (
        <TouchableOpacity
          style={[styles.cornerButton, styles.topRightButton]}
          onPress={handleGoBack}
        >
          {data.user_data.avatar ? (
            <Image
              style={styles.avatar}
              source={{ uri: API_HOST + '/img/avatars/' + data.user_data.avatar }}
            />
          ) : (
            <AvatarWithInitials
              text={`${data.user_data.first_name[0] ?? ''}${data.user_data.last_name[0] ?? ''}`}
              flag={API_HOST + '/img/flags_new/' + data.user_data.flag1}
              size={48}
              borderColor={Colors.WHITE}
            />
          )}
        </TouchableOpacity>
      ) : null}

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

      <TouchableOpacity
        onPress={handleGetLocation}
        style={[styles.cornerButton, styles.bottomButton, styles.bottomRightButton]}
      >
        {isLocationLoading ? (
          <ActivityIndicator size="small" color={Colors.DARK_BLUE} />
        ) : (
          <LocationIcon />
        )}
      </TouchableOpacity>
      <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>
      <FilterModal
        isFilterVisible={isFilterVisible}
        setIsFilterVisible={setIsFilterVisible}
        tilesTypes={tilesTypes}
        tilesType={tilesType}
        setTilesType={setTilesType}
        setType={setType}
        userId={userId}
        setRegionsFilter={setRegionsFilter}
        isPublicView={true}
        isLogged={true}
      />
      <LocationPopup
        visible={askLocationVisible}
        onClose={() => setAskLocationVisible(false)}
        onAccept={handleAcceptPermission}
        modalText="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."
      />
      <LocationPopup
        visible={openSettingsVisible}
        onClose={() => setOpenSettingsVisible(false)}
        onAccept={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();
          }
        }}
        modalText="NomadMania app needs location permissions to function properly. Open settings?"
      />
      <SearchModal
        searchVisible={searchVisible}
        handleCloseModal={handleCloseModal}
        handleFindRegion={handleFindRegion}
        index={index}
        searchData={searchData}
        setIndex={setIndex}
        token={token}
      />
    </SafeAreaView>
  );
};

export default UsersMapScreen;
