import React, { useEffect, useRef, useState } from 'react';
import {
  View,
  Text,
  TouchableOpacity,
  KeyboardAvoidingView,
  TouchableWithoutFeedback,
  Keyboard,
  ScrollView
} from 'react-native';
import { SafeAreaView } from 'react-native-safe-area-context';
import MapView, { Marker } from 'react-native-maps';
import ReactModal from 'react-native-modal';
import axios from 'axios';
import 'react-native-get-random-values';
import {
  GooglePlaceData,
  GooglePlaceDetail,
  GooglePlacesAutocomplete
} from 'react-native-google-places-autocomplete';
import { FlashList } from '@shopify/flash-list';
import { Formik } from 'formik';
import * as yup from 'yup';

import { styles } from './styles';
import { Header, Input, Button, WarningModal } from 'src/components';
import { GOOGLE_MAP_PLACES_APIKEY } from 'src/constants';
import { Colors } from 'src/theme';
import {
  SubmitSuggestionTypes,
  useGetDataFromPoint,
  useGetSuggestionData,
  useSubmitSuggestionMutation
} from '@api/series';
import { StoreType, storage } from 'src/storage';
import { ButtonVariants } from 'src/types/components';
import SeriesSelector from './SeriesSelector';

import SearchIcon from 'assets/icons/search.svg';
import InfoIcon from 'assets/icons/info-solid.svg';
import Tooltip from 'react-native-walkthrough-tooltip';
import { GooglePlacesAutocompleteDefaultProps } from './GooglePlacesAutocompleteProps';

interface Series {
  id: number;
  name: string;
  group_name: string | null;
}

const SuggestionSchema = yup.object({
  comment: yup.string().required('comment is required')
});

