use crate::components::{EventCreationData, RecurringEditAction, RecurringEditModal};
use crate::models::ical::VEvent;
use crate::services::calendar_service::{UserInfo, ExternalCalendar};
use chrono::{Datelike, Duration, Local, NaiveDate, NaiveDateTime, NaiveTime, Timelike, Weekday};
use std::collections::HashMap;
use web_sys::MouseEvent;
use yew::prelude::*;

#[derive(Properties, PartialEq)]
pub struct WeekViewProps {
    pub current_date: NaiveDate,
    pub today: NaiveDate,
    pub events: HashMap<NaiveDate, Vec<VEvent>>,
    pub on_event_click: Callback<VEvent>,
    #[prop_or_default]
    pub refreshing_event_uid: Option<String>,
    #[prop_or_default]
    pub user_info: Option<UserInfo>,
    #[prop_or_default]
    pub external_calendars: Vec<ExternalCalendar>,
    #[prop_or_default]
    pub on_event_context_menu: Option<Callback<(web_sys::MouseEvent, VEvent)>>,
    #[prop_or_default]
    pub on_calendar_context_menu: Option<Callback<(web_sys::MouseEvent, NaiveDate)>>,
    #[prop_or_default]
    pub on_create_event: Option<Callback<(NaiveDate, NaiveDateTime, NaiveDateTime)>>,
    #[prop_or_default]
    pub on_create_event_request: Option<Callback<EventCreationData>>,
    #[prop_or_default]
    pub on_event_update: Option<
        Callback<(
            VEvent,
            NaiveDateTime,
            NaiveDateTime,
            bool,
            Option<chrono::NaiveDateTime>,
            Option<String>,
            Option<String>,
        )>,
    >,
    #[prop_or_default]
    pub context_menus_open: bool,
    #[prop_or_default]
    pub time_increment: u32,
    #[prop_or_default]
    pub print_mode: bool,
    #[prop_or_default]
    pub print_pixels_per_hour: Option<f64>,
    #[prop_or_default]
    pub print_start_hour: Option<u32>,
}

#[derive(Clone, PartialEq)]
enum DragType {
    CreateEvent,
    MoveEvent(VEvent),
    ResizeEventStart(VEvent), // Resizing from the top edge (start time)
    ResizeEventEnd(VEvent),   // Resizing from the bottom edge (end time)
}

#[derive(Clone, PartialEq)]
struct DragState {
    is_dragging: bool,
    drag_type: DragType,
    start_date: NaiveDate,
    start_y: f64,
    current_y: f64,
    offset_y: f64,   // For event moves, this is the offset from the event's top
    has_moved: bool, // Track if we've moved enough to constitute a real drag
}

