import React, {useCallback, useEffect, useMemo, useState} from "react";
import {Calendar} from "react-native-big-calendar";
import {ActivityIndicator, StyleSheet, TouchableOpacity, View, ViewStyle} from "react-native";
import {useGetEvents} from "@/hooks/firebase/useGetEvents";
import {useAtom, useSetAtom} from "jotai";
import {
    editVisibleAtom,
    eventForEditAtom,
    isAllDayAtom,
    isFamilyViewAtom,
    modeAtom,
    selectedDateAtom,
    selectedNewEventDateAtom,
    selectedUserAtom,
} from "@/components/pages/calendar/atoms";
import {useAuthContext} from "@/contexts/AuthContext";
import {CalendarEvent} from "@/components/pages/calendar/interfaces";
import {Text} from "react-native-ui-lib";
import {addDays, compareAsc, format, isWithinInterval, subDays} from "date-fns";
import {useCalSync} from "@/hooks/useCalSync";
import {useSyncEvents} from "@/hooks/useSyncOnScroll";
import {colorMap, getEventTextColor} from "@/constants/colorMap";
import {useGetFamilyMembers} from "@/hooks/firebase/useGetFamilyMembers";
import CachedImage from "expo-cached-image";
import { DeviceType } from "expo-device";
import * as Device from "expo-device"

interface EventCalendarProps {
    calendarHeight: number;
    // WAS USED FOR SCROLLABLE CALENDARS, PERFORMANCE WAS NOT OPTIMAL
    calendarWidth: number;
}

const getTotalMinutes = () => {
    const date = new Date();
    return Math.abs(date.getUTCHours() * 60 + date.getUTCMinutes() - 200);
};