const SuggestSeriesScreen = ({ navigation }: { navigation: any }) => {
  const token = storage.get('token', StoreType.STRING) as string;
  const [isModalVisible, setIsModalVisible] = useState(false);
  const [seriesVisible, setSeriesVisible] = useState(false);
  const [marker, setMarker] = useState<any>(null);
  const [coordinates, setCoordinates] = useState<any>(null);
  const [groupedSeries, setGroupedSeries] = useState<any>(null);
  const [region, setRegion] = useState<any>({ nmRegion: null, dareRegion: null });
  const [selectedSeries, setSelectedSeries] = useState<Series | null>(null);
  const [submitedModalVisible, setSubmitedModalVisible] = useState(false);
  const [keyboardVisible, setKeyboardVisible] = useState(false);

  const { data: suggestionData } = useGetSuggestionData();
  const { data } = useGetDataFromPoint(
    token,
    coordinates?.lat,
    coordinates?.lng,
    coordinates ? true : false
  );
  const { mutateAsync: submitSuggestion } = useSubmitSuggestionMutation();

  const [tooltipVisible, setTooltipVisible] = useState(false);

  const mapRef = useRef<MapView>(null);

  useEffect(() => {
    const keyboardDidShowListener = Keyboard.addListener('keyboardDidShow', () => {
      setKeyboardVisible(true);
    });
    const keyboardDidHideListener = Keyboard.addListener('keyboardDidHide', () => {
      setKeyboardVisible(false);
    });

    return () => {
      keyboardDidHideListener.remove();
      keyboardDidShowListener.remove();
    };
  }, []);

  useEffect(() => {
    if (data && data.result === 'OK') {
      const nmRegion = data.nm ? suggestionData?.nm.find((item) => item.id === data.nm.id) : null;
      const dareRegion = data.dare
        ? suggestionData?.dare.find((item) => item.id === data.dare.id)
        : null;
      setRegion({ nmRegion, dareRegion });
      setSelectedSeries(null);
      setIsModalVisible(true);
    }
  }, [data]);

  useEffect(() => {
    if (suggestionData && suggestionData.result === 'OK') {
      const groupedData = Object.keys(suggestionData.grouped).map((key) => ({
        title: key,
        data: suggestionData.grouped[key]
      }));
      setGroupedSeries(groupedData);
    }
  }, [suggestionData]);

  const findPlace = async (placeId: string) => {
    const response = await axios.get(
      `https://maps.googleapis.com/maps/api/place/details/json?place_id=${placeId}&key=${GOOGLE_MAP_PLACES_APIKEY}`
    );
    return { url: response.data.result.url, name: response.data.result.name };
  };

  const animateMapToRegion = (latitude: number, longitude: number) => {
    const region = {
      latitude,
      longitude,
      latitudeDelta: 0.015,
      longitudeDelta: 0.0121
    };
    mapRef.current?.animateToRegion(region, 500);
  };

  const handlePoiClick = async (event: any) => {
    const { placeId, coordinate } = event.nativeEvent;
    const { url, name } = await findPlace(placeId);
    setMarker({
      placeId,
      name,
      coordinate,
      url
    });
    setCoordinates({ lat: coordinate.latitude, lng: coordinate.longitude });
    animateMapToRegion(coordinate.latitude, coordinate.longitude);
  };

  const handlePlaceSelection = (data: GooglePlaceData, details: GooglePlaceDetail | null) => {
    if (details) {
      const { geometry } = details;

      setMarker({
        placeId: data.place_id,
        name: data.structured_formatting.main_text,
        coordinate: {
          latitude: geometry.location.lat,
          longitude: geometry.location.lng
        },
        url: details.url
      });
      setCoordinates({ lat: geometry.location.lat, lng: geometry.location.lng });
      animateMapToRegion(geometry.location.lat, geometry.location.lng);
    }
  };

  const renderGroup = ({ item }: { item: { title: string; data: Series[] } }) => {
    return (
      <View>
        {item.title !== '-' && <Text style={styles.groupTitle}>{item.title}</Text>}
        {item.data.map((series: Series) => (
          <TouchableOpacity
            key={series.id}
            style={styles.seriesItem}
            onPress={() => {
              setSelectedSeries(series);
              setSeriesVisible(false);
            }}
          >
            <Text style={styles.seriesText}>{series.name}</Text>
          </TouchableOpacity>
        ))}
      </View>
    );
  };

  const handleClose = () => {
    setSubmitedModalVisible(false);
    setIsModalVisible(false);
    navigation.goBack();
  };

  return (
    <SafeAreaView
      style={{
        height: '100%'
      }}
      edges={['top']}
    >
      <View style={styles.wrapper}>
        <Header
          label={'Suggest new Series item'}
          rightElement={
            <Tooltip
              isVisible={tooltipVisible}
              onClose={() => setTooltipVisible(false)}
              content={
                <Text style={{ color: Colors.DARK_BLUE, fontSize: 13 }}>
                  We value the enthusiasm of travelers who want to share their favorite places with
                  the NomadMania community. Every suggestion reflects passion for exploration, and
                  we appreciate the time and thought that goes into each contribution to the series.
                  {'\n\n'}At the same time, not all submissions will be added to the map. We have a
                  dedicated team that is tasked to review all suggestions and maintain an overall
                  balance across regions and topics and to prevent overcrowding in certain areas.
                  {'\n\n'}For this reason, even good suggestions may occasionally be declined. We
                  hope you understand this approach, and we thank you for helping us shape a map
                  that highlights the richness of travel across the world.{'\n\n'}Best regards, the
                  Series Team
                </Text>
              }
              contentStyle={{ backgroundColor: Colors.WHITE }}
              backgroundColor="transparent"
              allowChildInteraction={false}
              placement="bottom"
            >
              <TouchableOpacity onPress={() => setTooltipVisible(true)} style={{ width: 30 }}>
                <InfoIcon />
              </TouchableOpacity>
            </Tooltip>
          }
        />
        <View style={styles.searchContainer}>
          <GooglePlacesAutocomplete
            {...GooglePlacesAutocompleteDefaultProps}
            placeholder="Add a landmark"
            onPress={handlePlaceSelection}
            query={{
              key: GOOGLE_MAP_PLACES_APIKEY,
              language: 'en',
              types: 'establishment'
            }}
            nearbyPlacesAPI="GooglePlacesSearch"
            fetchDetails={true}
            styles={{
              textInput: styles.searchInput
            }}
            isRowScrollable={true}
            renderLeftButton={() => (
              <View style={styles.searchIcon}>
                <SearchIcon fill={Colors.LIGHT_GRAY} />
              </View>
            )}
          />
        </View>
      </View>

      <View style={styles.container}>
        <MapView
          ref={mapRef}
          style={styles.map}
          showsMyLocationButton={true}
          showsUserLocation={true}
          showsCompass={false}
          zoomControlEnabled={false}
          mapType={'standard'}
          maxZoomLevel={18}
          minZoomLevel={0}
          initialRegion={{
            latitude: 0,
            longitude: 0,
            latitudeDelta: 180,
            longitudeDelta: 180
          }}
          provider="google"
          onPoiClick={handlePoiClick}
        >
          {marker && (
            <Marker coordinate={marker.coordinate} onPress={() => setIsModalVisible(true)} />
          )}
        </MapView>
      </View>

      <ReactModal
        isVisible={isModalVisible}
        onBackdropPress={() => setIsModalVisible(false)}
        style={styles.modal}
        statusBarTranslucent={true}
        presentationStyle="overFullScreen"
      >
        <Formik
          initialValues={{
            comment: '',
            nm: region.nmRegion ? region.nmRegion.region_name : '-',
            dare: region.dareRegion ? region.dareRegion.name : '-',
            series: selectedSeries ? selectedSeries.id : null,
            name: marker?.name,
            link: marker?.url,
            lat: coordinates?.lat,
            lng: coordinates?.lng,
            item: -1
          }}
          validationSchema={SuggestionSchema}
          onSubmit={(values) => {
            const { comment, name, link, lat, lng, item } = values;
            if (!selectedSeries) return;

            const submitData: SubmitSuggestionTypes = {
              token,
              comment,
              name,
              link,
              lat,
              lng,
              item,
              nm: region.nmRegion.id,
              dare: region.dareRegion ? region.dareRegion.id : 0,
              series: selectedSeries.id
            };

            submitSuggestion(submitData, {
              onSuccess: () => {
                setSubmitedModalVisible(true);
              }
            });
          }}
        >
          {(props) => (
            <KeyboardAvoidingView
              behavior={'padding'}
              style={[styles.modalContent, { maxHeight: keyboardVisible ? undefined : '90%' }]}
            >
              <TouchableWithoutFeedback onPress={Keyboard.dismiss}>
                <ScrollView
                  contentContainerStyle={{ gap: 16 }}
                  showsVerticalScrollIndicator={false}
                  keyboardShouldPersistTaps="handled"
                >
                  <Input
                    placeholder="NM region"
                    value={props.values.nm}
                    editable={false}
                    header="NM region"
                    height={40}
                  />
                  <Input
                    placeholder="DARE place"
                    value={props.values.dare}
                    editable={false}
                    header="DARE place"
                    height={40}
                  />
                  <SeriesSelector
                    selectedSeries={selectedSeries}
                    setSeriesVisible={setSeriesVisible}
                    props={props}
                  />
                  <Input
                    placeholder="Name"
                    value={props.values.name}
                    editable={false}
                    header="Name"
                    height={40}
                  />
                  <Input
                    placeholder="URL"
                    value={props.values.link}
                    editable={false}
                    header="Google maps link"
                    height={40}
                  />
                  <Input
                    multiline={true}
                    header="Comment"
                    value={props.values.comment}
                    onChange={props.handleChange('comment')}
                    formikError={props.touched.comment && props.errors.comment}
                  />

                  <View style={{ paddingBottom: 24, gap: 16 }}>
                    <Button children="Send" onPress={props.handleSubmit} />
                    <Button
                      children="Close"
                      onPress={() => setIsModalVisible(false)}
                      variant={ButtonVariants.OPACITY}
                      containerStyles={styles.closeBtn}
                      textStyles={{ color: Colors.DARK_BLUE }}
                    />
                  </View>
                </ScrollView>
              </TouchableWithoutFeedback>
            </KeyboardAvoidingView>
          )}
        </Formik>
        <ReactModal
          isVisible={seriesVisible}
          onBackdropPress={() => setSeriesVisible(false)}
          style={styles.modal}
          statusBarTranslucent={true}
          presentationStyle="overFullScreen"
        >
          <View style={styles.modalWrapper}>
            <ScrollView
              style={{ paddingBottom: 16 }}
              showsVerticalScrollIndicator={false}
              nestedScrollEnabled={true}
            >
              {groupedSeries ? (
                <View style={{ minHeight: 100, paddingBottom: 16, paddingTop: 8 }}>
                  <TouchableOpacity
                    style={styles.seriesItem}
                    onPress={() => {
                      setSelectedSeries(null);
                      setSeriesVisible(false);
                    }}
                  >
                    <Text style={styles.seriesText}>Select series</Text>
                  </TouchableOpacity>
                  <FlashList
                    viewabilityConfig={{
                      waitForInteraction: true,
                      itemVisiblePercentThreshold: 50,
                      minimumViewTime: 1000
                    }}
                    data={groupedSeries}
                    renderItem={renderGroup}
                    keyExtractor={(item) => item.title}
                    nestedScrollEnabled={true}
                  />
                </View>
              ) : null}
            </ScrollView>
          </View>
        </ReactModal>
        <WarningModal
          isVisible={submitedModalVisible}
          onClose={handleClose}
          type="success"
          message="Thank you for your suggestion!"
          title="Success!"
        />
      </ReactModal>
    </SafeAreaView>
  );
};

export default SuggestSeriesScreen;