#[function_component(WeekView)]
pub fn week_view(props: &WeekViewProps) -> Html {
    let start_of_week = get_start_of_week(props.current_date);
    let week_days: Vec<NaiveDate> = (0..7).map(|i| start_of_week + Duration::days(i)).collect();

    // Drag state for event creation
    let drag_state = use_state(|| None::<DragState>);

    // State for recurring event edit modal
    #[derive(Clone, PartialEq)]
    struct PendingRecurringEdit {
        event: VEvent,
        new_start: NaiveDateTime,
        new_end: NaiveDateTime,
    }

    let pending_recurring_edit = use_state(|| None::<PendingRecurringEdit>);

    // Current time state for time indicator
    let current_time = use_state(|| Local::now());

    // Update current time every 5 seconds
    {
        let current_time = current_time.clone();
        use_effect_with((), move |_| {
            let interval = gloo_timers::callback::Interval::new(5_000, move || {
                current_time.set(Local::now());
            });
            
            // Return the interval to keep it alive
            move || drop(interval)
        });
    }

    // Helper function to calculate current time indicator position
    let calculate_current_time_position = |time_increment: u32| -> f64 {
        let now = current_time.time();
        let hour = now.hour() as f64;
        let minute = now.minute() as f64;
        let pixels_per_hour = if time_increment == 15 { 120.0 } else { 60.0 };
        (hour + minute / 60.0) * pixels_per_hour
    };

    // Helper function to get calendar color for an event
    let get_event_color = |event: &VEvent| -> String {
        if let Some(calendar_path) = &event.calendar_path {
            // Check external calendars first (path format: "external_{id}")
            if calendar_path.starts_with("external_") {
                if let Ok(id_str) = calendar_path.strip_prefix("external_").unwrap_or("").parse::<i32>() {
                    if let Some(external_calendar) = props.external_calendars
                        .iter()
                        .find(|cal| cal.id == id_str)
                    {
                        return external_calendar.color.clone();
                    }
                }
            }
            // Check regular calendars
            else if let Some(user_info) = &props.user_info {
                if let Some(calendar) = user_info
                    .calendars
                    .iter()
                    .find(|cal| &cal.path == calendar_path)
                {
                    return calendar.color.clone();
                }
            }
        }
        "#3B82F6".to_string()
    };

    // Generate time labels - 24 hours
    let time_labels: Vec<String> = (0..24)
        .map(|hour| {
            if hour == 0 {
                "12 AM".to_string()
            } else if hour < 12 {
                format!("{} AM", hour)
            } else if hour == 12 {
                "12 PM".to_string()
            } else {
                format!("{} PM", hour - 12)
            }
        })
        .collect();

    // Handlers for recurring event modification modal
    let on_recurring_choice = {
        let pending_recurring_edit = pending_recurring_edit.clone();
        let on_event_update = props.on_event_update.clone();
        let _on_create_event = props.on_create_event.clone();
        let events = props.events.clone();
        Callback::from(move |action: RecurringEditAction| {
            if let Some(edit) = (*pending_recurring_edit).clone() {
                match action {
                    RecurringEditAction::ThisEvent => {
                        // RFC 5545 Compliant Single Occurrence Modification: "This Event Only"
                        //
                        // When a user chooses to modify "this event only" for a recurring series,
                        // we implement an exception-based modification that:
                        //
                        // 1. **Add EXDATE to Original Series**: The original series is updated with
                        //    an EXDATE entry to exclude this specific occurrence from generation
                        // 2. **Create Exception Event**: A new standalone event is created with
                        //    RECURRENCE-ID pointing to the original occurrence, containing the modifications
                        //
                        // Example: User drags Aug 22 occurrence of "Daily 9AM meeting" to 2PM:
                        // - Original series: "Daily 9AM meeting" + EXDATE for Aug 22 (continues as normal except Aug 22)
                        // - Exception event: "Daily 2PM meeting" with RECURRENCE-ID=Aug22 (only affects Aug 22)
                        //
                        // This approach ensures:
                        // - All other occurrences remain unchanged (past and future)
                        // - Modified occurrence displays user's changes
                        // - RFC 5545 compliance through EXDATE and RECURRENCE-ID
                        // - CalDAV compatibility with standard calendar applications
                        //
                        // The backend handles both operations atomically within a single API call.
                        if let Some(update_callback) = &on_event_update {
                            // Extract occurrence date for backend processing
                            let occurrence_date = edit.event.dtstart.format("%Y-%m-%d").to_string();

                            // Send single request to backend with "this_only" scope
                            // Backend will atomically:
                            // 1. Add EXDATE to original series (excludes this occurrence)
                            // 2. Create exception event with RECURRENCE-ID and user's modifications
                            update_callback.emit((
                                edit.event.clone(),            // Original event (series to modify)
                                edit.new_start,                // Dragged start time for exception
                                edit.new_end,                  // Dragged end time for exception
                                true,                          // preserve_rrule = true
                                None,                          // No until_date for this_only
                                Some("this_only".to_string()), // Update scope
                                Some(occurrence_date),         // Date of occurrence being modified
                            ));
                        }
                    }
                    RecurringEditAction::FutureEvents => {
                        // RFC 5545 Compliant Series Splitting: "This and Future Events"
                        //
                        // When a user chooses to modify "this and future events" for a recurring series,
                        // we implement a series split operation that:
                        //
                        // 1. **Terminates Original Series**: The existing series is updated with an UNTIL
                        //    clause to stop before the occurrence being modified
                        // 2. **Creates New Series**: A new recurring series is created starting from the
                        //    occurrence date with the user's modifications (new time, title, etc.)
                        //
                        // Example: User drags Aug 22 occurrence of "Daily 9AM meeting" to 2PM:
                        // - Original: "Daily 9AM meeting" → ends Aug 21 (UNTIL=Aug22T000000Z)
                        // - New: "Daily 2PM meeting" → starts Aug 22, continues indefinitely
                        //
                        // This approach ensures:
                        // - Past occurrences remain unchanged (preserves user's historical data)
                        // - Future occurrences reflect the new modifications
                        // - CalDAV compatibility through proper RRULE manipulation
                        // - No conflicts with existing calendar applications
                        //
                        // The backend handles both operations atomically within a single API call
                        // to prevent race conditions and ensure data consistency.
                        if let Some(update_callback) = &on_event_update {
                            // Find the original series event (not the occurrence)
                            // UIDs like "uuid-timestamp" need to split on the last hyphen, not the first
                            let base_uid = if let Some(last_hyphen_pos) = edit.event.uid.rfind('-')
                            {
                                let suffix = &edit.event.uid[last_hyphen_pos + 1..];
                                // Check if suffix is numeric (timestamp), if so remove it
                                if suffix.chars().all(|c| c.is_numeric()) {
                                    edit.event.uid[..last_hyphen_pos].to_string()
                                } else {
                                    edit.event.uid.clone()
                                }
                            } else {
                                edit.event.uid.clone()
                            };

                            web_sys::console::log_1(
                                &format!(
                                    "🔍 Looking for original series: '{}' from occurrence: '{}'",
                                    base_uid, edit.event.uid
                                )
                                .into(),
                            );

                            // Find the original series event by searching for the base UID
                            let mut original_series = None;
                            for events_list in events.values() {
                                for event in events_list {
                                    if event.uid == base_uid {
                                        original_series = Some(event.clone());
                                        break;
                                    }
                                }
                                if original_series.is_some() {
                                    break;
                                }
                            }

                            let original_series = match original_series {
                                Some(series) => {
                                    web_sys::console::log_1(
                                        &format!("✅ Found original series: '{}'", series.uid)
                                            .into(),
                                    );
                                    series
                                }
                                None => {
                                    web_sys::console::log_1(&format!("⚠️  Could not find original series '{}', using occurrence but fixing UID", base_uid).into());
                                    let mut fallback_event = edit.event.clone();
                                    // Ensure the UID is the base UID, not the occurrence UID
                                    fallback_event.uid = base_uid.clone();
                                    fallback_event
                                }
                            };

                            // Calculate the day before this occurrence for UNTIL clause
                            let until_date =
                                edit.event.dtstart.date() - chrono::Duration::days(1);
                            let until_datetime = until_date
                                .and_time(chrono::NaiveTime::from_hms_opt(23, 59, 59).unwrap());
                            let until_naive = until_datetime; // Use local time directly

                            web_sys::console::log_1(&format!("🔄 Will set UNTIL {} for original series to end before occurrence {}", 
                                until_naive.format("%Y-%m-%d %H:%M:%S"),
                                edit.event.dtstart.format("%Y-%m-%d %H:%M:%S")).into());

                            // Critical: Use the dragged times (new_start/new_end) not the original series times
                            // This ensures the new series reflects the user's drag operation
                            let new_start = edit.new_start; // The dragged start time
                            let new_end = edit.new_end; // The dragged end time

                            // Extract occurrence date from the dragged event for backend processing
                            // Format: YYYY-MM-DD (e.g., "2025-08-22")
                            // This tells the backend which specific occurrence is being modified
                            let occurrence_date = edit.event.dtstart.format("%Y-%m-%d").to_string();

                            // Send single request to backend with "this_and_future" scope
                            // Backend will atomically:
                            // 1. Add UNTIL clause to original series (stops before occurrence_date)
                            // 2. Create new series starting from occurrence_date with dragged times
                            update_callback.emit((
                                original_series,                     // Original event to terminate
                                new_start,       // Dragged start time for new series
                                new_end,         // Dragged end time for new series
                                true,            // preserve_rrule = true
                                Some(until_naive), // UNTIL date for original series
                                Some("this_and_future".to_string()), // Update scope
                                Some(occurrence_date), // Date of occurrence being modified
                            ));
                        }
                    }
                    RecurringEditAction::AllEvents => {
                        // Modify the entire series
                        let series_event = edit.event.clone();

                        if let Some(callback) = &on_event_update {
                            callback.emit((
                                series_event,
                                edit.new_start,
                                edit.new_end,
                                true,
                                None,
                                Some("all_in_series".to_string()),
                                None,
                            )); // Regular drag operation - preserve RRULE, update_scope = all_in_series
                        }
                    }
                }
            }
            pending_recurring_edit.set(None);
        })
    };

    let on_recurring_cancel = {
        let pending_recurring_edit = pending_recurring_edit.clone();
        Callback::from(move |_| {
            pending_recurring_edit.set(None);
        })
    };


    html! {
        <div class="week-view-container">
            // Header with weekday names and dates
            <div class="week-header">
                <div class="time-gutter"></div>
                {
                    week_days.iter().map(|date| {
                        let is_today = *date == props.today;
                        let weekday_name = get_weekday_name(date.weekday());
                        
                        // Collect all-day events that span this date (from any day in the week)
                        let mut all_day_events: Vec<&VEvent> = Vec::new();
                        for events_list in props.events.values() {
                            for event in events_list {
                                if event.all_day && event_spans_date(event, *date) {
                                    all_day_events.push(event);
                                }
                            }
                        }
                        // Remove duplicates (same event might appear in multiple day buckets)
                        all_day_events.sort_by_key(|e| &e.uid);
                        all_day_events.dedup_by_key(|e| &e.uid);

                        html! {
                            <div class={classes!("week-day-header", if is_today { Some("today") } else { None })}>
                                <div class="day-header-content">
                                    <div class="weekday-name">{weekday_name}</div>
                                    <div class="day-number">{date.day()}</div>
                                </div>
                                
                                // All-day events section
                                {if !all_day_events.is_empty() {
                                    html! {
                                        <div class="all-day-events">
                                            {
                                                all_day_events.iter().map(|event| {
                                                    let event_color = get_event_color(event);
                                                    let onclick = {
                                                        let on_event_click = props.on_event_click.clone();
                                                        let event = (*event).clone();
                                                        Callback::from(move |e: MouseEvent| {
                                                            e.stop_propagation();
                                                            on_event_click.emit(event.clone());
                                                        })
                                                    };
                                                    
                                                    let oncontextmenu = {
                                                        if let Some(callback) = &props.on_event_context_menu {
                                                            let callback = callback.clone();
                                                            let event = (*event).clone();
                                                            Some(Callback::from(move |e: web_sys::MouseEvent| {
                                                                e.prevent_default();
                                                                e.stop_propagation(); // Prevent calendar context menu from also triggering
                                                                callback.emit((e, event.clone()));
                                                            }))
                                                        } else {
                                                            None
                                                        }
                                                    };
                                                    
                                                    html! {
                                                        <div 
                                                            class="all-day-event"
                                                            style={format!("background-color: {}", event_color)}
                                                            data-external={event.categories.contains(&"__EXTERNAL_CALENDAR__".to_string()).to_string()}
                                                            {onclick}
                                                            {oncontextmenu}
                                                        >
                                                            <span class="all-day-event-title">
                                                                {event.summary.as_ref().unwrap_or(&"Untitled".to_string())}
                                                            </span>
                                                        </div>
                                                    }
                                                }).collect::<Html>()
                                            }
                                        </div>
                                    }
                                } else {
                                    html! {}
                                }}
                            </div>
                        }
                    }).collect::<Html>()
                }
            </div>

            // Scrollable content area with time grid
            <div class="week-content">
                <div class={classes!("time-grid", if props.time_increment == 15 { Some("quarter-mode") } else { None })}>
                    // Time labels
                    <div class={classes!("time-labels", if props.time_increment == 15 { Some("quarter-mode") } else { None })}>
                        {
                            time_labels.iter().enumerate().map(|(hour, time)| {
                                let is_quarter_mode = props.time_increment == 15;
                                html! {
                                    <div class={classes!(
                                        "time-label",
                                        if is_quarter_mode { Some("quarter-mode") } else { None }
                                    )} data-hour={hour.to_string()}>
                                        {time}
                                    </div>
                                }
                            }).collect::<Html>()
                        }
                    </div>

                    // Day columns
                    <div class={classes!("week-days-grid", if props.time_increment == 15 { Some("quarter-mode") } else { None })}>
                        {
                            week_days.iter().enumerate().map(|(_column_index, date)| {
                                let is_today = *date == props.today;
                                let day_events = props.events.get(date).cloned().unwrap_or_default();
                                let event_layouts = calculate_event_layout(&day_events, *date, props.time_increment);

                                // Drag event handlers
                                let drag_state_clone = drag_state.clone();
                                let date_for_drag = *date;

                                let onmousedown = {
                                    let drag_state = drag_state_clone.clone();
                                    let context_menus_open = props.context_menus_open;
                                    let time_increment = props.time_increment;
                                    Callback::from(move |e: MouseEvent| {
                                        // Don't start drag if any context menu is open
                                        if context_menus_open {
                                            return;
                                        }

                                        // Only handle left-click (button 0)
                                        if e.button() != 0 {
                                            return;
                                        }

                                        // Calculate Y position relative to day column container
                                        // Use layer_y which gives coordinates relative to positioned ancestor
                                        let relative_y = e.layer_y() as f64;
                                        let relative_y = if relative_y > 0.0 { relative_y } else { e.offset_y() as f64 };

                                        // Snap to increment
                                        let snapped_y = snap_to_increment(relative_y, time_increment);

                                        drag_state.set(Some(DragState {
                                            is_dragging: true,
                                            drag_type: DragType::CreateEvent,
                                            start_date: date_for_drag,
                                            start_y: snapped_y,
                                            current_y: snapped_y,
                                            offset_y: 0.0,
                                            has_moved: false,
                                        }));
                                        e.prevent_default();
                                    })
                                };

                                let onmousemove = {
                                    let drag_state = drag_state_clone.clone();
                                    let time_increment = props.time_increment;
                                    Callback::from(move |e: MouseEvent| {
                                        // Only process mouse move if a button is still pressed
                                        if e.buttons() == 0 {
                                            // No mouse button pressed, clear drag state
                                            drag_state.set(None);
                                            return;
                                        }
                                        
                                        if let Some(mut current_drag) = (*drag_state).clone() {
                                            if current_drag.is_dragging {
                                                // Use layer_y for consistent coordinate calculation
                                                let mouse_y = e.layer_y() as f64;
                                                let mouse_y = if mouse_y > 0.0 { mouse_y } else { e.offset_y() as f64 };

                                                // For move operations, we now follow the mouse directly since we start at click position
                                                // For resize operations, we still use the mouse position directly
                                                let adjusted_y = mouse_y;

                                                // Snap to increment
                                                let snapped_y = snap_to_increment(adjusted_y, time_increment);

                                                // Check if we've moved enough to constitute a real drag (5 pixels minimum)
                                                let movement_distance = (snapped_y - current_drag.start_y).abs();
                                                if movement_distance > 5.0 {
                                                    current_drag.has_moved = true;
                                                }

                                                current_drag.current_y = snapped_y;
                                                drag_state.set(Some(current_drag));
                                            }
                                        }
                                    })
                                };

                                let onmouseup = {
                                    let drag_state = drag_state_clone.clone();
                                    let on_create_event = props.on_create_event.clone();
                                    let on_event_update = props.on_event_update.clone();
                                    let pending_recurring_edit = pending_recurring_edit.clone();
                                    let time_increment = props.time_increment;
                                    Callback::from(move |_e: MouseEvent| {
                                        if let Some(current_drag) = (*drag_state).clone() {
                                            if current_drag.is_dragging && current_drag.has_moved {
                                                match &current_drag.drag_type {
                                                    DragType::CreateEvent => {
                                                        // Calculate start and end times
                                                        let start_time = pixels_to_time(current_drag.start_y, time_increment);
                                                        let end_time = pixels_to_time(current_drag.current_y, time_increment);

                                                        // Ensure start is before end
                                                        let (actual_start, actual_end) = if start_time <= end_time {
                                                            (start_time, end_time)
                                                        } else {
                                                            (end_time, start_time)
                                                        };

                                                        // Ensure minimum duration (15 minutes)
                                                        let actual_end = if actual_end.signed_duration_since(actual_start).num_minutes() < 15 {
                                                            actual_start + chrono::Duration::minutes(15)
                                                        } else {
                                                            actual_end
                                                        };

                                                        let start_datetime = NaiveDateTime::new(current_drag.start_date, actual_start);
                                                        let end_datetime = NaiveDateTime::new(current_drag.start_date, actual_end);

                                                        if let Some(callback) = &on_create_event {
                                                            callback.emit((current_drag.start_date, start_datetime, end_datetime));
                                                        }
                                                    },
                                                    DragType::MoveEvent(event) => {
                                                        // Calculate new start time based on drag position (accounting for click offset)
                                                        let unsnapped_position = current_drag.current_y - current_drag.offset_y;
                                                        // Snap the final position to maintain time increment alignment
                                                        let event_top_position = snap_to_increment(unsnapped_position, time_increment);
                                                        let new_start_time = pixels_to_time(event_top_position, time_increment);

                                                        // Calculate duration from original event
                                                        let original_duration = if let Some(end) = event.dtend {
                                                            end.signed_duration_since(event.dtstart)
                                                        } else {
                                                            chrono::Duration::hours(1) // Default 1 hour
                                                        };

                                                        let new_start_datetime = NaiveDateTime::new(current_drag.start_date, new_start_time);
                                                        let new_end_datetime = new_start_datetime + original_duration;

                                                        // Check if this is a recurring event
                                                        if event.rrule.is_some() {
                                                            // Show modal for recurring event modification
                                                            pending_recurring_edit.set(Some(PendingRecurringEdit {
                                                                event: event.clone(),
                                                                new_start: new_start_datetime,
                                                                new_end: new_end_datetime,
                                                            }));
                                                        } else {
                                                            // Regular event - proceed with update
                                                            if let Some(callback) = &on_event_update {
                                                                callback.emit((event.clone(), new_start_datetime, new_end_datetime, true, None, None, None)); // Regular drag operation - preserve RRULE, no until_date
                                                            }
                                                        }
                                                    },
                                                    DragType::ResizeEventStart(event) => {
                                                        // Calculate new start time based on drag position
                                                        let new_start_time = pixels_to_time(current_drag.current_y, time_increment);

                                                        // Keep the original end time
                                                        let original_end = if let Some(end) = event.dtend {
                                                            end                                                        } else {
                                                            // If no end time, use start time + 1 hour as default
                                                            event.dtstart + chrono::Duration::hours(1)
                                                        };

                                                        let new_start_datetime = NaiveDateTime::new(current_drag.start_date, new_start_time);

                                                        // Ensure start is before end (minimum 15 minutes)
                                                        let new_end_datetime = if new_start_datetime >= original_end {
                                                            new_start_datetime + chrono::Duration::minutes(15)
                                                        } else {
                                                            original_end
                                                        };

                                                        // Check if this is a recurring event
                                                        if event.rrule.is_some() {
                                                            // Show modal for recurring event modification
                                                            pending_recurring_edit.set(Some(PendingRecurringEdit {
                                                                event: event.clone(),
                                                                new_start: new_start_datetime,
                                                                new_end: new_end_datetime,
                                                            }));
                                                        } else {
                                                            // Regular event - proceed with update
                                                            if let Some(callback) = &on_event_update {
                                                                callback.emit((event.clone(), new_start_datetime, new_end_datetime, true, None, None, None)); // Regular drag operation - preserve RRULE, no until_date
                                                            }
                                                        }
                                                    },
                                                    DragType::ResizeEventEnd(event) => {
                                                        // Calculate new end time based on drag position
                                                        let new_end_time = pixels_to_time(current_drag.current_y, time_increment);

                                                        // Keep the original start time (already local)
                                                        let original_start = event.dtstart;

                                                        let new_end_datetime = NaiveDateTime::new(current_drag.start_date, new_end_time);

                                                        // Ensure end is after start (minimum 15 minutes)
                                                        let new_start_datetime = if new_end_datetime <= original_start {
                                                            new_end_datetime - chrono::Duration::minutes(15)
                                                        } else {
                                                            original_start
                                                        };

                                                        // Check if this is a recurring event
                                                        if event.rrule.is_some() {
                                                            // Show modal for recurring event modification
                                                            pending_recurring_edit.set(Some(PendingRecurringEdit {
                                                                event: event.clone(),
                                                                new_start: new_start_datetime,
                                                                new_end: new_end_datetime,
                                                            }));
                                                        } else {
                                                            // Regular event - proceed with update
                                                            if let Some(callback) = &on_event_update {
                                                                callback.emit((event.clone(), new_start_datetime, new_end_datetime, true, None, None, None)); // Regular drag operation - preserve RRULE, no until_date
                                                            }
                                                        }
                                                    }
                                                }

                                                drag_state.set(None);
                                            }
                                        }
                                    })
                                };

                                // Check if currently dragging to create an event
                                let is_creating_event = if let Some(drag) = (*drag_state).clone() {
                                    matches!(drag.drag_type, DragType::CreateEvent) && drag.is_dragging
                                } else {
                                    false
                                };

                                html! {
                                    <div
                                        class={classes!(
                                            "week-day-column",
                                            if is_today { Some("today") } else { None },
                                            if is_creating_event { Some("creating-event") } else { None },
                                            if props.time_increment == 15 { Some("quarter-mode") } else { None }
                                        )}
                                        {onmousedown}
                                        {onmousemove}
                                        {onmouseup}
                                    >
                                        // Time slot backgrounds - 24 hour slots to represent full day
                                        {
                                            (0..24).map(|hour| {
                                                let slots_per_hour = 60 / props.time_increment;
                                                html! {
                                                    <div class={classes!("time-slot", if props.time_increment == 15 { Some("quarter-mode") } else { None })} data-hour={hour.to_string()}>
                                                        {
                                                            (0..slots_per_hour).map(|_slot| {
                                                                let slot_class = if props.time_increment == 15 {
                                                                    "time-slot-quarter"
                                                                } else {
                                                                    "time-slot-half"
                                                                };
                                                                html! {
                                                                    <div class={slot_class}></div>
                                                                }
                                                            }).collect::<Html>()
                                                        }
                                                    </div>
                                                }
                                            }).collect::<Html>()
                                        }

                                        // Events positioned absolutely based on their actual times
                                        <div class="events-container">
                                            {
                                                day_events.iter().enumerate().filter_map(|(event_idx, event)| {
                                                    let (start_pixels, duration_pixels, is_all_day) = calculate_event_position(event, *date, props.time_increment, props.print_pixels_per_hour, props.print_start_hour);

                                                    // Skip all-day events (they're rendered in the header)
                                                    if is_all_day {
                                                        return None;
                                                    }

                                                    // Skip events that don't belong on this date or have invalid positioning
                                                    if start_pixels == 0.0 && duration_pixels == 0.0 {
                                                        return None;
                                                    }

                                                    let event_color = get_event_color(event);
                                                    let is_refreshing = props.refreshing_event_uid.as_ref() == Some(&event.uid);

                                                    let onclick = {
                                                        let on_event_click = props.on_event_click.clone();
                                                        let event = event.clone();
                                                        Callback::from(move |e: MouseEvent| {
                                                            e.stop_propagation(); // Prevent calendar click events from also triggering
                                                            on_event_click.emit(event.clone());
                                                        })
                                                    };

                                                    let onmousedown_event = {
                                                        let drag_state = drag_state.clone();
                                                        let event_for_drag = event.clone();
                                                        let date_for_drag = *date;
                                                        let time_increment = props.time_increment;
                                                        let print_pixels_per_hour = props.print_pixels_per_hour;
                                                        let print_start_hour = props.print_start_hour;
                                                        Callback::from(move |e: MouseEvent| {
                                                            e.stop_propagation(); // Prevent drag-to-create from starting on event clicks

                                                            // Only handle left-click (button 0) for moving
                                                            if e.button() != 0 {
                                                                return;
                                                            }

                                                            // Calculate click position relative to event element
                                                            let click_y_relative = e.layer_y() as f64;
                                                            let click_y_relative = if click_y_relative > 0.0 { click_y_relative } else { e.offset_y() as f64 };

                                                            // Get event's current position in day column coordinates
                                                            let (event_start_pixels, _, _) = calculate_event_position(&event_for_drag, date_for_drag, time_increment, print_pixels_per_hour, print_start_hour);
                                                            let event_start_pixels = event_start_pixels as f64;

                                                            // Convert click position to day column coordinates
                                                            let click_y = event_start_pixels + click_y_relative;

                                                            // Store the offset from the event's top where the user clicked
                                                            // This will be used to maintain the relative click position
                                                            let offset_y = click_y_relative;

                                                            // Start drag tracking from where we clicked (in day column coordinates)
                                                            drag_state.set(Some(DragState {
                                                                is_dragging: true,
                                                                drag_type: DragType::MoveEvent(event_for_drag.clone()),
                                                                start_date: date_for_drag,
                                                                start_y: click_y,
                                                                current_y: click_y,
                                                                offset_y,
                                                                has_moved: false,
                                                            }));
                                                            e.prevent_default();
                                                        })
                                                    };

                                                    let oncontextmenu = {
                                                        if let Some(callback) = &props.on_event_context_menu {
                                                            let callback = callback.clone();
                                                            let event = event.clone();
                                                            let drag_state_for_context = drag_state.clone();
                                                            Some(Callback::from(move |e: web_sys::MouseEvent| {
                                                                // Check if we're currently dragging - if so, prevent context menu
                                                                if let Some(drag) = (*drag_state_for_context).clone() {
                                                                    if drag.is_dragging {
                                                                        e.prevent_default();
                                                                        return;
                                                                    }
                                                                }

                                                                e.prevent_default();
                                                                e.stop_propagation(); // Prevent calendar context menu from also triggering
                                                                callback.emit((e, event.clone()));
                                                            }))
                                                        } else {
                                                            None
                                                        }
                                                    };

                                                    // Format time display for the event
                                                    let time_display = if event.all_day {
                                                        "All Day".to_string()
                                                    } else {
                                                        let local_start = event.dtstart;
                                                        if let Some(end) = event.dtend {
                                                            let local_end = end;

                                                            // Check if both times are in same AM/PM period to avoid redundancy
                                                            let start_is_am = local_start.hour() < 12;
                                                            let end_is_am = local_end.hour() < 12;

                                                            if start_is_am == end_is_am {
                                                                // Same AM/PM period - show "9:00 - 10:30 AM"
                                                                format!("{} - {}",
                                                                    local_start.format("%I:%M").to_string().trim_start_matches('0'),
                                                                    local_end.format("%I:%M %p")
                                                                )
                                                            } else {
                                                                // Different AM/PM periods - show "9:00 AM - 2:30 PM"
                                                                format!("{} - {}",
                                                                    local_start.format("%I:%M %p"),
                                                                    local_end.format("%I:%M %p")
                                                                )
                                                            }
                                                        } else {
                                                            // No end time, just show start time
                                                            format!("{}", local_start.format("%I:%M %p"))
                                                        }
                                                    };

                                                    // Check if this event is currently being dragged or resized
                                                    let is_being_dragged = if let Some(drag) = (*drag_state).clone() {
                                                        match &drag.drag_type {
                                                            DragType::MoveEvent(dragged_event) =>
                                                                dragged_event.uid == event.uid && drag.is_dragging,
                                                            DragType::ResizeEventStart(dragged_event) =>
                                                                dragged_event.uid == event.uid && drag.is_dragging,
                                                            DragType::ResizeEventEnd(dragged_event) =>
                                                                dragged_event.uid == event.uid && drag.is_dragging,
                                                            _ => false,
                                                        }
                                                    } else {
                                                        false
                                                    };

                                                    if is_being_dragged {
                                                        // Hide the original event while being dragged
                                                        Some(html! {})
                                                    } else {
                                                        // Create resize handles for left-click resize
                                                        let resize_start_handler = {
                                                            let drag_state = drag_state.clone();
                                                            let event_for_resize = event.clone();
                                                            let date_for_drag = *date;
                                                            let time_increment = props.time_increment;
                                                            Callback::from(move |e: web_sys::MouseEvent| {
                                                                e.stop_propagation();

                                                                let relative_y = e.layer_y() as f64;
                                                                let relative_y = if relative_y > 0.0 { relative_y } else { e.offset_y() as f64 };
                                                                let snapped_y = snap_to_increment(relative_y, time_increment);

                                                                drag_state.set(Some(DragState {
                                                                    is_dragging: true,
                                                                    drag_type: DragType::ResizeEventStart(event_for_resize.clone()),
                                                                    start_date: date_for_drag,
                                                                    start_y: snapped_y,
                                                                    current_y: snapped_y,
                                                                    offset_y: 0.0,
                                                                    has_moved: false,
                                                                }));
                                                                e.prevent_default();
                                                            })
                                                        };

                                                        let resize_end_handler = {
                                                            let drag_state = drag_state.clone();
                                                            let event_for_resize = event.clone();
                                                            let date_for_drag = *date;
                                                            let time_increment = props.time_increment;
                                                            Callback::from(move |e: web_sys::MouseEvent| {
                                                                e.stop_propagation();

                                                                let relative_y = e.layer_y() as f64;
                                                                let relative_y = if relative_y > 0.0 { relative_y } else { e.offset_y() as f64 };
                                                                let snapped_y = snap_to_increment(relative_y, time_increment);

                                                                drag_state.set(Some(DragState {
                                                                    is_dragging: true,
                                                                    drag_type: DragType::ResizeEventEnd(event_for_resize.clone()),
                                                                    start_date: date_for_drag,
                                                                    start_y: snapped_y,
                                                                    current_y: snapped_y,
                                                                    offset_y: 0.0,
                                                                    has_moved: false,
                                                                }));
                                                                e.prevent_default();
                                                            })
                                                        };

                                                        Some(html! {
                                                            <div
                                                                class={classes!(
                                                                    "week-event",
                                                                    if is_refreshing { Some("refreshing") } else { None },
                                                                    if is_all_day { Some("all-day") } else { None }
                                                                )}
                                                                style={
                                                                    let (column_idx, total_columns) = event_layouts[event_idx];
                                                                    let column_width = if total_columns > 1 {
                                                                        format!("calc((100% - 8px) / {})", total_columns) // Account for 4px margins on each side
                                                                    } else {
                                                                        "calc(100% - 8px)".to_string()
                                                                    };
                                                                    let left_offset = if total_columns > 1 {
                                                                        format!("calc(4px + {} * (100% - 8px) / {})", column_idx, total_columns)
                                                                    } else {
                                                                        "4px".to_string()
                                                                    };
                                                                    
                                                                    format!(
                                                                        "background-color: {}; top: {}px; height: {}px; left: {}; width: {}; right: auto;",
                                                                        event_color,
                                                                        start_pixels,
                                                                        duration_pixels,
                                                                        left_offset,
                                                                        column_width
                                                                    )
                                                                }
                                                                data-external={event.categories.contains(&"__EXTERNAL_CALENDAR__".to_string()).to_string()}
                                                                {onclick}
                                                                {oncontextmenu}
                                                                onmousedown={onmousedown_event}
                                                            >
                                                                // Top resize handle
                                                                {if !is_all_day {
                                                                    html! {
                                                                        <div
                                                                            class="resize-handle resize-handle-top"
                                                                            onmousedown={resize_start_handler}
                                                                        />
                                                                    }
                                                                } else {
                                                                    html! {}
                                                                }}

                                                                // Event content
                                                                <div class="event-content">
                                                                    <div class="event-title-row">
                                                                        <span class="event-title">{event.summary.as_ref().unwrap_or(&"Untitled".to_string())}</span>
                                                                        if !event.alarms.is_empty() {
                                                                            <i class="fas fa-bell event-reminder-icon" title="Has reminders"></i>
                                                                        }
                                                                    </div>
                                                                    {if !is_all_day && duration_pixels > 30.0 {
                                                                        html! { <div class="event-time">{time_display}</div> }
                                                                    } else {
                                                                        html! {}
                                                                    }}
                                                                </div>

                                                                // Bottom resize handle
                                                                {if !is_all_day {
                                                                    html! {
                                                                        <div
                                                                            class="resize-handle resize-handle-bottom"
                                                                            onmousedown={resize_end_handler}
                                                                        />
                                                                    }
                                                                } else {
                                                                    html! {}
                                                                }}
                                                            </div>
                                                        })
                                                    }
                                                }).collect::<Html>()
                                            }
                                        </div>

                                        // Temporary event box during drag
                                        {
                                            if let Some(drag) = (*drag_state).clone() {
                                                if drag.is_dragging && drag.has_moved && drag.start_date == *date {
                                                    match &drag.drag_type {
                                                        DragType::CreateEvent => {
                                                            let start_y = drag.start_y.min(drag.current_y);
                                                            let end_y = drag.start_y.max(drag.current_y);
                                                            let height = (drag.current_y - drag.start_y).abs().max(20.0);

                                                            // Convert pixels to times for display
                                                            let start_time = pixels_to_time(start_y, props.time_increment);
                                                            let end_time = pixels_to_time(end_y, props.time_increment);

                                                            html! {
                                                                <div
                                                                    class="temp-event-box"
                                                                    style={format!("top: {}px; height: {}px;", start_y, height)}
                                                                >
                                                                    {format!("{} - {}", start_time.format("%I:%M %p"), end_time.format("%I:%M %p"))}
                                                                </div>
                                                            }
                                                        },
                                                        DragType::MoveEvent(event) => {
                                                            // Calculate the event's new position accounting for click offset
                                                            let unsnapped_position = drag.current_y - drag.offset_y;
                                                            // Snap the final position to maintain time increment alignment
                                                            let preview_position = snap_to_increment(unsnapped_position, props.time_increment);
                                                            let new_start_time = pixels_to_time(preview_position, props.time_increment);
                                                            let original_duration = if let Some(end) = event.dtend {
                                                                end.signed_duration_since(event.dtstart)
                                                            } else {
                                                                chrono::Duration::hours(1)
                                                            };
                                                            let duration_pixels = (original_duration.num_minutes() as f64).max(20.0);
                                                            let new_end_time = new_start_time + original_duration;

                                                            let event_color = get_event_color(event);

                                                            html! {
                                                                <div
                                                                    class="temp-event-box moving-event"
                                                                    style={format!("top: {}px; height: {}px; background-color: {}; opacity: 0.7;", preview_position, duration_pixels, event_color)}
                                                                    data-external={event.categories.contains(&"__EXTERNAL_CALENDAR__".to_string()).to_string()}
                                                                >
                                                                    <div class="event-title">{event.summary.as_ref().unwrap_or(&"Untitled".to_string())}</div>
                                                                    {if duration_pixels > 30.0 {
                                                                        html! { <div class="event-time">{format!("{} - {}", new_start_time.format("%I:%M %p"), new_end_time.format("%I:%M %p"))}</div> }
                                                                    } else {
                                                                        html! {}
                                                                    }}
                                                                </div>
                                                            }
                                                        },
                                                        DragType::ResizeEventStart(event) => {
                                                            // Show the event being resized from the start
                                                            let new_start_time = pixels_to_time(drag.current_y, props.time_increment);
                                                            let original_end = if let Some(end) = event.dtend {
                                                                end                                                            } else {
                                                                event.dtstart + chrono::Duration::hours(1)
                                                            };

                                                            // Calculate positions for the preview
                                                            let (original_start_pixels, _, _) = calculate_event_position(event, drag.start_date, props.time_increment, props.print_pixels_per_hour, props.print_start_hour);
                                                            let original_duration = original_end.signed_duration_since(event.dtstart);
                                                            let original_end_pixels = original_start_pixels + (original_duration.num_minutes() as f32);

                                                            let new_start_pixels = drag.current_y;
                                                            let new_height = (original_end_pixels as f64 - new_start_pixels).max(20.0);

                                                            let event_color = get_event_color(event);

                                                            html! {
                                                                <div
                                                                    class="temp-event-box resizing-event"
                                                                    style={format!("top: {}px; height: {}px; background-color: {}; opacity: 0.7;", new_start_pixels, new_height, event_color)}
                                                                    data-external={event.categories.contains(&"__EXTERNAL_CALENDAR__".to_string()).to_string()}
                                                                >
                                                                    <div class="event-title">{event.summary.as_ref().unwrap_or(&"Untitled".to_string())}</div>
                                                                    {if new_height > 30.0 {
                                                                        html! { <div class="event-time">{format!("{} - {}", new_start_time.format("%I:%M %p"), original_end.time().format("%I:%M %p"))}</div> }
                                                                    } else {
                                                                        html! {}
                                                                    }}
                                                                </div>
                                                            }
                                                        },
                                                        DragType::ResizeEventEnd(event) => {
                                                            // Show the event being resized from the end
                                                            let new_end_time = pixels_to_time(drag.current_y, props.time_increment);
                                                            let original_start = event.dtstart;

                                                            // Calculate positions for the preview
                                                            let (original_start_pixels, _, _) = calculate_event_position(event, drag.start_date, props.time_increment, props.print_pixels_per_hour, props.print_start_hour);

                                                            let new_end_pixels = drag.current_y;
                                                            let new_height = (new_end_pixels - original_start_pixels as f64).max(20.0);

                                                            let event_color = get_event_color(event);

                                                            html! {
                                                                <div
                                                                    class="temp-event-box resizing-event"
                                                                    style={format!("top: {}px; height: {}px; background-color: {}; opacity: 0.7;", original_start_pixels, new_height, event_color)}
                                                                    data-external={event.categories.contains(&"__EXTERNAL_CALENDAR__".to_string()).to_string()}
                                                                >
                                                                    <div class="event-title">{event.summary.as_ref().unwrap_or(&"Untitled".to_string())}</div>
                                                                    {if new_height > 30.0 {
                                                                        html! { <div class="event-time">{format!("{} - {}", original_start.time().format("%I:%M %p"), new_end_time.format("%I:%M %p"))}</div> }
                                                                    } else {
                                                                        html! {}
                                                                    }}
                                                                </div>
                                                            }
                                                        }
                                                    }
                                                } else {
                                                    html! {}
                                                }
                                            } else {
                                                html! {}
                                            }
                                        }

                                        // Current time indicator - only show on today
                                        {
                                            if *date == props.today {
                                                let current_time_position = calculate_current_time_position(props.time_increment);
                                                let current_time_str = current_time.time().format("%I:%M %p").to_string();
                                                
                                                html! {
                                                    <div class="current-time-indicator-container">
                                                        <div 
                                                            class="current-time-indicator"
                                                            style={format!("top: {}px;", current_time_position)}
                                                        >
                                                            <div class="current-time-dot"></div>
                                                            <div class="current-time-line"></div>
                                                            <div class="current-time-label">{current_time_str}</div>
                                                        </div>
                                                    </div>
                                                }
                                            } else {
                                                html! {}
                                            }
                                        }
                                    </div>
                                }
                            }).collect::<Html>()
                        }
                    </div>
                </div>
            </div>

            // Recurring event modification modal
            if let Some(edit) = (*pending_recurring_edit).clone() {
                <RecurringEditModal
                    show={true}
                    event={edit.event}
                    new_start={edit.new_start}
                    new_end={edit.new_end}
                    on_choice={on_recurring_choice}
                    on_cancel={on_recurring_cancel}
                />
            } else {
                <></>
            }
        </div>
    }
}

