import React, {useCallback, useEffect, useMemo, useRef, useState} from 'react';
import {Linking, View} from 'react-native';
import {useTranslation} from 'react-i18next';
import {useDispatch} from 'react-redux';
import {
  IconBuilding,
  IconChevronDown,
  IconCircleX,
  IconHome,
} from '@tabler/icons-react-native';
import type {InputSelectOption} from '@components';
import {
  CardContainer,
  Avatar,
  BottomModalFooter,
  ListRow,
  Typography,
  Title,
  Button,
} from '@components';
import {Navigation} from '@interfaces/navigation';
import {TIME_TRACKING_REMOTE_SITE_OPTION_ID} from '@modules/timeTracking/constants';
import {
  useGeolocation,
  useGetSites,
  useTimeoutHandler,
} from '@modules/timeTracking/hooks';
import {
  LocationSelectorSelection,
  PositionError,
} from '@modules/timeTracking/interfaces';
import {
  openPermissionsDialog,
  openTimeTracker,
  setLocationError,
} from '@modules/timeTracking/redux';
import {useAppSelector} from '@redux/utils';
import {AMPLITUDE_EVENTS, Screens} from '@shared/constants';
import {useTheme} from '@shared/theme';
import {logAmplitudeEvent} from '@shared/utils/logs';

import LocationsLoaderSk from './components/LocationsLoaderSk';
import Map from './components/Map';
import {SelectLocationDialog} from './components/SelectLocationDialog';
import {styles} from './styles';

const formatSelectedItem = (selectedItem: InputSelectOption<number>) =>
  selectedItem.description
    ? `${selectedItem.label} - ${selectedItem.description}`
    : selectedItem.label;

