import React, {useCallback, useMemo, useRef, useState} from "react";
import {View} from "react-native-ui-lib";
import {DeviceType} from "expo-device";
import * as Device from "expo-device";
import {CalendarBody, CalendarContainer, CalendarHeader, CalendarKitHandle} from "@howljs/calendar-kit";
import {useAtomValue} from "jotai";
import {selectedUserAtom} from "@/components/pages/calendar/atoms";

import {useAuthContext} from "@/contexts/AuthContext";
import {useGetFamilyMembers} from "@/hooks/firebase/useGetFamilyMembers";
import {useGetEvents} from "@/hooks/firebase/useGetEvents";
import {useFormattedEvents} from "@/components/pages/calendar/useFormattedEvents";
import {useCalendarControls} from "@/components/pages/calendar/useCalendarControls";
import {EventCell} from "@/components/pages/calendar/EventCell";
import {DetailedCalendarController} from "@/components/pages/calendar/DetailedCalendarController";

interface EventCalendarProps {
    calendarWidth: number;
    mode: "week" | "month" | "day" | "3days";
    onLoad?: () => void;
}

const HEADER_PROPS = {
    dayBarHeight: 60,
    headerBottomHeight: 20,
};

const BODY_PROPS = {
    showNowIndicator: true,
    hourFormat: "h:mm a"
};

const MODE_TO_DAYS = {
    'week': 7,
    '3days': 3,
    'day': 1,
    'month': 1
} as const;

const getContainerProps = (date: Date, customKey: string) => ({
    hourWidth: 70,
    allowPinchToZoom: true,
    useHaptic: true,
    scrollToNow: true,
    initialDate: customKey !== "default" ? customKey : date.toISOString(),
});

const MemoizedEventCell = React.memo(EventCell, (prev, next) => {
    return prev.event.id === next.event.id &&
        prev.event.lastModified === next.event.lastModified;
});

export const DetailedCalendar: React.FC<EventCalendarProps> = React.memo(({
                                                                              calendarWidth,
                                                                              mode,
                                                                              onLoad
                                                                          }) => {
    const {profileData} = useAuthContext();
    const {data: familyMembers} = useGetFamilyMembers();
    const {data: events} = useGetEvents();
    const selectedUser = useAtomValue(selectedUserAtom);
    const calendarRef = useRef<CalendarKitHandle>(null);
    const [customKey, setCustomKey] = useState("defaultKey");

    const memoizedFamilyMembers = useMemo(() => familyMembers || [], [familyMembers]);
    const currentDate = useMemo(() => new Date(), []);
    const containerProps = useMemo(() => getContainerProps(currentDate, customKey), [currentDate, customKey]);

    const {data: formattedEvents} = useFormattedEvents(events ?? [], currentDate, selectedUser);
    const {
        handlePressEvent,
        handlePressCell,
        debouncedOnDateChanged
    } = useCalendarControls(events ?? []);

    const getAttendees = useCallback((event: any) => {
        return memoizedFamilyMembers.filter(member => event?.attendees?.includes(member?.uid!));
    }, [memoizedFamilyMembers]);

    const renderEvent = useCallback((event: any) => {
        const attendees = getAttendees(event);
        return (
                <MemoizedEventCell
                    event={event}
                    onPress={handlePressEvent}
                    attendees={attendees}
                />
        );
    }, [getAttendees, handlePressEvent]);

    return (
        <CalendarContainer
            ref={calendarRef}
            {...containerProps}
            numberOfDays={MODE_TO_DAYS[mode]}
            calendarWidth={calendarWidth}
            onDateChanged={debouncedOnDateChanged}
            firstDay={profileData?.firstDayOfWeek === "Mondays" ? 1 : 0}
            events={formattedEvents ?? []}
            onPressEvent={handlePressEvent}
            onPressBackground={handlePressCell}
            onLoad={onLoad}
        >
            <DetailedCalendarController
                calendarRef={calendarRef}
                setCustomKey={setCustomKey}
            />
            <CalendarHeader {...HEADER_PROPS}/>
            <CalendarBody
                {...BODY_PROPS}
                renderEvent={renderEvent}
            />
            {Device.deviceType === DeviceType.TABLET && (
                <View style={{backgroundColor: 'white', height: '9%', width: '100%'}}/>
            )}
        </CalendarContainer>
    );
});

DetailedCalendar.displayName = 'DetailedCalendar';

export default DetailedCalendar;