import React, { useEffect, useRef, useState } from 'react';
import {
  View,
  Text,
  TouchableOpacity,
  StyleSheet,
  Animated,
  LayoutChangeEvent,
  Platform
} from 'react-native';
import { Picker as WheelPicker } from 'react-native-wheel-pick';
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 type CalendarMode = 'exact' | 'approx';

const CURRENT_YEAR = dayjs().year();

const YEAR_STRINGS: string[] = Array.from(
  { length: 100 },
  (_, i) => String(CURRENT_YEAR + 50 - i)
);

const FIXED_CONTENT_HEIGHT = 380;

function TabSwitcher({
  activeTab,
  onTabChange
}: {
  activeTab: CalendarMode;
  onTabChange: (tab: CalendarMode) => void;
}) {
  const slideAnim = useRef(new Animated.Value(activeTab === 'exact' ? 0 : 1)).current;
  const [pillWidth, setPillWidth] = useState(0);

  useEffect(() => {
    Animated.spring(slideAnim, {
      toValue: activeTab === 'exact' ? 0 : 1,
      useNativeDriver: true,
      tension: 68,
      friction: 12
    }).start();
  }, [activeTab]);

  const handleLayout = (e: LayoutChangeEvent) => {
    setPillWidth((e.nativeEvent.layout.width - 8) / 2);
  };

  const translateX = slideAnim.interpolate({
    inputRange: [0, 1],
    outputRange: [0, pillWidth]
  });

  return (
    <View style={tabStyles.wrapper} onLayout={handleLayout}>
      <Animated.View style={[tabStyles.pill, { width: pillWidth, transform: [{ translateX }] }]} />
      {(['exact', 'approx'] as CalendarMode[]).map((tab) => (
        <TouchableOpacity
          key={tab}
          style={tabStyles.tab}
          onPress={() => onTabChange(tab)}
          activeOpacity={0.85}
        >
          <Text style={[tabStyles.label, activeTab === tab && tabStyles.labelActive]}>
            {tab === 'exact' ? 'Exact dates' : 'Year'}
          </Text>
        </TouchableOpacity>
      ))}
    </View>
  );
}

const tabStyles = StyleSheet.create({
  wrapper: {
    flexDirection: 'row',
    backgroundColor: Colors.FILL_LIGHT,
    borderRadius: 50,
    padding: 4,
    marginHorizontal: 16,
    marginBottom: 12,
    position: 'relative',
    overflow: 'hidden'
  },
  pill: {
    position: 'absolute',
    top: 4,
    left: 4,
    bottom: 4,
    borderRadius: 50,
    backgroundColor: Colors.DARK_BLUE,
    shadowColor: '#000',
    shadowOffset: { width: 0, height: 2 },
    shadowOpacity: 0.14,
    shadowRadius: 4,
    elevation: 4
  },
  tab: {
    flex: 1,
    paddingVertical: 8,
    alignItems: 'center',
    zIndex: 1
  },
  label: {
    fontSize: 14,
    fontWeight: '500',
    color: Colors.TEXT_GRAY
  },
  labelActive: {
    color: Colors.WHITE,
    fontWeight: '600'
  }
});

function YearWheelPicker({
  selectedYear,
  onYearChange
}: {
  selectedYear: number;
  onYearChange: (year: number) => void;
}) {
  return (
    <View
      style={[wheelStyles.container, Platform.OS === 'android' ? { justifyContent: 'center' } : {}]}
    >
      <WheelPicker
        style={[wheelStyles.wheel, Platform.OS === 'android' ? { height: '75%' } : {}]}
        pickerData={YEAR_STRINGS}
        selectedValue={String(selectedYear)}
        onValueChange={(value: string) => onYearChange(Number(value))}
        textColor={Colors.TEXT_GRAY}
        textSize={22}
        selectTextColor={Colors.DARK_BLUE}
        isAtmospheric={true}
        isCyclic={false}
        isShowSelectLine={true}
        selectLineColor={Colors.ORANGE}
        selectLineSize={1}
        itemStyle={{
          fontSize: 22,
          fontFamily: 'montserrat-600',
          height: 380
        }}
        selectedItemTextStyle={{
          fontSize: 30,
          fontFamily: 'montserrat-700',
          color: Colors.DARK_BLUE
        }}
      />
    </View>
  );
}

const wheelStyles = StyleSheet.create({
  container: {
    flex: 1,
    alignItems: 'center'
  },
  wheel: {
    width: '100%',
    backgroundColor: 'transparent'
  }
});