export const MonthCalendar: React.FC<EventCalendarProps> = React.memo(
    ({calendarHeight}) => {
        const {data: events, isLoading} = useGetEvents();
        const {profileData, user} = useAuthContext();
        const [selectedDate, setSelectedDate] = useAtom(selectedDateAtom);
        const [mode, setMode] = useAtom(modeAtom);
        const [isFamilyView] = useAtom(isFamilyViewAtom);

        //tablet view filter
        const [selectedUser] = useAtom(selectedUserAtom);

        const setEditVisible = useSetAtom(editVisibleAtom);
        const [isAllDay, setIsAllDay] = useAtom(isAllDayAtom);
        const setEventForEdit = useSetAtom(eventForEditAtom);
        const setSelectedNewEndDate = useSetAtom(selectedNewEventDateAtom);

        const {isSyncing} = useSyncEvents()
        const [offsetMinutes, setOffsetMinutes] = useState(getTotalMinutes());
        useCalSync()

        const todaysDate = new Date();

        const handlePressEvent = useCallback(
            (event: CalendarEvent) => {
                if (mode === "day" || mode === "week" || mode === "3days") {
                    setEditVisible(true);
                    setEventForEdit(event);
                } else {
                    setMode("day");
                    setSelectedDate(event.start);
                }
            },
            [setEditVisible, setEventForEdit, mode]
        );

        const handlePressCell = useCallback(
            (date: Date) => {
                    date && setSelectedDate(date);
                    setTimeout(() => {
                        setMode("day");
                    }, 100)
            },
            [mode, setSelectedNewEndDate, setSelectedDate]
        );

        const handlePressDayHeader = useCallback(
            (date: Date) => {
                if (mode === "day") {
                    setIsAllDay(true);
                    setSelectedNewEndDate(date);
                    setEditVisible(true);
                }
                if (mode === 'week' || mode === '3days') {
                    setSelectedDate(date)
                    setMode("day")
                }
            },
            [mode, setSelectedNewEndDate]
        );

        const handleSwipeEnd = useCallback(
            (date: Date) => {
                setSelectedDate(date);
            },
            [setSelectedDate]
        );

        const memoizedEventCellStyle = useCallback(
            (event: CalendarEvent) => {
                let eventColor = event.eventColor;
                if (!isFamilyView && (event.attendees?.includes(user?.uid!) || event.creatorId! === user?.uid)) {
                    eventColor = profileData?.eventColor ?? colorMap.teal;
                }

                return {backgroundColor: eventColor, fontSize: 14, color: getEventTextColor(event?.eventColor)}
            },
            []
        );

        const memoizedWeekStartsOn = useMemo(
            () => (profileData?.firstDayOfWeek === "Mondays" ? 1 : 0),
            [profileData]
        );

        const isSameDate = useCallback((date1: Date, date2: Date) => {
            return (
                date1.getDate() === date2.getDate() &&
                date1.getMonth() === date2.getMonth() &&
                date1.getFullYear() === date2.getFullYear()
            );
        }, []);

        const dayHeaderColor = useMemo(() => {
            return isSameDate(todaysDate, selectedDate) ? "white" : "#4d4d4d";
        }, [selectedDate, mode]);

        const dateStyle = useMemo(() => {
            if (mode === "week" || mode === "3days") return undefined;
            return isSameDate(todaysDate, selectedDate) && mode === "day"
                ? styles.dayHeader
                : styles.otherDayHeader;
        }, [selectedDate, mode]);

        const memoizedHeaderContentStyle = useMemo(() => {
            if (mode === "day") {
                return styles.dayModeHeader;
            } else if (mode === "week" || mode === "3days") {
                return styles.weekModeHeader;
            } else if (mode === "month") {
                return styles.monthModeHeader;
            } else {
                return {};
            }
        }, [mode]);
        const {filteredEvents} = useMemo(() => {
            const startOffset = mode === "month" ? 40 : (mode === "week" || mode === "3days") ? 10 : 1;
            const endOffset = mode === "month" ? 40 : (mode === "week" || mode === "3days") ? 10 : 1;

            let eventsToFilter = events ?? [];

            if (selectedUser && Device.deviceType === DeviceType.TABLET) {
                eventsToFilter = events?.filter(event =>
                    event.attendees?.includes(selectedUser.uid) ||
                    event.creatorId === selectedUser.uid
                );
            }

            const filteredEvents =
                eventsToFilter?.filter(
                    (event) =>
                        event?.start instanceof Date &&
                        event?.end instanceof Date &&
                        isWithinInterval(event.start, {
                            start: subDays(selectedDate, startOffset),
                            end: addDays(selectedDate, endOffset),
                        }) &&
                        isWithinInterval(event.end, {
                            start: subDays(selectedDate, startOffset),
                            end: addDays(selectedDate, endOffset),
                        })
                ) ?? [];

            return {filteredEvents};
        }, [events, selectedDate, mode, selectedUser]);

        useEffect(() => {
            setOffsetMinutes(getTotalMinutes());
        }, [events, mode]);

        if (isLoading || !events) {
            return (
                <View style={styles.loadingContainer}>
                    {isSyncing && <Text>Syncing...</Text>}
                    <ActivityIndicator size="large" color="#0000ff"/>
                </View>
            );
        }

        return (
            <>
                {isSyncing && (
                    <View style={styles.loadingContainer}>
                        {isSyncing && <Text>Syncing...</Text>}
                        <ActivityIndicator size="large" color="#0000ff"/>
                    </View>
                )}
                <Calendar
                    bodyContainerStyle={styles.calHeader}
                    swipeEnabled
                    mode={"month"}
                    sortedMonthView
                    events={filteredEvents}
                    // renderEvent={renderEvent}
                    eventCellStyle={memoizedEventCellStyle}
                    allDayEventCellStyle={memoizedEventCellStyle}
                    // enableEnrichedEvents={true}
                    // enrichedEventsByDate={enrichedEvents}
                    onPressEvent={handlePressEvent}
                    weekStartsOn={memoizedWeekStartsOn}
                    height={calendarHeight}
                    activeDate={todaysDate}
                    date={selectedDate}
                    onPressCell={handlePressCell}
                    headerContentStyle={memoizedHeaderContentStyle}
                    onSwipeEnd={handleSwipeEnd}
                    scrollOffsetMinutes={offsetMinutes}
                    theme={{
                        palette: {
                            nowIndicator: profileData?.eventColor || "#fd1575",
                            gray: {
                                "100": "#e8eaed",
                                "200": "#e8eaed",
                                "500": "#b7b7b7",
                                "800": "#919191",
                            },
                        },
                        typography: {
                            fontFamily: "PlusJakartaSans_500Medium",
                            sm: {fontFamily: "Manrope_600SemiBold", fontSize: 8},
                            xl: {
                                fontFamily: "PlusJakartaSans_500Medium",
                                fontSize: 14,
                            },
                            moreLabel: {},
                            xs: {fontSize: 10},
                        },
                    }}
                    dayHeaderStyle={dateStyle}
                    dayHeaderHighlightColor={"white"}
                    showAdjacentMonths
                    headerContainerStyle={mode !== "month" ? {
                        overflow: "hidden",
                    } : {}}
                    hourStyle={styles.hourStyle}
                    onPressDateHeader={handlePressDayHeader}
                    ampm
                    // renderCustomDateForMonth={renderCustomDateForMonth}
                />
                {Device.deviceType === DeviceType.TABLET && <View style={{backgroundColor: 'white', height: '9%', width: '100%'}}/>}
            </>

        );
    }
);

const styles = StyleSheet.create({
    segmentslblStyle: {
        fontSize: 12,
        fontFamily: "Manrope_600SemiBold",
    },
    calHeader: {
        borderWidth: 0,
        paddingBottom: 0,
    },
    dayModeHeader: {
        alignSelf: "flex-start",
        justifyContent: "space-between",
        alignContent: "center",
        width: 38,
        right: 42,
        height: 13,
    },
    weekModeHeader: {},
    monthModeHeader: {},
    loadingContainer: {
        flex: 1,
        justifyContent: "center",
        alignItems: "center",
        position: "absolute",
        width: "100%",
        height: "100%",
        zIndex: 100,
        backgroundColor: "rgba(255, 255, 255, 0.9)",
    },
    dayHeader: {
        backgroundColor: "#4184f2",
        aspectRatio: 1,
        borderRadius: 100,
        alignItems: "center",
        justifyContent: "center",
    },
    otherDayHeader: {
        backgroundColor: "transparent",
        color: "#919191",
        aspectRatio: 1,
        borderRadius: 100,
        alignItems: "center",
        justifyContent: "center",
    },
    hourStyle: {
        color: "#5f6368",
        fontSize: 12,
        fontFamily: "Manrope_500Medium",
    },
    eventCell: {
        flex: 1,
        borderRadius: 4,
        padding: 4,
        height: '100%',
        justifyContent: 'center',
    },
    eventTitle: {
        color: 'white',
        fontSize: 12,
        fontFamily: "PlusJakartaSans_500Medium",
    },
});