fn get_start_of_week(date: NaiveDate) -> NaiveDate {
    let weekday = date.weekday();
    let days_from_sunday = match weekday {
        Weekday::Sun => 0,
        Weekday::Mon => 1,
        Weekday::Tue => 2,
        Weekday::Wed => 3,
        Weekday::Thu => 4,
        Weekday::Fri => 5,
        Weekday::Sat => 6,
    };
    date - Duration::days(days_from_sunday)
}

fn get_weekday_name(weekday: Weekday) -> &'static str {
    match weekday {
        Weekday::Sun => "Sun",
        Weekday::Mon => "Mon",
        Weekday::Tue => "Tue",
        Weekday::Wed => "Wed",
        Weekday::Thu => "Thu",
        Weekday::Fri => "Fri",
        Weekday::Sat => "Sat",
    }
}

// Calculate the pixel position of an event based on its time
// Snap pixel position based on time increment and grid scaling
// In 30-minute mode: 60px per hour (1px = 1 minute)
// In 15-minute mode: 120px per hour (2px = 1 minute)
fn snap_to_increment(pixels: f64, increment: u32) -> f64 {
    let pixels_per_minute = if increment == 15 { 2.0 } else { 1.0 };
    let increment_px = increment as f64 * pixels_per_minute;
    (pixels / increment_px).round() * increment_px
}

