// src/screens/EventFormScreen.tsx
import React, { useState, useEffect, useCallback } from 'react';
// Add Platform import
import { View, StyleSheet, ScrollView, Alert, TouchableOpacity, Platform } from 'react-native';
// Add Chip and Switch
import { TextInput, Button, useTheme, Text, ActivityIndicator, HelperText, Chip, Switch } from 'react-native-paper';
import { useNavigation, useRoute, RouteProp } from '@react-navigation/native';
// Conditionally import DateTimePickerModal only if not on web
// Note: This dynamic import might not work as expected depending on the bundler setup.
// A more robust approach might involve platform-specific files or checking Platform.OS before rendering.
// For now, we'll check Platform.OS before using it.
import DateTimePickerModal from "react-native-modal-datetime-picker";
import { format, parseISO, isValid, parse } from 'date-fns'; // Added parse

import { getCalendarEventById, createCalendarEvent, updateCalendarEvent, deleteCalendarEvent } from '../api/calendar';
// Import the new types
import { CalendarEventCreate, CalendarEventUpdate } from '../types/calendar';
import { WebContentStackParamList } from '../types/navigation'; // Adjust path if needed
import { NativeStackNavigationProp } from '@react-navigation/native-stack';

type EventFormRouteProp = RouteProp<WebContentStackParamList, 'EventForm'>;
type EventFormNavigationProp = NativeStackNavigationProp<WebContentStackParamList, 'EventForm'>;

