import React, { useEffect, useState } from 'react';
import { View, Text } from 'react-native';
import { Modal } from '../../Modal';
import DateTimePicker, { DateType } from 'react-native-ui-datepicker';
import dayjs from 'dayjs';
import 'dayjs/locale/en';
import calendar from 'dayjs/plugin/calendar';
import updateLocale from 'dayjs/plugin/updateLocale';
import localeData from 'dayjs/plugin/localeData';
import customParseFormat from 'dayjs/plugin/customParseFormat';

dayjs.locale('en');
dayjs.extend(calendar);
dayjs.extend(updateLocale);
dayjs.extend(localeData);
dayjs.extend(customParseFormat);

import { styles } from './style';
import { Colors } from '../../../theme';
import { Button } from 'src/components/Button';
import { ButtonVariants } from 'src/types/components';
import Navigation from './Navigation';

export default function RangeCalendar({
  isModalVisible,
  closeModal,
  allowRangeSelection = true,
  disableFutureDates = false,
  disablePastDates = false,
  highlightedDates,
  selectedDate,
  minDate: externalMinDate,
  maxDate: externalMaxDate,
  initialStartDate,
  initialEndDate,
  initialYear,
  initialMonth,
  withHint = false
}: {
  isModalVisible: boolean;
  closeModal: (startDate?: string | null, endDate?: string | null) => void;
  allowRangeSelection?: boolean;
  disableFutureDates?: boolean;
  disablePastDates?: boolean;
  highlightedDates?: string[];
  selectedDate?: string;
  minDate?: string | Date | dayjs.Dayjs;
  maxDate?: string | Date | dayjs.Dayjs;
  initialStartDate?: string | null;
  initialEndDate?: string | null;
  initialYear?: number;
  initialMonth?: number;
  withHint?: boolean;
}) {
  const [selectedStartDate, setSelectedStartDate] = useState<string | null>(null);
  const [selectedEndDate, setSelectedEndDate] = useState<string | null>(null);
  const [singleDate, setSingleDate] = useState<DateType>(undefined);
  const [startDate, setStartDate] = useState<DateType>(undefined);
  const [endDate, setEndDate] = useState<DateType>(undefined);
  const [currentMonth, setCurrentMonth] = useState<number | undefined>(undefined);
  const [currentYear, setCurrentYear] = useState<number | undefined>(undefined);

  const computedMinDate = externalMinDate
    ? dayjs(externalMinDate)
    : highlightedDates && highlightedDates.length > 0
      ? dayjs(highlightedDates[0])
      : undefined;

  const computedMaxDate = externalMaxDate
    ? dayjs(externalMaxDate)
    : highlightedDates && highlightedDates.length > 0
      ? dayjs(highlightedDates[highlightedDates.length - 1])
      : undefined;

  useEffect(() => {
    if (!isModalVisible) return;

    if (allowRangeSelection) {
      if (initialStartDate) {
        const startDateObj = dayjs(initialStartDate);
        setSelectedStartDate(initialStartDate);
        setStartDate(startDateObj);
        setCurrentMonth(startDateObj.month());
        setCurrentYear(startDateObj.year());
      } else {
        if (typeof initialYear === 'number' && initialYear !== 1) {
          setCurrentYear(initialYear);
        }

        if (typeof initialMonth === 'number') {
          setCurrentMonth(initialMonth - 1);
        }
      }
      if (initialEndDate) {
        setSelectedEndDate(initialEndDate);
        setEndDate(dayjs(initialEndDate));
      }
    } else if (selectedDate) {
      const dateObj = dayjs(selectedDate);
      setSelectedStartDate(selectedDate);
      setSingleDate(dateObj);
      setCurrentMonth(dateObj.month());
      setCurrentYear(dateObj.year());
    }
  }, [
    isModalVisible,
    initialStartDate,
    initialEndDate,
    selectedDate,
    allowRangeSelection,
    initialYear,
    initialMonth
  ]);

  const getDisabledDates = (date: DateType) => {
    const dateString = dayjs(date).format('YYYY-MM-DD');

    if (disableFutureDates) {
      if (dayjs(date).isAfter(dayjs(), 'day')) {
        return true;
      }
    }

    if (disablePastDates) {
      if (dayjs(date).isBefore(dayjs(), 'day')) {
        return true;
      }
    }

    if (highlightedDates && highlightedDates.length > 0) {
      return !highlightedDates.includes(dateString);
    }

    return false;
  };

  const handleDateChange = (params: any) => {
    if (allowRangeSelection) {
      setStartDate(params.startDate);
      setEndDate(params.endDate);
      if (params.startDate) {
        setSelectedStartDate(dayjs(params.startDate).format('YYYY-MM-DD'));
      }
      if (params.endDate) {
        setSelectedEndDate(dayjs(params.endDate).format('YYYY-MM-DD'));
      } else {
        setSelectedEndDate(null);
      }
    } else {
      setSingleDate(params.date);
      setSelectedStartDate(dayjs(params.date).format('YYYY-MM-DD'));
      setSelectedEndDate(null);
    }
  };

  const resetSelections = () => {
    closeModal();
    setSelectedStartDate(null);
    setSelectedEndDate(null);
    setStartDate(undefined);
    setEndDate(undefined);
    setSingleDate(undefined);
    setTimeout(() => {
      setCurrentMonth(undefined);
      setCurrentYear(undefined);
    }, 200);
  };

  const handleClose = () => {
    closeModal(selectedStartDate, selectedEndDate);
    setSelectedStartDate(null);
    setSelectedEndDate(null);
    setStartDate(undefined);
    setEndDate(undefined);
    setSingleDate(undefined);
    setTimeout(() => {
      setCurrentMonth(undefined);
      setCurrentYear(undefined);
    }, 200);
  };

  return (
    <Modal
      visibleInPercent={'auto'}
      visible={isModalVisible}
      onRequestClose={resetSelections}
      headerTitle={allowRangeSelection ? 'Select Dates' : 'Select Date'}
    >
      <View style={styles.modalContent}>
        {startDate && endDate && withHint ? (
          <Text style={{ color: Colors.TEXT_GRAY, fontSize: 12, textAlign: 'center', fontWeight: '500' }}>
            Double-tap to mark the first day of your trip.
          </Text>
        ) : null}
        <DateTimePicker
          key={`${currentMonth}-${currentYear}`}
          mode={allowRangeSelection ? 'range' : 'single'}
          date={singleDate}
          startDate={startDate}
          endDate={endDate}
          month={currentMonth}
          year={currentYear}
          onChange={handleDateChange}
          minDate={computedMinDate}
          maxDate={computedMaxDate}
          disabledDates={getDisabledDates}
          firstDayOfWeek={1}
          timePicker={false}
          showOutsideDays={true}
          weekdaysFormat={'short'}
          components={{
            IconPrev: <Navigation direction="prev" />,
            IconNext: <Navigation direction="next" />
          }}
          styles={{
            header: {
              paddingBottom: 10
            },
            month_selector_label: {
              color: Colors.DARK_BLUE,
              fontWeight: 'bold',
              fontSize: 15
            },
            year_selector_label: {
              color: Colors.DARK_BLUE,
              fontWeight: 'bold',
              fontSize: 15
            },
            button_prev: {},
            button_next: {},
            weekday_label: {
              color: Colors.DARK_BLUE,
              fontWeight: 'bold',
              fontSize: 12
            },
            days: {},
            day_cell: {},
            day: {},
            day_label: {
              color: Colors.DARK_BLUE,
              fontSize: 14,
              fontWeight: 'normal'
            },
            today: {
              borderWidth: 1,
              borderRadius: 23,
              width: 46,
              height: 46,
              maxHeight: 46,
              borderColor: Colors.ORANGE
            },
            today_label: {
              color: Colors.DARK_BLUE,
              fontWeight: '500'
            },
            selected: {
              backgroundColor: Colors.ORANGE,
              borderRadius: 23,
              width: 46,
              height: 46,
              maxHeight: 46,
              marginVertical: 'auto',
              alignItems: 'center',
              justifyContent: 'center'
            },
            selected_label: {
              color: 'white',
              fontWeight: '500'
            },
            range_start: {
              backgroundColor: Colors.ORANGE,
              borderRadius: 23,
              width: 46,
              height: 46,
              alignItems: 'center',
              justifyContent: 'center'
            },
            range_start_label: {
              color: 'white'
            },
            range_end: {
              backgroundColor: Colors.ORANGE,
              borderRadius: 23,
              width: 46,
              height: 46,
              alignItems: 'center',
              justifyContent: 'center'
            },
            range_end_label: {
              color: 'white'
            },
            range_middle_label: {
              color: Colors.DARK_BLUE,
              fontWeight: '500'
            },
            range_fill: {
              backgroundColor: Colors.ORANGE,
              opacity: 0.2
            },
            disabled: {
              opacity: 0.3
            },
            disabled_label: {
              color: Colors.TEXT_GRAY
            },
            outside_label: {
              color: Colors.LIGHT_GRAY
            }
          }}
        />
      </View>
      <View style={styles.modalFooter}>
        <Button
          children="Done"
          onPress={handleClose}
          disabled={!selectedStartDate}
          variant={!selectedStartDate ? ButtonVariants.OPACITY : ButtonVariants.FILL}
          containerStyles={{ borderWidth: 0 }}
        />
      </View>
    </Modal>
  );
}