// Convert pixel position to time (inverse of time to pixels)
fn pixels_to_time(pixels: f64, time_increment: u32) -> NaiveTime {
    let pixels_per_minute = if time_increment == 15 { 2.0 } else { 1.0 };
    let total_minutes = pixels / pixels_per_minute;
    let hours = (total_minutes / 60.0) as u32;
    let minutes = (total_minutes % 60.0) as u32;

    // Handle midnight boundary - check against scaled boundary
    let max_pixels = 1440.0 * pixels_per_minute; // 24 hours in pixels
    if pixels >= max_pixels {
        return NaiveTime::from_hms_opt(0, 0, 0).unwrap();
    }

    // Clamp to valid time range for within-day times
    let hours = hours.min(23);
    let minutes = minutes.min(59);

    NaiveTime::from_hms_opt(hours, minutes, 0).unwrap_or(NaiveTime::from_hms_opt(0, 0, 0).unwrap())
}

fn calculate_event_position(event: &VEvent, date: NaiveDate, time_increment: u32, print_pixels_per_hour: Option<f64>, print_start_hour: Option<u32>) -> (f32, f32, bool) {
    // Events are already in local time
    let local_start = event.dtstart;
    
    // Events should display based on their local date, since we now store proper UTC times
    // Convert the UTC stored time back to local time to determine display date
    let event_date = local_start.date();
    
    if event_date != date {
        return (0.0, 0.0, false); // Event not on this date
    }

    // Handle all-day events - they appear at the top
    if event.all_day {
        return (0.0, 30.0, true); // Position at top, 30px height, is_all_day = true
    }

    // Calculate start position in pixels
    let start_hour = local_start.hour() as f32;
    let start_minute = local_start.minute() as f32;
    let pixels_per_hour = if let Some(print_pph) = print_pixels_per_hour {
        print_pph as f32 // Use the dynamic print mode calculation
    } else {
        if time_increment == 15 { 120.0 } else { 60.0 } // Default values
    };
    
    // In print mode, offset by the start hour to show relative position within visible range
    let hour_offset = if let Some(print_start) = print_start_hour {
        print_start as f32
    } else {
        0.0 // No offset for normal view (starts at midnight)
    };
    
    let start_pixels = ((start_hour + start_minute / 60.0) - hour_offset) * pixels_per_hour;

    // Calculate duration and height
    let duration_pixels = if let Some(end) = event.dtend {
        let local_end = end;
        let end_date = local_end.date();

        // Handle events that span multiple days by capping at midnight
        if end_date > date {
            // Event continues past midnight, cap at end of visible range
            let max_hour = if let Some(_print_start) = print_start_hour { 24.0 } else { 24.0 };
            let max_pixels = (max_hour - hour_offset) * pixels_per_hour;
            (max_pixels - start_pixels).max(20.0)
        } else {
            let end_hour = local_end.hour() as f32;
            let end_minute = local_end.minute() as f32;
            let end_pixels = ((end_hour + end_minute / 60.0) - hour_offset) * pixels_per_hour;
            (end_pixels - start_pixels).max(20.0) // Minimum 20px height
        }
    } else {
        pixels_per_hour // Default 1 hour if no end time
    };
    (start_pixels, duration_pixels, false) // is_all_day = false
}