const EventFormScreen = () => {
    const theme = useTheme();
    const navigation = useNavigation<EventFormNavigationProp>();
    const route = useRoute<EventFormRouteProp>();

    const eventId = route.params?.eventId; // Get eventId from navigation params
    const selectedDate = route.params?.selectedDate; // Get pre-selected date

    const [title, setTitle] = useState('');
    const [description, setDescription] = useState('');
    const [startDate, setStartDate] = useState<Date | null>(null);
    const [endDate, setEndDate] = useState<Date | null>(null);
    const [color, setColor] = useState(''); // Basic color input for now
    const [location, setLocation] = useState(''); // Add location state
    const [isAllDay, setIsAllDay] = useState(false); // Add all_day state
    const [tags, setTags] = useState<string[]>([]); // Add tags state
    const [currentTagInput, setCurrentTagInput] = useState(''); // State for tag input field

    // Add state for raw web date input
    const [webStartDateInput, setWebStartDateInput] = useState<string>('');
    const [webEndDateInput, setWebEndDateInput] = useState<string>('');

    const [isStartDatePickerVisible, setStartDatePickerVisibility] = useState(false);
    const [isEndDatePickerVisible, setEndDatePickerVisibility] = useState(false);

    const [isLoading, setIsLoading] = useState(false);
    const [isDeleting, setIsDeleting] = useState(false);
    const [error, setError] = useState<string | null>(null);
    const [formErrors, setFormErrors] = useState<{ title?: string; start?: string; end?: string }>({});


    // --- Fetch Event Data on Edit ---
    useEffect(() => {
        if (eventId) {
            const fetchEvent = async () => {
                setIsLoading(true);
                setError(null);
                try {
                    const event = await getCalendarEventById(eventId);
                    setTitle(event.title);
                    setDescription(event.description || '');
                    setColor(event.color || ''); // Use optional color
                    setLocation(event.location || ''); // Set location state
                    setIsAllDay(event.all_day ?? false); // Set all_day state, default to false if null/undefined
                    setTags(event.tags || []); // Load tags or default to empty array
                    // Ensure dates are Date objects
                    if (event.start && isValid(parseISO(event.start))) {
                        const parsedDate = parseISO(event.start);
                        setStartDate(parsedDate);
                        setWebStartDateInput(formatForWebInput(parsedDate)); // Init web input
                    } else {
                         console.warn("Fetched event has invalid start date:", event.start);
                         const now = new Date();
                         setStartDate(now);
                         setWebStartDateInput(formatForWebInput(now)); // Init web input
                    }
                    if (event.end && isValid(parseISO(event.end))) {
                        const parsedDate = parseISO(event.end);
                        setEndDate(parsedDate);
                        setWebEndDateInput(formatForWebInput(parsedDate)); // Init web input
                    } else {
                        setEndDate(null);
                        setWebEndDateInput(''); // Init web input
                    }
                } catch (err) {
                    setError('Failed to load event details.');
                    console.error(err);
                } finally {
                    setIsLoading(false);
                }
            };
            fetchEvent();
        } else if (selectedDate) {
            // Pre-fill start date if creating from a specific day
            try {
                const initialDate = parseISO(selectedDate);
                 if (isValid(initialDate)) {
                     // Set start time to a default (e.g., 9 AM) on the selected date
                     initialDate.setHours(9, 0, 0, 0);
                     setStartDate(initialDate);
                     setWebStartDateInput(formatForWebInput(initialDate)); // Init web input
                     setEndDate(null); // Ensure end date starts null
                     setWebEndDateInput('');
                 } else {
                     const now = new Date();
                     setStartDate(now);
                     setWebStartDateInput(formatForWebInput(now)); // Init web input
                     setEndDate(null);
                     setWebEndDateInput('');
                 }
            } catch {
                const now = new Date();
                setStartDate(now);
                setWebStartDateInput(formatForWebInput(now)); // Init web input
                setEndDate(null);
                setWebEndDateInput('');
            }
            setIsAllDay(false); // Default all_day to false for new events
            setTags([]); // Ensure tags start empty for new event
        } else {
            // Default start date to now if creating without a selected date
            const now = new Date();
            setStartDate(now);
            setWebStartDateInput(formatForWebInput(now)); // Init web input
            setEndDate(null);
            setWebEndDateInput('');
            setIsAllDay(false); // Default all_day to false for new events
            setTags([]); // Ensure tags start empty for new event
        }
    }, [eventId, selectedDate]);

    // --- Date Picker Logic ---
    const showStartDatePicker = () => {
        if (Platform.OS !== 'web') {
            setStartDatePickerVisibility(true);
        }
        // On web, clicking the input field allows manual editing
    };
    const hideStartDatePicker = () => setStartDatePickerVisibility(false);
    const handleStartDateConfirm = (date: Date) => {
        setStartDate(date);
        setWebStartDateInput(formatForWebInput(date)); // Update web input state
        validateForm({ start: date }); // Validate after setting
        hideStartDatePicker();
    };

    const showEndDatePicker = () => {
        if (Platform.OS !== 'web') {
            setEndDatePickerVisibility(true);
        }
         // On web, clicking the input field allows manual editing
    };
    const hideEndDatePicker = () => setEndDatePickerVisibility(false);
    const handleEndDateConfirm = (date: Date) => {
        setEndDate(date);
        setWebEndDateInput(formatForWebInput(date)); // Update web input state
        validateForm({ end: date }); // Validate after setting
        hideEndDatePicker();
    };

    // --- Web Date Input Handling ---
    const handleWebDateInputChange = (text: string, type: 'start' | 'end') => {
        // 1. Update the raw input state immediately
        if (type === 'start') {
            setWebStartDateInput(text);
        } else {
            setWebEndDateInput(text);
        }

        // 2. Attempt to parse the input text
        // Allow partial input (e.g., "yyyy-MM-dd") for validation purposes later if needed,
        // but only update the Date state if the format is fully matched.
        try {
            // Use a reference date (like 'new Date()') for parsing robustness
            const parsedDate = parse(text, 'yyyy-MM-dd HH:mm', new Date());

            // 3. Check if the parsed date is valid *and* the input string roughly matches the expected format length
            // This prevents updating the Date state too early with partial input like "202"
            if (isValid(parsedDate) && text.length >= 15) { // Basic length check for 'yyyy-MM-dd HH:mm'
                if (type === 'start') {
                    setStartDate(parsedDate);
                    validateForm({ start: parsedDate }); // Validate with the actual Date
                } else {
                    setEndDate(parsedDate);
                    validateForm({ end: parsedDate }); // Validate with the actual Date
                }
            } else {
                 // Input is incomplete or invalid format, don't update Date state yet.
                 // Validation should reflect that the required Date state might be missing or invalid.
                 if (type === 'start') {
                     // If text is empty, treat as null for validation. If partially filled,
                     // it's technically invalid until complete. Keep startDate as is for now.
                     validateForm({ start: text.trim() === '' ? null : startDate });
                 } else {
                     validateForm({ end: text.trim() === '' ? null : endDate });
                 }
            }
        } catch (e) {
            // Parsing likely failed due to highly invalid format
            console.error("Error parsing date string:", e);
             if (type === 'start') {
                 validateForm({ start: null }); // Treat as invalid for validation
             } else {
                 validateForm({ end: null }); // Treat as invalid for validation
             }
        }
    };


    // --- Form Validation ---
     const validateForm = (changedValues: { title?: string; start?: Date | null; end?: Date | null } = {}): boolean => {
         const errors: { title?: string; start?: string; end?: string } = { ...formErrors }; // Start with existing errors
         let isValidForm = true;

         const currentTitle = changedValues.title !== undefined ? changedValues.title : title;
         const currentStart = changedValues.start !== undefined ? changedValues.start : startDate;
         const currentEnd = changedValues.end !== undefined ? changedValues.end : endDate;


         // Validate Title
         if (currentTitle.trim() === '') {
             errors.title = 'Title is required.';
             isValidForm = false;
         } else {
             delete errors.title; // Clear error if valid
         }

         // Validate Start Date
         if (!currentStart) {
             errors.start = 'Start date/time is required.';
             isValidForm = false;
         } else {
             delete errors.start; // Clear error if valid
         }

         // Validate End Date (must be after start date if provided)
         if (currentStart && currentEnd && currentEnd < currentStart) {
             errors.end = 'End time cannot be before start time.';
             isValidForm = false;
         } else {
             delete errors.end; // Clear error if valid
         }

         setFormErrors(errors);
         return isValidForm;
     };


    // --- Save Event ---
    const handleSave = async () => {
        if (!validateForm({ title, start: startDate, end: endDate })) {
            setError("Please fix the errors in the form.");
            return;
        }
        if (!startDate) { // Should be caught by validation, but double-check
             setError("Start date is missing.");
             return;
         }

        setIsLoading(true);
        setError(null);

        // Construct data based on CalendarEventCreate/Update types
        const eventData: CalendarEventCreate | CalendarEventUpdate = {
            title: title.trim(),
            description: description.trim() || null,
            start: startDate.toISOString(),
            end: endDate ? endDate.toISOString() : null,
            location: location.trim() || null, // Include location
            color: color.trim() || null, // Include color
            all_day: isAllDay, // Include all_day state
            tags: tags.length > 0 ? tags : null, // Include tags, send null if empty
        };

        try {
            if (eventId) {
                await updateCalendarEvent(eventId, eventData as CalendarEventUpdate);
            } else {
                await createCalendarEvent(eventData as CalendarEventCreate);
            }
            navigation.goBack(); // Go back to calendar screen on success
        } catch (err) {
            setError(eventId ? 'Failed to update event.' : 'Failed to create event.');
            console.error(err);
        } finally {
            setIsLoading(false);
        }
    };

    // --- Delete Event ---
    const handleDelete = () => {
        if (!eventId) return;

        Alert.alert(
            "Confirm Deletion",
            "Are you sure you want to delete this event?",
            [
                { text: "Cancel", style: "cancel" },
                {
                    text: "Delete",
                    style: "destructive",
                    onPress: async () => {
                        setIsDeleting(true);
                        setError(null);
                        try {
                            await deleteCalendarEvent(eventId);
                            navigation.goBack(); // Go back on successful deletion
                        } catch (err) {
                            setError('Failed to delete event.');
                            console.error(err);
                        } finally {
                            setIsDeleting(false);
                        }
                    },
                },
            ]
        );
    };

    // --- Format Date/Time for Display ---
    // Keep this for native display or potentially other uses
    const formatDateTime = (date: Date | null): string => {
        if (!date) return '';
        try {
            // If all_day, only show the date part
            const formatString = isAllDay ? "MMM d, yyyy" : "MMM d, yyyy, p";
            return format(date, formatString);
        } catch {
            return "Invalid Date";
        }
    };

    // Helper to format date specifically for web input state
    const formatForWebInput = (date: Date | null): string => {
        if (!date || !isValid(date)) return '';
        try {
            // If all_day, only format the date part for the input
            const formatString = isAllDay ? "yyyy-MM-dd" : "yyyy-MM-dd HH:mm";
            return format(date, formatString);
        } catch {
            return ''; // Return empty if formatting fails
        }
    };

    // --- Tag Handling Logic ---
    const handleAddTag = () => {
        const newTag = currentTagInput.trim();
        if (newTag && !tags.includes(newTag)) {
            setTags([...tags, newTag]);
            setCurrentTagInput(''); // Clear input after adding
        }
    };

    const handleRemoveTag = (tagToRemove: string) => {
        setTags(tags.filter(tag => tag !== tagToRemove));
    };

    // --- All Day Toggle Logic ---
    const onToggleAllDay = () => {
        const newAllDay = !isAllDay;
        setIsAllDay(newAllDay);

        // Adjust dates when toggling all_day
        if (startDate) {
            const newStartDate = new Date(startDate);
            if (newAllDay) {
                // Set time to beginning of the day
                newStartDate.setHours(0, 0, 0, 0);
                // Optionally clear end date or set it to end of the same day
                setEndDate(null);
                setWebEndDateInput('');
            } else {
                // Restore a default time (e.g., 9 AM) or keep the previous time if stored
                newStartDate.setHours(9, 0, 0, 0);
            }
            setStartDate(newStartDate);
            setWebStartDateInput(formatForWebInput(newStartDate)); // Update web input

            // Re-validate if end date was cleared or start date changed
            validateForm({ start: newStartDate, end: newAllDay ? null : endDate });
        }
    };

    if (isLoading && !title) { // Show loading indicator only during initial fetch
        return <ActivityIndicator animating={true} style={styles.loading} />;
    }

    return (
        <ScrollView style={[styles.container, { backgroundColor: theme.colors.background }]}>
            <View style={styles.content}>
                <Text style={styles.header}>{eventId ? 'Edit Event' : 'Create Event'}</Text>

                {error && <Text style={styles.errorText}>{error}</Text>}

                <TextInput
                    label="Title *"
                    value={title}
                    onChangeText={(text) => { setTitle(text); validateForm({ title: text }); }}
                    mode="outlined"
                    style={styles.input}
                    error={!!formErrors.title}
                />
                 <HelperText type="error" visible={!!formErrors.title}>
                     {formErrors.title}
                 </HelperText>

                {/* All Day Switch */}
                <View style={styles.switchContainer}>
                    <Text>All-day event</Text>
                    <Switch value={isAllDay} onValueChange={onToggleAllDay} />
                </View>

                {/* Start Date Input - Conditional Logic */}
                <TouchableOpacity onPress={showStartDatePicker} disabled={Platform.OS === 'web' || isAllDay}>
                    <TextInput
                        label={isAllDay ? "Date *" : "Start Date & Time *"}
                        // Use raw web input state for value on web, formatted Date otherwise
                        value={Platform.OS === 'web' ? webStartDateInput : formatDateTime(startDate)}
                        editable={Platform.OS === 'web' && !isAllDay}
                        onChangeText={Platform.OS === 'web' && !isAllDay ? (text) => handleWebDateInputChange(text, 'start') : undefined}
                        placeholder={Platform.OS === 'web' ? (isAllDay ? 'YYYY-MM-DD' : 'YYYY-MM-DD HH:mm') : ''}
                        mode="outlined"
                        style={styles.input}
                        right={Platform.OS !== 'web' && !isAllDay ? <TextInput.Icon icon="calendar-clock" onPress={showStartDatePicker} /> : <TextInput.Icon icon="calendar" onPress={showStartDatePicker} />}
                        error={!!formErrors.start}
                        disabled={isAllDay && Platform.OS !== 'web'} // Disable native text input editing for all-day
                    />
                </TouchableOpacity>
                 <HelperText type="error" visible={!!formErrors.start}>
                     {formErrors.start}
                 </HelperText>

                {/* End Date Input - Conditionally render based on all_day */}
                {!isAllDay && (
                    <>
                        <TouchableOpacity onPress={showEndDatePicker} disabled={Platform.OS === 'web'}>
                            <TextInput
                                label="End Date & Time"
                                // Use raw web input state for value on web, formatted Date otherwise
                                value={Platform.OS === 'web' ? webEndDateInput : formatDateTime(endDate)}
                                editable={Platform.OS === 'web'}
                                onChangeText={Platform.OS === 'web' ? (text) => handleWebDateInputChange(text, 'end') : undefined}
                                placeholder={Platform.OS === 'web' ? 'YYYY-MM-DD HH:mm' : ''}
                                mode="outlined"
                                style={styles.input}
                                right={Platform.OS !== 'web' ? <TextInput.Icon icon="calendar-clock" onPress={showEndDatePicker} /> : null}
                                error={!!formErrors.end}
                            />
                        </TouchableOpacity>
                        <HelperText type="error" visible={!!formErrors.end}>
                            {formErrors.end}
                        </HelperText>
                    </>
                )}

                {/* Add Location Input */}
                <TextInput
                    label="Location"
                    value={location}
                    onChangeText={setLocation}
                    mode="outlined"
                    style={styles.input}
                />

                <TextInput
                    label="Description"
                    value={description}
                    onChangeText={setDescription}
                    mode="outlined"
                    style={styles.input}
                    multiline
                    numberOfLines={3}
                />

                <TextInput
                    label="Color (e.g., #ff0000)" // Simple text input for color for now
                    value={color}
                    onChangeText={setColor}
                    mode="outlined"
                    style={styles.input}
                    placeholder={theme.colors.primary} // Show default color hint
                />

                {/* --- Tags Input --- */}
                <View style={styles.tagInputContainer}>
                    <TextInput
                        label="Add Tag"
                        value={currentTagInput}
                        onChangeText={setCurrentTagInput}
                        mode="outlined"
                        style={styles.tagInput}
                        onSubmitEditing={handleAddTag} // Allow adding tag by pressing enter/submit
                    />
                    {/* Wrap Button text in <Text> */}
                    <Button onPress={handleAddTag} mode="contained" style={styles.addTagButton} icon="plus">
                        <Text>Add</Text>
                    </Button>
                </View>
                <View style={styles.tagsDisplayContainer}>
                    {tags.map((tag, index) => (
                        <Chip
                            key={index}
                            icon="close" // Use close icon for removal
                            onPress={() => handleRemoveTag(tag)} // Use onPress for removal
                            style={styles.tagChip}
                            mode="flat" // Use flat mode for less emphasis
                        >
                            {tag}
                        </Chip>
                    ))}
                </View>

                <Button
                    mode="contained"
                    onPress={handleSave}
                    style={styles.button}
                    loading={isLoading && !!title} // Show loading on button during save/update
                    disabled={isLoading || isDeleting}
                >
                    {eventId ? 'Update Event' : 'Create Event'}
                </Button>

                {eventId && (
                    <Button
                        mode="outlined"
                        onPress={handleDelete}
                        style={styles.button}
                        textColor={theme.colors.error}
                        loading={isDeleting}
                        disabled={isLoading || isDeleting}
                    >
                        Delete Event
                    </Button>
                )}

                {/* Conditionally render DateTimePickerModal only on native platforms */}
                {Platform.OS !== 'web' && (
                    <>
                        <DateTimePickerModal
                            isVisible={isStartDatePickerVisible}
                            mode={isAllDay ? "date" : "datetime"} // Use 'date' mode if all_day
                            date={startDate || new Date()} // Default picker to current start date or now
                            onConfirm={handleStartDateConfirm}
                            onCancel={hideStartDatePicker}
                            is24Hour={false} // Adjust based on preference
                        />
                        {/* Only show end date picker if not all_day */}
                        {!isAllDay && (
                            <DateTimePickerModal
                                isVisible={isEndDatePickerVisible}
                                mode="datetime"
                                date={endDate || startDate || new Date()} // Default picker to end, start, or now
                                minimumDate={startDate || undefined} // Prevent end date being before start date
                                onConfirm={handleEndDateConfirm}
                                onCancel={hideEndDatePicker}
                                is24Hour={false}
                            />
                        )}
                    </>
                )}
            </View>
        </ScrollView>
    );
};