export default function RangeCalendarWithTabs({
  isModalVisible,
  closeModal,
  allowRangeSelection = true,
  disableFutureDates = false,
  disablePastDates = false,
  highlightedDates,
  selectedDate,
  minDate: externalMinDate,
  maxDate: externalMaxDate,
  initialStartDate,
  initialEndDate,
  initialYear,
  initialMonth,
  withHint = false,
  defaultMode = 'exact',
  initialApproxYear
}: {
  isModalVisible: boolean;
  closeModal: (
    startDate?: string | null,
    endDate?: string | null,
    approxYear?: number | 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;
  defaultMode?: CalendarMode;
  initialApproxYear?: number | null;
}) {
  const fallbackYear = CURRENT_YEAR;

  const [activeTab, setActiveTab] = useState<CalendarMode>(defaultMode);
  const [selectedYear, setSelectedYear] = useState<number>(initialApproxYear ?? fallbackYear);

  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?.length
      ? dayjs(highlightedDates[0])
      : undefined;

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

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

    setActiveTab(defaultMode);

    setSelectedYear(
      initialApproxYear && YEAR_STRINGS.includes(String(initialApproxYear))
        ? initialApproxYear
        : fallbackYear
    );

    if (allowRangeSelection) {
      if (initialStartDate) {
        const s = dayjs(initialStartDate);
        setSelectedStartDate(initialStartDate);
        setStartDate(s);
        setCurrentMonth(s.month());
        setCurrentYear(s.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 d = dayjs(selectedDate);
      setSelectedStartDate(selectedDate);
      setSingleDate(d);
      setCurrentMonth(d.month());
      setCurrentYear(d.year());
    }
  }, [
    isModalVisible,
    defaultMode,
    initialApproxYear,
    initialStartDate,
    initialEndDate,
    selectedDate,
    allowRangeSelection,
    initialYear,
    initialMonth
  ]);

  const getDisabledDates = (date: DateType) => {
    const ds = dayjs(date).format('YYYY-MM-DD');
    if (disableFutureDates && dayjs(date).isAfter(dayjs(), 'day')) return true;
    if (disablePastDates && dayjs(date).isBefore(dayjs(), 'day')) return true;
    if (highlightedDates?.length) return !highlightedDates.includes(ds);
    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'));
      setSelectedEndDate(params.endDate ? dayjs(params.endDate).format('YYYY-MM-DD') : null);
    } else {
      setSingleDate(params.date);
      setSelectedStartDate(dayjs(params.date).format('YYYY-MM-DD'));
      setSelectedEndDate(null);
    }
  };

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

  const resetSelections = () => {
    closeModal();
    clearAll();
  };

  const handleClose = () => {
    if (activeTab === 'approx') {
      closeModal(null, null, selectedYear);
    } else {
      closeModal(selectedStartDate, selectedEndDate, null);
    }
    clearAll();
  };

  const isDoneEnabled = activeTab === 'approx' ? !!selectedYear : !!selectedStartDate;

  return (
    <Modal
      visibleInPercent={'auto'}
      visible={isModalVisible}
      onRequestClose={resetSelections}
      headerTitle={allowRangeSelection ? 'Select Dates' : 'Select Date'}
    >
      <View style={styles.modalContent}>
        <TabSwitcher activeTab={activeTab} onTabChange={setActiveTab} />

        <View style={{ height: FIXED_CONTENT_HEIGHT }}>
          <View
            style={[StyleSheet.absoluteFill, { opacity: activeTab === 'exact' ? 1 : 0 }]}
            pointerEvents={activeTab === 'exact' ? 'auto' : 'none'}
          >
            {startDate && endDate && withHint && (
              <Text
                style={{
                  color: Colors.TEXT_GRAY,
                  fontSize: 12,
                  textAlign: 'center',
                  fontWeight: '500',
                  marginBottom: 8
                }}
              >
                Double-tap to mark the first day of your trip.
              </Text>
            )}
            <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={[StyleSheet.absoluteFill, { opacity: activeTab === 'approx' ? 1 : 0 }]}
            pointerEvents={activeTab === 'approx' ? 'auto' : 'none'}
          >
            <YearWheelPicker selectedYear={selectedYear} onYearChange={setSelectedYear} />
          </View>
        </View>
      </View>

      <View style={styles.modalFooter}>
        <Button
          children="Done"
          onPress={handleClose}
          disabled={!isDoneEnabled}
          variant={!isDoneEnabled ? ButtonVariants.OPACITY : ButtonVariants.FILL}
          containerStyles={{ borderWidth: 0 }}
        />
      </View>
    </Modal>
  );
}
