import {
    useImperativeHandle,
    useLayoutEffect,
    forwardRef,
    useEffect,
    useState,
    type Ref,
    useRef
} from "react";
import {
    TouchableOpacity,
    type ViewStyle,
    View
} from "react-native";
import type {
    IYearSelectorRef,
    CalendarYear
} from "./type";
import type IYearSelectorProps from "./type";
import stylesheet, {
    useStyles
} from "./stylesheet";
import {
    dateSelect
} from "./util";
import {
    NCoreUIKitLocalize,
    NCoreUIKitTheme,
    NCoreUIKitToast
} from "../../core/hooks";
import {
    type Mutable
} from "../../types";
import {
    ChevronRight as ChevronRightIcon,
    ChevronLeft as ChevronLeftIcon
} from "lucide-react-native";
import moment from "moment";
import Text from "../text";
import {
    webStyle
} from "../../utils";

const YEAR_LINES = [
    [
        0,
        1,
        2
    ],
    [
        3,
        4,
        5
    ],
    [
        6,
        7,
        8
    ],
    [
        9,
        10,
        11
    ]
];

const YearSelector = ({
    multipleSelectMinimumRequiredDayCount,
    isShowTodayIndicator = true,
    viewDate: viewDateProp,
    multipleSelectDayLimit,
    setIsSheetContentReady,
    selectMultipleObject,
    selectObject,
    dateRange,
    maxDate,
    minDate,
    variant,
    date
}: IYearSelectorProps, ref: Ref<IYearSelectorRef>) => {
    const {
        radiuses,
        borders,
        spaces,
        colors
    } = NCoreUIKitTheme.useContext();

    const {
        localize
    } = NCoreUIKitLocalize.useContext();

    const selectDate = dateSelect({
        dateRange,
        variant,
        date
    });

    const [
        viewDate,
        setViewDate
    ] = useState(viewDateProp ? viewDateProp : selectDate);

    const [
        years,
        setYears
    ] = useState<Array<CalendarYear>>([]);

    const allSelectedYears = useRef<Array<Date>>([]);

    const {
        nextPrevToolChevronButton: nextPrevToolChevronButtonDynamicStyle,
        nextPrevToolContainer: nextPrevToolContainerDynamicStyle,
        todayIndicator: todayIndicatorDynamicStyle,
        day: dayDynamicStyle
    } = useStyles({
        radiuses,
        borders,
        colors,
        spaces
    });

    useEffect(() => {
        const allYears = getViewYears({
            tDate: viewDate
        });

        setYears(allYears);
    }, [
        dateRange,
        viewDate,
        date
    ]);

    useLayoutEffect(() => {
        if(years && years.length) setIsSheetContentReady(true);
    }, [
        years
    ]);

    useEffect(() => {
        if(viewDateProp) {
            setViewDate(viewDateProp);
        }
    }, [
        viewDateProp
    ]);

    useImperativeHandle(
        ref,
        () => ({
            changeCurrentView: (date: Date) => {
                setViewDate(date);
            }
        }),
        []
    );

    const getViewYears = ({
        tDate
    }: {
        tDate: Date
    }): Array<CalendarYear> => {
        allSelectedYears.current = [];

        const targetDate = moment(new Date(tDate));

        const startOfCalendar = targetDate.clone().subtract(5, "years").startOf("year");

        const totalYears = 12;

        const allYears = Array.from({
            length: totalYears
        }).map((_, index) => {
            const currentYear = startOfCalendar.clone().add(index, "years");

            let isSelected = false;

            if(variant === "single" && date) {
                allSelectedYears.current = [
                    date
                ];

                if(moment(currentYear).isSame(date, "year")) isSelected = true;
            } else if(variant === "range" && dateRange && dateRange.start) {
                if(dateRange.end) {
                    allSelectedYears.current = Array.from({
                        length: moment(dateRange.end).diff(dateRange.start, "years") + 1
                    }, (_, i) =>
                        moment(dateRange.start).clone().add(i, "years").toDate()
                    );

                    if(moment(currentYear).isBetween(dateRange.start, dateRange.end, "year", "[]")) isSelected = true;
                } else if(moment(currentYear).isSame(dateRange.start, "year")) {
                    allSelectedYears.current = [
                        dateRange.start
                    ];

                    isSelected = true;
                }
            }

            let isDisabled = false;

            if(minDate && moment(currentYear).isBefore(moment(minDate).startOf("year"))) {
                isDisabled = true;
            }

            if(maxDate && moment(currentYear).isAfter(moment(maxDate).endOf("year"))) {
                isDisabled = true;
            }

            const currentYearNumber = currentYear.year();

            return {
                originalIndex: allSelectedYears.current.findIndex((day) => moment(currentYear).isSame(day, "year")),
                isToday: currentYear.isSame(moment(), "year"),
                title: String(currentYearNumber),
                yearNumber: currentYearNumber,
                year: currentYearNumber,
                date: currentYear,
                isDisabled,
                isSelected
            };
        });

        return allYears;
    };

    const renderDay = ({
        yearIndex,
        yearItem
    }: {
        yearItem: CalendarYear;
        yearIndex: number;
    }) => {
        const isLastItemSelected = yearItem.isSelected && yearItem.originalIndex === allSelectedYears.current.length - 1;
        const isFirstItemSelected = yearItem.isSelected && yearItem.originalIndex === 0;

        const selectionStyle: Array<Mutable<ViewStyle> | null> = [
            isFirstItemSelected && allSelectedYears.current.length > 1 ? {
                borderBottomRightRadius: 0,
                borderTopRightRadius: 0
            } : null,
            isLastItemSelected && allSelectedYears.current.length > 1 ? {
                borderBottomLeftRadius: 0,
                borderTopLeftRadius: 0
            } : null
        ];

        let dayTitleColor: keyof NCoreUIKit.TextContentColors = "mid";

        if(yearItem.isSelected && !isLastItemSelected && !isFirstItemSelected) {
            dayTitleColor = "emphasized";

            selectionStyle.push({
                borderBottomRightRadius: 0,
                borderBottomLeftRadius: 0,
                borderTopRightRadius: 0,
                borderTopLeftRadius: 0
            });
        } else if(yearItem.isSelected) {
            dayTitleColor = "onPrimary";
        }

        if(yearItem.isDisabled) {
            dayTitleColor = "disabled";
        }

        return <TouchableOpacity
            disabled={yearItem.isDisabled}
            key={`year-${yearIndex}`}
            onPress={() => {
                if(variant === "single") {
                    const newDate = date as Date;

                    newDate.setFullYear(yearItem.date.toDate().getFullYear());

                    selectObject(newDate);
                } else if(variant === "range") {
                    if(!dateRange || !dateRange.start) {
                        selectMultipleObject({
                            start: new Date(yearItem.date.toDate().setHours(0, 0, 0)),
                            end: undefined
                        });
                        return;
                    }

                    if(dateRange && moment(dateRange.start).isSame(yearItem.date, "year")) {
                        selectMultipleObject({
                            start: undefined,
                            end: undefined
                        });
                        return;
                    }

                    if(dateRange && !dateRange.end) {
                        if(multipleSelectDayLimit && moment(yearItem.date).diff(dateRange.start, "days") >= multipleSelectDayLimit) {
                            NCoreUIKitToast.open({
                                title: localize("maximum-selection-number-of-days-limit-exceeds")
                            });
                            return;
                        }

                        if(multipleSelectMinimumRequiredDayCount && moment(yearItem.date).diff(dateRange.start, "days") + 1 < multipleSelectMinimumRequiredDayCount) {
                            NCoreUIKitToast.open({
                                title: localize("minimum-selection-number-of-days-required-not-provided")
                            });
                            return;
                        }

                        if(moment(yearItem.date).isBefore(dateRange.start)) {
                            selectMultipleObject({
                                start: new Date(yearItem.date.toDate().setHours(0, 0, 0)),
                                end: undefined
                            });
                        } else {
                            selectMultipleObject({
                                end: new Date(yearItem.date.toDate().setHours(23, 59, 59)),
                                start: dateRange?.start
                            });
                        }
                        return;
                    }

                    selectMultipleObject({
                        start: yearItem.date.toDate(),
                        end: undefined
                    });
                }
            }}
            style={[
                stylesheet.day,
                dayDynamicStyle,
                yearItem.isSelected ? {
                    backgroundColor: colors.content.container.primary,
                    borderColor: colors.content.container.primary
                } : null,
                yearItem.isSelected && !isLastItemSelected && !isFirstItemSelected ? {
                    backgroundColor: colors.content.container.emphasized,
                    borderColor: colors.content.container.emphasized
                } : null,
                yearItem.isSelected && (yearItem.isDisabled) ? {
                    opacity: 0.33
                } : null,
                ...selectionStyle
            ]}
        >
            <Text
                variant="labelLargeSize"
                color={dayTitleColor}
            >
                {yearItem.title}
            </Text>
            {
                isShowTodayIndicator && yearItem.isToday ?
                    <View
                        style={[
                            stylesheet.todayIndicator,
                            selectionStyle,
                            todayIndicatorDynamicStyle,
                    yearItem.isSelected ? {
                        borderColor: colors.content.border.subtle
                    } : null
                        ]}
                    />
                :
                    null
            }
        </TouchableOpacity>;
    };

    const renderNextPrevTool = () => {
        return <View
            style={[
                stylesheet.nextPrevToolContainer,
                nextPrevToolContainerDynamicStyle
            ]}
        >
            <TouchableOpacity
                onPress={() => {
                    const prevViewDate = moment(viewDate).clone().subtract(12, "years");
                    setViewDate(prevViewDate.toDate());
                }}
                style={[
                    nextPrevToolChevronButtonDynamicStyle
                ]}
            >
                <ChevronLeftIcon
                    color={colors.content.icon.default}
                    size={26}
                />
            </TouchableOpacity>
            <Text
                variant="labelLargeSize"
                color="high"
            >
                {
                    years && years.length ?
                        `${moment(years[0]?.date.toDate()).format("YYYY")} - ${moment(years[years.length - 1]?.date.toDate()).format("YYYY")}`
                        :
                        null
                }
            </Text>
            <TouchableOpacity
                onPress={() => {
                    const nextViewDate = moment(viewDate).clone().add(12, "years");
                    setViewDate(nextViewDate.toDate());
                }}
                style={[
                    nextPrevToolChevronButtonDynamicStyle
                ]}
            >
                <ChevronRightIcon
                    color={colors.content.icon.default}
                    size={26}
                />
            </TouchableOpacity>
        </View>;
    };

    return <View
        style={[
            stylesheet.container
        ]}
    >
        <View>
            {renderNextPrevTool()}
        </View>
        <View
            style={[
                stylesheet.contentContainer
            ]}
        >
            {years && years.length ? YEAR_LINES.map((yItem, yIndex) => {
                const currentYears = yItem.map(yI => years[yI]);

                return <View
                    key={`year-row-${yIndex}`}
                    style={[
                        stylesheet.rowContainer,
                        webStyle({
                            width: "100%"
                        })
                    ]}
                >
                    {currentYears.map((yearItem, yearIndex) => {
                        return renderDay({
                            yearItem: yearItem as CalendarYear,
                            yearIndex
                        });
                    })}
                </View>;
            }) : null}
        </View>
    </View>;
};
export default forwardRef(YearSelector);