const styles = StyleSheet.create({
    container: {
        flex: 1,
    },
    content: {
        padding: 20,
    },
    header: {
        fontSize: 24,
        fontWeight: 'bold',
        marginBottom: 20,
        textAlign: 'center',
    },
    input: {
        marginBottom: 5, // Reduced margin as HelperText adds space
    },
    switchContainer: {
        flexDirection: 'row',
        justifyContent: 'space-between',
        alignItems: 'center',
        marginBottom: 15, // Add some space below the switch
        paddingHorizontal: 4, // Align text with TextInput label
    },
    button: {
        marginTop: 15,
    },
    loading: {
        flex: 1,
        justifyContent: 'center',
        alignItems: 'center',
    },
    errorText: {
        color: 'red', // Use theme.colors.error in practice
        textAlign: 'center',
        marginBottom: 10,
    },
    tagInputContainer: {
        flexDirection: 'row',
        alignItems: 'center',
        marginBottom: 5,
    },
    tagInput: {
        flex: 1,
        marginRight: 8,
    },
    addTagButton: {
        // Adjust height or padding if needed to align with text input
    },
    tagsDisplayContainer: {
        flexDirection: 'row',
        flexWrap: 'wrap',
        marginBottom: 15, // Add some space below the tags
    },
    tagChip: {
        marginRight: 5,
        marginBottom: 5,
        // backgroundColor: theme.colors.secondaryContainer, // Optional: Style chips
    },
    errorText: {
        color: 'red', // Use theme.colors.error in practice
        textAlign: 'center',
        marginBottom: 10,
    },
});

export default EventFormScreen;