function Locations({navigation, route}: Navigation<Screens.LOCATIONS>) {
  const dispatch = useDispatch();
  const {theme} = useTheme();
  const {t} = useTranslation();
  const hasGeoFencing = useAppSelector(
    ({timeTracking}) => timeTracking.policies?.geofencing,
  );
  const enableRemoteWork = useAppSelector(
    ({timeTracking}) => timeTracking.policies?.enableRemoteWork,
  );
  const saveRemoteWorkLocation = useAppSelector(
    ({timeTracking}) => timeTracking.policies?.saveRemoteWorkLocation,
  );
  const locationError = useAppSelector(
    ({timeTracking}) => timeTracking.locationError,
  );
  const locationLoading = useAppSelector(
    ({timeTracking}) => timeTracking.locationLoading,
  );
  const [showWarning, setShowWarning] = useState(false);
  const [isLocationDialogOpen, setIsLocationDialogOpen] = useState(false);
  const preventOpenModal = useRef(false);
  const {
    fullSelectedSite,
    isInsideSite,
    isSitesEmpty,
    isLoadingSites,
    onSelectLocation,
    selectedLocation,
    sitesOptions,
  } = useGetSites();
  const {onGetCurrentLocation} = useGeolocation();
  const isInternalError = locationError === PositionError.INTERNAL_ERROR;
  const isPreciseLocationError =
    !!locationError &&
    [
      PositionError.PRECISE_LOCATION,
      PositionError.PREMISSION_DENIED_PRECISE_LOCATION,
    ].includes(locationError);
  const hasGeoError =
    hasGeoFencing &&
    !isSitesEmpty &&
    (!isInsideSite || isPreciseLocationError || isInternalError);
  const isLoading = isLoadingSites || locationLoading;

  const selectedSiteOption = useMemo(
    () => sitesOptions.find(option => option.id === selectedLocation),
    [selectedLocation, sitesOptions],
  );

  const locationRowLabel = selectedSiteOption
    ? formatSelectedItem(selectedSiteOption)
    : t('time_tracking_common.select_location');

  useTimeoutHandler();

  const getCurrentLocation = useCallback(() => {
    onGetCurrentLocation({startTime: new Date()});
  }, [onGetCurrentLocation]);

  useEffect(() => {
    if (locationError === PositionError.MOCK_ERROR && !__DEV__) {
      navigation.popToTop();
      navigation.navigate(Screens.LOCATION_MOCK_ERROR);
    } else if (locationError === PositionError.PERMISSION_DENIED) {
      navigation.popToTop();
      openPermissionsDialog('locationBlocker');
    } else if (locationError === PositionError.SERVICE_NOT_AVAILABLE) {
      navigation.popToTop();
      openPermissionsDialog('locationServiceBlocker');
    }
  }, [locationError, navigation]);

  useEffect(() => {
    const blur = navigation.addListener('blur', () => {
      preventOpenModal.current = true;
    });
    const focus = navigation.addListener('focus', () => {
      preventOpenModal.current = false;
    });
    const beforeRemove = navigation.addListener('beforeRemove', () => {
      if (
        !preventOpenModal.current &&
        !route.params?.comingFromCamera &&
        !locationError
      ) {
        openTimeTracker();
      }
    });
    return () => {
      blur();
      focus();
      beforeRemove();
    };
  }, [locationError, navigation, route.params?.comingFromCamera]);

  useEffect(() => {
    setShowWarning(!!locationError);
  }, [locationError]);

  const onPressCTA = () => {
    if (isLoading) return;
    navigation.navigate(Screens.TRACKER_COMMENT, {
      selectedLocation: fullSelectedSite,
      faceRejected: route.params?.faceRejected,
    });
  };

  const openSettings = async () => {
    await Linking.openSettings().catch(() => {});
    navigation.popToTop();
    dispatch(setLocationError(null));
  };

  const onOpenSettings = () => {
    openSettings();
  };

  const onExit = () => {
    navigation.popToTop();
  };

  const onOpenDialog = () => {
    logAmplitudeEvent(AMPLITUDE_EVENTS.TIME_TRACKING_LOCATION_SELECTOR_OPENED, {
      currentSelection:
        selectedLocation === TIME_TRACKING_REMOTE_SITE_OPTION_ID
          ? LocationSelectorSelection.REMOTE_WORK
          : selectedLocation === null
          ? LocationSelectorSelection.NO_LOCATION
          : LocationSelectorSelection.SITE,
    });
    setIsLocationDialogOpen(true);
  };

  return (
    <View
      style={[
        styles.container,
        {backgroundColor: theme.background.layout.default},
      ]}>
      {isLoading ? (
        <LocationsLoaderSk />
      ) : (
        <View style={styles.content}>
          {(hasGeoError || (isSitesEmpty && !enableRemoteWork)) && (
            <Typography
              weight="semiBold"
              color={
                hasGeoError
                  ? theme.text.feedback.error
                  : theme.text.neutral.default
              }>
              {t('time_tracker.your_location_is')}
            </Typography>
          )}
          {selectedLocation === TIME_TRACKING_REMOTE_SITE_OPTION_ID &&
          !saveRemoteWorkLocation ? (
            <CardContainer style={styles.remoteContainer}>
              <Avatar Icon={IconHome} variant="primary" />
              <Title
                title={t('time_tracking_common.home_office.title')}
                description={t(
                  'time_tracking_common.home_office.no_geolocation_description',
                )}
                center
                descriptionNumberOfLines={4}
              />
              <Button
                variant="secondary"
                onPress={onOpenDialog}
                text={t('time_tracking_common.choose_other_location')}
                IconLeft={IconBuilding}
              />
            </CardContainer>
          ) : (
            <>
              {isSitesEmpty && !enableRemoteWork ? (
                <Typography style={styles.subtitle} variant="xs">
                  {`${t('time_tracker.current_location')}.`}
                </Typography>
              ) : (
                <View style={styles.inputSelect}>
                  <ListRow
                    onPress={onOpenDialog}
                    style={[
                      styles.locationRow,
                      {
                        borderColor: hasGeoError
                          ? theme.border.states.error
                          : theme.border.neutral.default,
                      },
                    ]}>
                    {selectedSiteOption?.AvatarProps ? (
                      <ListRow.Avatar {...selectedSiteOption.AvatarProps} />
                    ) : null}
                    <ListRow.Title title={locationRowLabel} />
                    <ListRow.SideContent RightIconButton={IconChevronDown} />
                  </ListRow>
                </View>
              )}
              {showWarning ? (
                <CardContainer style={styles.cardContainer}>
                  <Avatar Icon={IconCircleX} variant="error" />
                  <Title
                    center
                    description={t(
                      isPreciseLocationError
                        ? 'time_tracker.not_precise_location_description'
                        : 'time_tracker.location_unavailable_description',
                    )}
                    descriptionNumberOfLines={4}
                    title={t(
                      isPreciseLocationError
                        ? 'time_tracker.not_precise_location'
                        : 'time_tracker.location_unavailable',
                    )}
                  />
                  <Button
                    variant="secondary"
                    onPress={
                      isPreciseLocationError
                        ? onOpenSettings
                        : getCurrentLocation
                    }
                    text={t(
                      `time_tracker.${
                        isPreciseLocationError
                          ? 'open_settings'
                          : 'retry_location'
                      }`,
                    )}
                  />
                </CardContainer>
              ) : (
                <Map
                  fullSelectedSite={fullSelectedSite}
                  isInsideSite={isInsideSite}
                  isSitesEmpty={isSitesEmpty}
                />
              )}
            </>
          )}
        </View>
      )}
      <SelectLocationDialog
        isVisible={isLocationDialogOpen}
        onClose={() => setIsLocationDialogOpen(false)}
        onConfirm={onSelectLocation}
        options={sitesOptions}
        selectedId={selectedLocation}
      />
      <BottomModalFooter
        footer={
          hasGeoFencing
            ? {
                primaryButton: {
                  isLoading,
                  onPress: hasGeoError ? getCurrentLocation : onPressCTA,
                  text: t(
                    hasGeoError
                      ? 'time_tracker.retry_loading_location'
                      : 'general.continue',
                  ),
                },
                secondaryButton: hasGeoError
                  ? {onPress: onExit, text: t('general.exit')}
                  : undefined,
              }
            : {
                primaryButton: {
                  disabled: isPreciseLocationError,
                  isLoading,
                  onPress: onPressCTA,
                  text: t(
                    `general.${
                      isInternalError ? 'continue_anyway' : 'continue'
                    }`,
                  ),
                },
              }
        }
        style={styles.bottomContainer}
      />
    </View>
  );
}

export default Locations;
