import React, { useEffect, useState, useRef } from 'react';
import { View, Text, TouchableOpacity, ScrollView, Alert } from 'react-native';
import ReactModal from 'react-native-modal';
import { useNavigation } from '@react-navigation/native';
import { Picker as WheelPicker } from 'react-native-wheel-pick';
import moment from 'moment';
import ActionSheet from 'react-native-actions-sheet';

import { PageWrapper, Header, Input, WarningModal } from 'src/components';
import RegionItem from '../Components/RegionItem';
import RangeCalendar from 'src/components/Calendars/RangeCalendar';

import { StoreType, storage } from 'src/storage';
import { Colors } from 'src/theme';
import { NAVIGATION_PAGES } from 'src/types';
import { RegionAddData } from '../utils/types';
import {
  useGetTripQuery,
  usePostDeleteTripMutation,
  usePostUpdateTripMutation,
  usePostSetNewTripMutation
} from '@api/trips';
import { qualityOptions } from '../utils/constants';
import { styles } from './styles';

import CalendarSvg from '../../../../../assets/icons/calendar.svg';
import { ActivityIndicator } from 'react-native-paper';

interface DateValue {
  year: number | null;
  month: number | null;
  day: number | null;
}

interface RegionWithDates extends RegionAddData {
  visitStartDate?: DateValue | null;
  visitEndDate?: DateValue | null;
  year_from?: number;
  year_to?: number;
  month_from?: number;
  month_to?: number;
  day_from?: number | null;
  day_to?: number | null;
}

interface DatePickerState {
  regionIndex: number;
  field: 'visitStartDate' | 'visitEndDate';
}

