// src/components/calendar/CustomCalendarView.tsx
import React, { useState, useEffect, useCallback, useMemo } from 'react';
import { View, StyleSheet, ActivityIndicator } from 'react-native';
import { useTheme, Text } from 'react-native-paper';
import {
    startOfMonth, endOfMonth, startOfWeek, endOfWeek, addMonths, subMonths,
    addWeeks, subWeeks, addDays, subDays, eachDayOfInterval, format, getMonth, getYear, isSameMonth,
    parseISO, isValid, isSameDay, startOfDay, endOfDay
} from 'date-fns';
// Import useFocusEffect
import { useFocusEffect } from '@react-navigation/native';

import CalendarHeader from './CalendarHeader';
import ViewSwitcher from './ViewSwitcher';
import MonthView from './MonthView';
import WeekView from './WeekView';
import ThreeDayView from './ThreeDayView';
import { getCalendarEvents } from '../../api/calendar';
import { CalendarEvent } from '../../types/calendar';

export type CalendarViewMode = 'month' | 'week' | '3day';

const CustomCalendarView = () => {
    const theme = useTheme();
    const [viewMode, setViewMode] = useState<CalendarViewMode>('month');
    const [currentDate, setCurrentDate] = useState(startOfDay(new Date())); // Use start of day for consistency
    const [events, setEvents] = useState<CalendarEvent[]>([]);
    const [isLoading, setIsLoading] = useState(false);
    const [error, setError] = useState<string | null>(null);

    // Calculate date range based on view mode and current date
    const { startDate, endDate, displayRangeText } = useMemo(() => {
        let start: Date, end: Date, text: string;
        switch (viewMode) {
            case 'week':
                start = startOfWeek(currentDate, { weekStartsOn: 1 }); // Assuming week starts on Monday
                end = endOfWeek(currentDate, { weekStartsOn: 1 });
                text = `${format(start, 'MMM d')} - ${format(end, 'MMM d, yyyy')}`;
                break;
            case '3day':
                start = currentDate;
                end = addDays(currentDate, 2);
                text = `${format(start, 'MMM d')} - ${format(end, 'MMM d, yyyy')}`;
                break;
            case 'month':
            default:
                start = startOfMonth(currentDate);
                end = endOfMonth(currentDate);
                text = format(currentDate, 'MMMM yyyy');
                break;
        }
        // Ensure end date includes the full day for fetching
        return { startDate: start, endDate: endOfDay(end), displayRangeText: text };
    }, [viewMode, currentDate]);

    // Fetch events when date range or view mode changes
    const fetchEvents = useCallback(async () => {
        setIsLoading(true);
        setError(null);
        console.log(`[CustomCalendar] Fetching events from ${startDate.toISOString()} to ${endDate.toISOString()}`);
        try {
            // Pass adjusted start/end dates for fetching
            const fetchedEvents = await getCalendarEvents(startDate, endDate);
            setEvents(fetchedEvents);
        } catch (err) {
            console.error("Error fetching calendar events:", err);
            setError('Failed to load events.');
            setEvents([]);
        } finally {
            setIsLoading(false);
        }
    }, [startDate, endDate]); // Depend on calculated start/end dates

    // Use useFocusEffect to fetch events when the screen is focused
    useFocusEffect(
        useCallback(() => {
            console.log('[CustomCalendar] Screen focused, fetching events.');
            fetchEvents();
            // Optional: Return a cleanup function if needed, though not necessary for just fetching
            return () => {
                console.log('[CustomCalendar] Screen unfocused.');
            };
        }, [fetchEvents]) // Re-run effect if fetchEvents changes (due to date range change)
    );

    // Navigation handlers
    const handlePrev = useCallback(() => {
        switch (viewMode) {
            case 'week': setCurrentDate(subWeeks(currentDate, 1)); break;
            case '3day': setCurrentDate(subDays(currentDate, 3)); break;
            case 'month':
            default: setCurrentDate(subMonths(currentDate, 1)); break;
        }
    }, [viewMode, currentDate]);

    const handleNext = useCallback(() => {
        switch (viewMode) {
            case 'week': setCurrentDate(addWeeks(currentDate, 1)); break;
            case '3day': setCurrentDate(addDays(currentDate, 3)); break;
            case 'month':
            default: setCurrentDate(addMonths(currentDate, 1)); break;
        }
    }, [viewMode, currentDate]);

    // Group events by date string for easier lookup in child components
    const eventsByDate = useMemo(() => {
        const grouped: { [key: string]: CalendarEvent[] } = {};
        events.forEach(event => {
            if (typeof event.start !== 'string') return; // Skip invalid
            const start = parseISO(event.start);
            if (!isValid(start)) return; // Skip invalid

            const end = typeof event.end === 'string' && isValid(parseISO(event.end)) ? parseISO(event.end) : start;
            const endForInterval = end < start ? start : end; // Ensure end >= start

            const intervalDays = eachDayOfInterval({ start: startOfDay(start), end: startOfDay(endForInterval) });

            intervalDays.forEach(day => {
                const dateKey = format(day, 'yyyy-MM-dd');
                if (!grouped[dateKey]) {
                    grouped[dateKey] = [];
                }
                // Avoid duplicates within the same day's list
                if (!grouped[dateKey].some(e => e.id === event.id)) {
                    grouped[dateKey].push(event);
                }
            });
        });
        return grouped;
    }, [events]);


    const renderCalendarView = () => {
        const viewProps = { startDate, endDate, eventsByDate };
        switch (viewMode) {
            case 'week': return <WeekView {...viewProps} />;
            case '3day': return <ThreeDayView {...viewProps} />;
            case 'month':
            default: return <MonthView {...viewProps} />;
        }
    };

    const styles = StyleSheet.create({
        container: { flex: 1, backgroundColor: theme.colors.background },
        contentArea: {
            flex: 1,
            justifyContent: 'center',
        },
        loadingContainer: { flex: 1, justifyContent: 'center', alignItems: 'center' },
        errorText: { color: theme.colors.error, textAlign: 'center', padding: 10 },
        viewContainer: { flex: 1 },
    });

    return (
        <View style={styles.container}>
            <CalendarHeader
                currentRangeText={displayRangeText}
                onPrev={handlePrev}
                onNext={handleNext}
                currentView={viewMode}
                onViewChange={setViewMode}
            />
            <View style={styles.contentArea}>
                {isLoading ? (
                    <View style={styles.loadingContainer}>
                        <ActivityIndicator size="large" color={theme.colors.primary} />
                    </View>
                ) : error ? (
                    <Text style={styles.errorText}>{error}</Text>
                ) : (
                    <View style={styles.viewContainer}>
                        {renderCalendarView()}
                    </View>
                )}
            </View>
        </View>
    );
};

export default CustomCalendarView;