// Check if two events overlap in time
fn events_overlap(event1: &VEvent, event2: &VEvent) -> bool {
    // All-day events don't overlap with timed events for width calculation purposes
    if event1.all_day || event2.all_day {
        return false;
    }
    
    let start1 = event1.dtstart;
    let end1 = if let Some(end) = event1.dtend {
        end
    } else {
        start1 + chrono::Duration::hours(1) // Default 1 hour duration
    };
    
    let start2 = event2.dtstart;
    let end2 = if let Some(end) = event2.dtend {
        end
    } else {
        start2 + chrono::Duration::hours(1) // Default 1 hour duration
    };
    
    // Events overlap if one starts before the other ends
    start1 < end2 && start2 < end1
}

// Calculate layout columns for overlapping events
fn calculate_event_layout(events: &[VEvent], date: NaiveDate, time_increment: u32) -> Vec<(usize, usize)> {
    
    // Filter and sort events that should appear on this date (excluding all-day events)
    let mut day_events: Vec<_> = events.iter()
        .enumerate()
        .filter_map(|(idx, event)| {
            // Skip all-day events as they don't participate in timed event overlap calculations
            if event.all_day {
                return None;
            }
            
            let (_, _, _) = calculate_event_position(event, date, time_increment, None, None);
            let local_start = event.dtstart;
            let event_date = local_start.date();
            if event_date == date || 
                (event_date == date - chrono::Duration::days(1) && local_start.hour() >= 20) {
                Some((idx, event))
            } else {
                None
            }
        })
        .collect();
    
    // Sort by start time
    day_events.sort_by_key(|(_, event)| event.dtstart);
    
    // For each event, find all events it overlaps with
    let mut event_columns = vec![(0, 1); events.len()]; // (column_idx, total_columns)
    
    for i in 0..day_events.len() {
        let (orig_idx_i, event_i) = day_events[i];
        
        // Find all events that overlap with this event
        let mut overlapping_events = vec![i];
        for j in 0..day_events.len() {
            if i != j {
                let (_, event_j) = day_events[j];
                if events_overlap(event_i, event_j) {
                    overlapping_events.push(j);
                }
            }
        }
        
        // If this event doesn't overlap with anything, it gets full width
        if overlapping_events.len() == 1 {
            event_columns[orig_idx_i] = (0, 1);
        } else {
            // This event overlaps - we need to calculate column layout
            // Sort the overlapping group by start time
            overlapping_events.sort_by_key(|&idx| day_events[idx].1.dtstart);
            
            // Assign columns using a greedy algorithm
            let mut columns: Vec<Vec<usize>> = Vec::new();
            
            for &event_idx in &overlapping_events {
                let (orig_idx, event) = day_events[event_idx];
                
                // Find the first column where this event doesn't overlap with existing events
                let mut placed = false;
                for (col_idx, column) in columns.iter_mut().enumerate() {
                    let can_place = column.iter().all(|&existing_idx| {
                        let (_, existing_event) = day_events[existing_idx];
                        !events_overlap(event, existing_event)
                    });
                    
                    if can_place {
                        column.push(event_idx);
                        event_columns[orig_idx] = (col_idx, columns.len());
                        placed = true;
                        break;
                    }
                }
                
                if !placed {
                    // Create new column
                    columns.push(vec![event_idx]);
                    event_columns[orig_idx] = (columns.len() - 1, columns.len());
                }
            }
            
            // Update total_columns for all events in this overlapping group
            let total_columns = columns.len();
            for &event_idx in &overlapping_events {
                let (orig_idx, _) = day_events[event_idx];
                event_columns[orig_idx].1 = total_columns;
            }
        }
    }
    
    event_columns
}

// Check if an all-day event spans the given date
fn event_spans_date(event: &VEvent, date: NaiveDate) -> bool {
    let start_date = if event.all_day {
        // For all-day events, extract date directly from UTC without timezone conversion
        // since all-day events are stored at noon UTC to avoid timezone boundary issues
        event.dtstart.date()
    } else {
        event.dtstart.date()
    };
    
    let end_date = if let Some(dtend) = event.dtend {
        if event.all_day {
            // For all-day events, dtend is set to the day after the last day (RFC 5545)
            // Extract date directly from UTC and subtract a day to get actual last day
            dtend.date() - chrono::Duration::days(1)
        } else {
            // For timed events, use timezone conversion
            dtend.date()
        }
    } else {
        // Single day event
        start_date
    };
    
    // Check if the given date falls within the event's date range
    date >= start_date && date <= end_date
}