const AddNewTripScreen = ({ route }: { route: any }) => {
  const editTripId = route.params?.editTripId ?? null;
  const token = storage.get('token', StoreType.STRING) as string;
  const { data: editData } = useGetTripQuery(token, editTripId, Boolean(editTripId));
  const navigation = useNavigation();
  const [calendarVisible, setCalendarVisible] = useState(false);
  const [selectedDates, setSelectedDates] = useState<string | null>(null);
  const [description, setDescription] = useState<string>('');
  const [regions, setRegions] = useState<RegionWithDates[] | null>(null);
  const [disabled, setDisabled] = useState(true);
  const [isLoading, setIsLoading] = useState<string | null>(null);
  const [qualitySelectorVisible, setQualitySelectorVisible] = useState(false);
  const [selectedRegionId, setSelectedRegionId] = useState<number | null>(null);
  const [isWarningModalVisible, setIsWarningModalVisible] = useState(false);

  const [showDatePicker, setShowDatePicker] = useState<DatePickerState | null>(null);
  const actionSheetRef = useRef<any>(null);
  const [selectedYear, setSelectedYear] = useState<number | null>(new Date().getFullYear());
  const [selectedMonth, setSelectedMonth] = useState<number | null>(new Date().getMonth() + 1);
  const [selectedDay, setSelectedDay] = useState<number | null>(null);
  const [pendingDelete, setPendingDelete] = useState(false);

  const { mutate: saveNewTrip } = usePostSetNewTripMutation();
  const { mutate: updateTrip } = usePostUpdateTripMutation();
  const { mutate: deleteTrip } = usePostDeleteTripMutation();

  const fillRegionDatesFromSelectedDates = (regionsToUpdate: RegionWithDates[]) => {
    if (!selectedDates || !regionsToUpdate) return regionsToUpdate;

    const from = selectedDates.split(' - ')[0];
    const to = selectedDates.split(' - ')[1];

    const updatedRegions = regionsToUpdate.map((region) => {
      const hasEmptyStartDate = !region.visitStartDate?.year || !region.visitStartDate?.month;
      const hasEmptyEndDate = !region.visitEndDate?.year || !region.visitEndDate?.month;

      if (hasEmptyStartDate || hasEmptyEndDate) {
        const updatedRegion = { ...region };

        if (hasEmptyStartDate) {
          updatedRegion.visitStartDate = {
            year: moment(from, 'YYYY-MM-DD').year(),
            month: moment(from, 'YYYY-MM-DD').month() + 1,
            day: null
          };
          updatedRegion.year_from = moment(from, 'YYYY-MM-DD').year();
          updatedRegion.month_from = moment(from, 'YYYY-MM-DD').month() + 1;
        }

        if (hasEmptyEndDate) {
          updatedRegion.visitEndDate = {
            year: moment(to, 'YYYY-MM-DD').year(),
            month: moment(to, 'YYYY-MM-DD').month() + 1,
            day: null
          };
          updatedRegion.year_to = moment(to, 'YYYY-MM-DD').year();
          updatedRegion.month_to = moment(to, 'YYYY-MM-DD').month() + 1;
        }

        return updatedRegion;
      }

      return region;
    });

    return updatedRegions;
  };

  useEffect(() => {
    if (route.params?.regionsToSave) {
      setRegions((currentRegions) => {
        const newRegionsIds = route.params.regionsToSave.map((region: RegionAddData) => region.id);
        const existingRegions = currentRegions?.filter((region) =>
          newRegionsIds.includes(region.id)
        );

        const updatedRegions = route.params.regionsToSave.map((newRegion: RegionAddData) => {
          const existingRegion = existingRegions?.find((region) => region.id === newRegion.id);

          return {
            ...newRegion,
            quality: existingRegion ? existingRegion.quality : 3,
            can_be_hidden: existingRegion ? existingRegion.can_be_hidden : newRegion.hidden,
            hidden: existingRegion ? existingRegion.hidden : false,
            visitStartDate: existingRegion?.visitStartDate || {
              year: null,
              month: null,
              day: null
            },
            visitEndDate: existingRegion?.visitEndDate || {
              year: null,
              month: null,
              day: null
            }
          };
        });

        return fillRegionDatesFromSelectedDates(updatedRegions);
      });
    }
  }, [route.params?.regionsToSave]);

  function extractNumberAndExtension(path: string | null) {
    if (!path) return null;
    const slashIndex = path.lastIndexOf('/');
    return path.substring(slashIndex + 1);
  }

  useEffect(() => {
    if (editData && editData.trip) {
      setSelectedDates(editData.trip.date_from + ' - ' + editData.trip.date_to);
      setDescription(editData.trip.description);
      setRegions(
        editData.trip.regions.map((region: any) => {
          return {
            ...region,
            id: region.region,
            flag1: extractNumberAndExtension(region.flag1),
            flag2: extractNumberAndExtension(region.flag2),
            visitStartDate: {
              year: region.year_from || null,
              month: region.month_from || null,
              day: region.day_from || null
            },
            visitEndDate: {
              year: region.year_to || null,
              month: region.month_to || null,
              day: region.day_to || null
            }
          };
        })
      );
    }
  }, [editData]);

  useEffect(() => {
    if (regions?.length && selectedDates) {
      setRegions((currentRegions) => {
        if (!currentRegions) return null;
        return fillRegionDatesFromSelectedDates(currentRegions);
      });
      setDisabled(false);
    } else {
      setDisabled(true);
    }
  }, [selectedDates]);

  useEffect(() => {
    setDisabled(!(regions?.length && selectedDates));
  }, [regions, selectedDates]);

  const currentYear = new Date().getFullYear();
  const years = ['-', ...Array.from({ length: 120 }, (_, i) => (currentYear - 80 + i).toString())];

  const getAvailableMonths = (year: number | null) => {
    const allMonths = [
      { label: '-', value: null },
      { label: 'Jan', value: 1 },
      { label: 'Feb', value: 2 },
      { label: 'Mar', value: 3 },
      { label: 'Apr', value: 4 },
      { label: 'May', value: 5 },
      { label: 'Jun', value: 6 },
      { label: 'Jul', value: 7 },
      { label: 'Aug', value: 8 },
      { label: 'Sep', value: 9 },
      { label: 'Oct', value: 10 },
      { label: 'Nov', value: 11 },
      { label: 'Dec', value: 12 }
    ];

    return allMonths;
  };

  const months = getAvailableMonths(selectedYear);

  const getDaysInMonth = (
    year: number | null,
    month: number | null
  ): Array<{ label: string; value: number | null }> => {
    if (!year || !month) return [{ label: '-', value: null }];

    const daysCount = moment(`${year}-${month}`, 'YYYY-M').daysInMonth();
    const days = [{ label: '-', value: null }];

    for (let i = 1; i <= daysCount; i++) {
      days.push({ label: i.toString(), value: i as never });
    }

    return days;
  };

  const days = getDaysInMonth(selectedYear, selectedMonth);

  const openDatePicker = (
    index: number,
    field: 'visitStartDate' | 'visitEndDate',
    initialDate?: DateValue | null
  ) => {
    setShowDatePicker({ regionIndex: index, field });

    if (initialDate && initialDate.year) {
      setSelectedYear(initialDate.year || null);
      setSelectedMonth(initialDate.month || null);
      setSelectedDay(initialDate.day || null);
    } else {
      setSelectedYear(null);
      setSelectedMonth(null);
      setSelectedDay(null);
    }

    actionSheetRef.current?.show();
  };

  const handleDateConfirm = () => {
    if (showDatePicker) {
      const { regionIndex, field } = showDatePicker;
      const dateValue: DateValue = {
        year: selectedYear || null,
        month: selectedMonth || null,
        day: selectedDay || null
      };

      setRegions((prev) => {
        if (!prev) return null;
        const newRegions = [...prev];
        newRegions[regionIndex] = { ...newRegions[regionIndex], [field]: dateValue };
        return newRegions;
      });

      setShowDatePicker(null);
      actionSheetRef.current?.hide();
    }
  };

  const handleDateCancel = () => {
    setShowDatePicker(null);
    actionSheetRef.current?.hide();
  };

  const changeQualityForRegion = (index: number | null, newQuality: number) => {
    if (index === null || index === undefined) return;

    regions &&
      setRegions((prev) => {
        if (!prev) return null;
        const newRegions = [...prev];
        newRegions[index] = { ...newRegions[index], quality: newQuality };
        return newRegions;
      });
  };

  const changeHiddenForRegion = (index: number | null) => {
    if (index === null || index === undefined) return;

    regions &&
      setRegions((prev) => {
        if (!prev) return null;
        const newRegions = [...prev];
        newRegions[index] = { ...newRegions[index], hidden: !newRegions[index].hidden };
        return newRegions;
      });
  };

  const duplicateRegion = (index: number) => {
    if (!regions) return;
    const regionToCopy = regions[index];
    const copy = { ...regionToCopy };
    const newRegions = [...regions];
    newRegions.splice(index + 1, 0, copy);
    setRegions(newRegions);
  };

  const moveRegionUp = (index: number) => {
    if (index <= 0 || !regions) return;
    const newRegions = [...regions];
    [newRegions[index - 1], newRegions[index]] = [newRegions[index], newRegions[index - 1]];
    setRegions(newRegions);
  };

  const moveRegionDown = (index: number) => {
    if (!regions || index >= regions.length - 1) return;
    const newRegions = [...regions];
    [newRegions[index + 1], newRegions[index]] = [newRegions[index], newRegions[index + 1]];
    setRegions(newRegions);
  };

  const handleDeleteRegion = (index: number) => {
    if (!regions) return;
    const updated = [...regions];
    updated.splice(index, 1);
    setRegions(updated);
  };

  const handleDeleteTrip = async () => {
    setIsWarningModalVisible(false);
    setPendingDelete(true);
  };

  const handleSaveNewTrip = () => {
    if (regions && selectedDates) {
      setIsLoading('save');
      const regionsData = regions.map((region) => {
        return {
          id: region.id,
          quality: region.quality ?? 3,
          hidden: region.hidden,
          year_from: region.visitStartDate?.year || null,
          year_to: region.visitEndDate?.year || null,
          month_from: region.visitStartDate?.month || null,
          month_to: region.visitEndDate?.month || null,
          day_from: region.visitStartDate?.day || null,
          day_to: region.visitEndDate?.day || null
        };
      });

      if (regionsData.length > 30) {
        Alert.alert('One trip cannot have more than 30 regions.');
        setIsLoading(null);
        return;
      }

      saveNewTrip(
        {
          token,
          date_from: selectedDates.split(' - ')[0],
          date_to: selectedDates.split(' - ')[1],
          description,
          regions: regionsData
        },
        {
          onSuccess: (res) => {
            if (res && res.result === 'OK') {
              navigation.popTo(...([NAVIGATION_PAGES.TRIPS, { saved: true }] as never));
            }
            setIsLoading(null);
          },
          onError: () => {
            setIsLoading(null);
          }
        }
      );
    }
  };

  const handleUpdateTrip = () => {
    if (regions && selectedDates) {
      setIsLoading('update');
      const regionsData = regions.map((region) => {
        return {
          id: region.id,
          quality: region.quality ?? 3,
          hidden: region.hidden,
          year_from: region.visitStartDate?.year || null,
          year_to: region.visitEndDate?.year || null,
          month_from: region.visitStartDate?.month || null,
          month_to: region.visitEndDate?.month || null,
          day_from: region.visitStartDate?.day || null,
          day_to: region.visitEndDate?.day || null
        };
      });

      if (regionsData.length > 30) {
        Alert.alert('One trip cannot have more than 30 regions.');
        setIsLoading(null);
        return;
      }

      updateTrip(
        {
          token,
          trip_id: editTripId,
          date_from: selectedDates.split(' - ')[0],
          date_to: selectedDates.split(' - ')[1],
          description,
          regions: regionsData
        },
        {
          onSuccess: (res) => {
            if (res && res.result === 'OK') {
              navigation.popTo(...([NAVIGATION_PAGES.TRIPS, { updated: true }] as never));
            }
            setIsLoading(null);
          },
          onError: () => {
            setIsLoading(null);
          }
        }
      );
    }
  };

  return (
    <PageWrapper style={{ flex: 1 }}>
      <Header label={editTripId ? 'Edit Trip' : 'Add New Trip'} />
      <ScrollView
        contentContainerStyle={{ flexGrow: 1, gap: 16 }}
        showsVerticalScrollIndicator={false}
      >
        <TouchableOpacity style={styles.regionSelector} onPress={() => setCalendarVisible(true)}>
          <CalendarSvg fill={Colors.LIGHT_GRAY} />
          <Text style={styles.regionText}>{selectedDates ?? 'Add dates'}</Text>
        </TouchableOpacity>

        <Input
          placeholder="Add description and all interesting moments of your trip"
          inputMode={'text'}
          onChange={(text) => setDescription(text)}
          value={description}
          header="Description"
          height={54}
          multiline={true}
        />

        <View style={{ marginBottom: 8 }}>
          <Text style={styles.regionsLabel}>Regions</Text>
          <TouchableOpacity
            style={styles.addRegionBtn}
            onPress={() =>
              navigation.navigate(
                ...([
                  NAVIGATION_PAGES.ADD_REGIONS,
                  { regionsParams: regions, editId: editTripId }
                ] as never)
              )
            }
          >
            <Text style={styles.addRegionBtntext}>Add Region</Text>
          </TouchableOpacity>
          {regions && regions.length ? (
            <View style={styles.regionsContainer}>
              {regions.map((region, index) => {
                return (
                  <RegionItem
                    key={`${region.id}-${index}`}
                    region={region}
                    index={index}
                    total={regions.length}
                    onDelete={() => handleDeleteRegion(index)}
                    onQualityChange={() => {
                      setSelectedRegionId(index);
                      setQualitySelectorVisible(true);
                    }}
                    onHiddenChange={() => changeHiddenForRegion(index)}
                    openDatePicker={openDatePicker}
                    visitStartDate={region.visitStartDate}
                    visitEndDate={region.visitEndDate}
                    onDuplicate={() => duplicateRegion(index)}
                    onMoveUp={() => moveRegionUp(index)}
                    onMoveDown={() => moveRegionDown(index)}
                  />
                );
              })}
            </View>
          ) : (
            <Text style={styles.noRegiosText}>No regions at the moment</Text>
          )}
        </View>
      </ScrollView>

      <View style={styles.tabContainer}>
        {editTripId ? (
          <>
            <TouchableOpacity
              style={[styles.tabStyle, styles.deleteTab]}
              onPress={() => setIsWarningModalVisible(true)}
              disabled={isLoading === 'delete'}
            >
              {isLoading === 'delete' ? (
                <ActivityIndicator size={18} color={Colors.RED} />
              ) : (
                <Text style={[styles.tabText, styles.deleteTabText]}>Delete Trip</Text>
              )}
            </TouchableOpacity>
            <TouchableOpacity
              style={[
                styles.tabStyle,
                styles.addNewTab,
                disabled && { backgroundColor: Colors.LIGHT_GRAY, borderColor: Colors.LIGHT_GRAY }
              ]}
              onPress={handleUpdateTrip}
              disabled={disabled || isLoading === 'update'}
            >
              {isLoading === 'update' ? (
                <ActivityIndicator size={18} color={Colors.WHITE} />
              ) : (
                <Text style={[styles.tabText, styles.addNewTabText]}>Save Trip</Text>
              )}
            </TouchableOpacity>
          </>
        ) : (
          <TouchableOpacity
            style={[
              styles.tabStyle,
              styles.addNewTab,
              disabled && { backgroundColor: Colors.LIGHT_GRAY, borderColor: Colors.LIGHT_GRAY },
              { paddingVertical: 12 }
            ]}
            onPress={handleSaveNewTrip}
            disabled={disabled || isLoading === 'save'}
          >
            {isLoading === 'save' ? (
              <ActivityIndicator size={18} color={Colors.WHITE} />
            ) : (
              <Text style={[styles.tabText, styles.addNewTabText]}>Add New Trip</Text>
            )}
          </TouchableOpacity>
        )}
      </View>

      <ActionSheet
        ref={actionSheetRef}
        gestureEnabled={false}
        headerAlwaysVisible={true}
        onTouchBackdrop={handleDateConfirm}
        CustomHeaderComponent={
          <View style={styles.datePickerHeader}>
            <TouchableOpacity onPress={handleDateCancel}>
              <Text style={styles.datePickerCancel}>Cancel</Text>
            </TouchableOpacity>
            <Text style={styles.datePickerTitle}>Select Date</Text>
            <TouchableOpacity onPress={handleDateConfirm}>
              <Text style={styles.datePickerConfirm}>Done</Text>
            </TouchableOpacity>
          </View>
        }
      >
        <View style={styles.wheelContainer}>
          <View style={styles.wheelColumn}>
            <Text style={styles.wheelLabel}>Day</Text>
            <WheelPicker
              style={styles.wheelPicker}
              textColor={Colors.DARK_BLUE}
              itemStyle={{ fontSize: 16, fontFamily: 'montserrat-600', padding: 0 }}
              pickerData={days?.map((d) => d.label)}
              selectedValue={days?.find((d) => d.value === selectedDay)?.label || '-'}
              onValueChange={(value: string) => {
                const day = days?.find((d) => d.label === value);
                setSelectedDay(day?.value || null);
              }}
            />
          </View>

          <View style={styles.wheelColumn}>
            <Text style={styles.wheelLabel}>Month</Text>
            <WheelPicker
              style={styles.wheelPicker}
              textColor={Colors.DARK_BLUE}
              itemStyle={{
                fontSize: 16,
                fontFamily: 'montserrat-600'
              }}
              pickerData={months ? months?.map((m) => m.label) : []}
              selectedValue={months.find((m) => m.value === selectedMonth)?.label || '-'}
              onValueChange={(value: string) => {
                const month = months?.find((m) => m.label === value);
                setSelectedMonth(month?.value || null);
                if (!month?.value) setSelectedDay(null);
              }}
            />
          </View>

          <View style={styles.wheelColumn}>
            <Text style={styles.wheelLabel}>Year</Text>
            <WheelPicker
              style={styles.wheelPicker}
              textColor={Colors.DARK_BLUE}
              itemStyle={{ fontSize: 16, fontFamily: 'montserrat-600' }}
              pickerData={years}
              selectedValue={selectedYear ? selectedYear.toString() : '-'}
              onValueChange={(value: string) => {
                if (value === '-') {
                  setSelectedYear(null);
                  setSelectedMonth(null);
                  setSelectedDay(null);
                } else {
                  setSelectedYear(Number(value));
                }
              }}
            />
          </View>
        </View>
      </ActionSheet>

      <RangeCalendar
        isModalVisible={calendarVisible}
        closeModal={(startDate?: string | null, endDate?: string | null) => {
          startDate &&
            setSelectedDates(
              startDate.toString() + ' - ' + (endDate ? endDate?.toString() : startDate?.toString())
            );
          setCalendarVisible(false);
        }}
      />
      <ReactModal
        isVisible={qualitySelectorVisible}
        onBackdropPress={() => setQualitySelectorVisible(false)}
        style={styles.modal}
        statusBarTranslucent={true}
        presentationStyle="overFullScreen"
      >
        <View style={styles.wrapper}>
          <View style={{ paddingBottom: 16 }}>
            {qualityOptions.map((option) => (
              <TouchableOpacity
                key={option.id}
                style={styles.btnOption}
                onPress={() => {
                  setQualitySelectorVisible(false);
                  changeQualityForRegion(selectedRegionId, option.id);
                }}
              >
                <Text style={styles.btnOptionText}>{option.name}</Text>
              </TouchableOpacity>
            ))}
          </View>
        </View>
      </ReactModal>
      <WarningModal
        type={'delete'}
        isVisible={isWarningModalVisible}
        onClose={() => setIsWarningModalVisible(false)}
        title="Delete Trip"
        message="Are you sure you want to delete your trip?"
        action={handleDeleteTrip}
        onModalHide={() => {
          if (pendingDelete) {
            setPendingDelete(false);
            setIsLoading('delete');
            deleteTrip(
              {
                token,
                trip_id: editTripId
              },
              {
                onSuccess: (res) => {
                  if (res && res.result === 'OK') {
                    navigation.popTo(...([NAVIGATION_PAGES.TRIPS, { deleted: true }] as never));
                  }
                  setIsLoading(null);
                },
                onError: () => {
                  setIsLoading(null);
                }
              }
            );
          }
        }}
      />
    </PageWrapper>
  );
};

export default AddNewTripScreen;
