use crate::components::event_form::*;
use crate::components::EditAction;
use crate::models::ical::VEvent;
use crate::services::calendar_service::CalendarInfo;
use gloo_storage::{LocalStorage, Storage};
use yew::prelude::*;

#[derive(Properties, PartialEq)]
pub struct CreateEventModalProps {
    pub is_open: bool,
    pub on_close: Callback<()>,
    pub on_create: Callback<EventCreationData>,
    pub available_calendars: Vec<CalendarInfo>,
    pub selected_date: Option<chrono::NaiveDate>,
    pub initial_start_time: Option<chrono::NaiveTime>,
    pub initial_end_time: Option<chrono::NaiveTime>,
    #[prop_or_default]
    pub event_to_edit: Option<VEvent>,
    #[prop_or_default]
    pub edit_scope: Option<EditAction>,
}

#[function_component(CreateEventModal)]
pub fn create_event_modal(props: &CreateEventModalProps) -> Html {
    let active_tab = use_state(|| ModalTab::default());
    let event_data = use_state(|| EventCreationData::default());

    // Initialize data when modal opens
    {
        let event_data = event_data.clone();
        let is_open = props.is_open;
        let event_to_edit = props.event_to_edit.clone();
        let selected_date = props.selected_date;
        let initial_start_time = props.initial_start_time;
        let initial_end_time = props.initial_end_time;
        let edit_scope = props.edit_scope.clone();
        let available_calendars = props.available_calendars.clone();
        
        use_effect_with(is_open, move |&is_open| {
            if is_open {
                let mut data = if let Some(event) = &event_to_edit {
                    // Convert VEvent to EventCreationData for editing
                    vevent_to_creation_data(event, &available_calendars)
                } else if let Some(date) = selected_date {
                    let mut data = EventCreationData::default();
                    data.start_date = date;
                    data.end_date = date;
                    if let Some(start_time) = initial_start_time {
                        data.start_time = start_time;
                    }
                    if let Some(end_time) = initial_end_time {
                        data.end_time = end_time;
                    }
                    data
                } else {
                    EventCreationData::default()
                };

                // Set default calendar
                if data.selected_calendar.is_none() && !available_calendars.is_empty() {
                    // For new events, try to use the last used calendar
                    if event_to_edit.is_none() {
                        // Try to get last used calendar from localStorage
                        if let Ok(last_used_calendar) = LocalStorage::get::<String>("last_used_calendar") {
                            // Check if the last used calendar is still available
                            if available_calendars.iter().any(|cal| cal.path == last_used_calendar) {
                                data.selected_calendar = Some(last_used_calendar);
                            } else {
                                // Fall back to first available calendar
                                data.selected_calendar = Some(available_calendars[0].path.clone());
                            }
                        } else {
                            // No last used calendar, use first available
                            data.selected_calendar = Some(available_calendars[0].path.clone());
                        }
                    } else {
                        // For editing existing events, keep the current calendar as default
                        data.selected_calendar = Some(available_calendars[0].path.clone());
                    }
                }

                // Set edit scope if provided
                if let Some(scope) = &edit_scope {
                    data.edit_scope = Some(scope.clone());
                }

                event_data.set(data);
            }
            || ()
        });
    }

    if !props.is_open {
        return html! {};
    }

    let on_backdrop_click = {
        let on_close = props.on_close.clone();
        Callback::from(move |e: MouseEvent| {
            if e.target() == e.current_target() {
                on_close.emit(());
            }
        })
    };

    let switch_to_tab = {
        let active_tab = active_tab.clone();
        Callback::from(move |tab: ModalTab| {
            active_tab.set(tab);
        })
    };

    let on_save = {
        let event_data = event_data.clone();
        let on_create = props.on_create.clone();
        let event_to_edit = props.event_to_edit.clone();
        Callback::from(move |_: MouseEvent| {
            let mut data = (*event_data).clone();
            
            // If we're editing an existing event, mark it as an update operation
            if let Some(ref original_event) = event_to_edit {
                // Set the original UID so the backend knows to update instead of create
                data.original_uid = Some(original_event.uid.clone());
            }
            
            on_create.emit(data);
        })
    };

    let on_close = props.on_close.clone();
    let on_close_header = on_close.clone();

    let tab_props = TabProps {
        data: event_data.clone(),
        available_calendars: props.available_calendars.clone(),
    };

    html! {
        <div class="modal-backdrop" onclick={on_backdrop_click}>
            <div class="modal-content create-event-modal">
                <div class="modal-header">
                    <h3>
                        {if props.event_to_edit.is_some() { "Edit Event" } else { "Create Event" }}
                    </h3>
                    <button class="modal-close" onclick={Callback::from(move |_| on_close_header.emit(()))}>
                        {"×"}
                    </button>
                </div>

                <div class="modal-tabs">
                    <div class="tab-navigation">
                        <button
                            class={if *active_tab == ModalTab::BasicDetails { "tab-button active" } else { "tab-button" }}
                            onclick={{
                                let switch_to_tab = switch_to_tab.clone();
                                Callback::from(move |_| switch_to_tab.emit(ModalTab::BasicDetails))
                            }}
                        >
                            {"Basic"}
                        </button>
                        <button
                            class={if *active_tab == ModalTab::Advanced { "tab-button active" } else { "tab-button" }}
                            onclick={{
                                let switch_to_tab = switch_to_tab.clone();
                                Callback::from(move |_| switch_to_tab.emit(ModalTab::Advanced))
                            }}
                        >
                            {"Advanced"}
                        </button>
                        <button
                            class={if *active_tab == ModalTab::People { "tab-button active" } else { "tab-button" }}
                            onclick={{
                                let switch_to_tab = switch_to_tab.clone();
                                Callback::from(move |_| switch_to_tab.emit(ModalTab::People))
                            }}
                        >
                            {"People"}
                        </button>
                        <button
                            class={if *active_tab == ModalTab::Categories { "tab-button active" } else { "tab-button" }}
                            onclick={{
                                let switch_to_tab = switch_to_tab.clone();
                                Callback::from(move |_| switch_to_tab.emit(ModalTab::Categories))
                            }}
                        >
                            {"Categories"}
                        </button>
                        <button
                            class={if *active_tab == ModalTab::Location { "tab-button active" } else { "tab-button" }}
                            onclick={{
                                let switch_to_tab = switch_to_tab.clone();
                                Callback::from(move |_| switch_to_tab.emit(ModalTab::Location))
                            }}
                        >
                            {"Location"}
                        </button>
                        <button
                            class={if *active_tab == ModalTab::Reminders { "tab-button active" } else { "tab-button" }}
                            onclick={{
                                let switch_to_tab = switch_to_tab.clone();
                                Callback::from(move |_| switch_to_tab.emit(ModalTab::Reminders))
                            }}
                        >
                            {"Reminders"}
                        </button>
                    </div>

                    <div class="modal-body">
                        <div class="tab-content">
                            {
                                match *active_tab {
                                    ModalTab::BasicDetails => html! { <BasicDetailsTab ..tab_props /> },
                                    ModalTab::Advanced => html! { <AdvancedTab ..tab_props /> },
                                    ModalTab::People => html! { <PeopleTab ..tab_props /> },
                                    ModalTab::Categories => html! { <CategoriesTab ..tab_props /> },
                                    ModalTab::Location => html! { <LocationTab ..tab_props /> },
                                    ModalTab::Reminders => html! { <RemindersTab ..tab_props /> },
                                }
                            }
                        </div>
                    </div>
                </div>

                <div class="modal-footer">
                    <div class="modal-actions">
                        <button class="btn btn-secondary" onclick={Callback::from(move |_| on_close.emit(()))}>
                            {"Cancel"}
                        </button>
                        <button class="btn btn-primary" onclick={on_save}>
                            {if props.event_to_edit.is_some() { "Update Event" } else { "Create Event" }}
                        </button>
                    </div>
                </div>
            </div>
        </div>
    }
}

// Convert VEvent to EventCreationData for editing
fn vevent_to_creation_data(event: &crate::models::ical::VEvent, available_calendars: &[CalendarInfo]) -> EventCreationData {
    
    // VEvent fields are already local time (NaiveDateTime)
    let start_local = event.dtstart;
    let end_local = if let Some(dtend) = event.dtend {
        dtend
    } else {
        // Default to 1 hour after start if no end time
        start_local + chrono::Duration::hours(1)
    };

    EventCreationData {
        // Basic event info
        title: event.summary.clone().unwrap_or_default(),
        description: event.description.clone().unwrap_or_default(),
        location: event.location.clone().unwrap_or_default(),
        all_day: event.all_day,
        
        // Timing
        start_date: start_local.date(),
        end_date: if event.all_day {
            // For all-day events, subtract one day to convert from exclusive to inclusive end date
            // (UI expects inclusive dates, but iCalendar stores exclusive end dates)
            end_local.date() - chrono::Duration::days(1)
        } else {
            end_local.date()
        },
        start_time: start_local.time(),
        end_time: end_local.time(),
        
        // Classification
        status: match event.status {
            Some(crate::models::ical::EventStatus::Tentative) => EventStatus::Tentative,
            Some(crate::models::ical::EventStatus::Confirmed) => EventStatus::Confirmed,
            Some(crate::models::ical::EventStatus::Cancelled) => EventStatus::Cancelled,
            None => EventStatus::Confirmed,
        },
        class: match event.class {
            Some(crate::models::ical::EventClass::Public) => EventClass::Public,
            Some(crate::models::ical::EventClass::Private) => EventClass::Private,
            Some(crate::models::ical::EventClass::Confidential) => EventClass::Confidential,
            None => EventClass::Public,
        },
        priority: event.priority,
        
        // People
        organizer: event.organizer.as_ref().map(|o| o.cal_address.clone()).unwrap_or_default(),
        attendees: event.attendees.iter()
            .map(|a| a.cal_address.clone())
            .collect::<Vec<_>>()
            .join(","),
        
        // Categorization  
        categories: event.categories.join(","),
        
        // Reminders - Use VAlarms from the event
        alarms: event.alarms.clone(),
        
        // Recurrence - Parse RRULE if present
        recurrence: if let Some(ref rrule_str) = event.rrule {
            web_sys::console::log_1(&format!("🐛 MODAL DEBUG: Event has RRULE: {}", rrule_str).into());
            parse_rrule_frequency(rrule_str)
        } else {
            web_sys::console::log_1(&"🐛 MODAL DEBUG: Event has no RRULE (singleton)".into());
            RecurrenceType::None
        },
        recurrence_interval: if let Some(ref rrule_str) = event.rrule {
            parse_rrule_interval(rrule_str)
        } else {
            1
        },
        recurrence_until: if let Some(ref rrule_str) = event.rrule {
            parse_rrule_until(rrule_str)
        } else {
            None
        },
        recurrence_count: if let Some(ref rrule_str) = event.rrule {
            parse_rrule_count(rrule_str)
        } else {
            None
        },
        recurrence_days: if let Some(ref rrule_str) = event.rrule {
            parse_rrule_days(rrule_str)
        } else {
            vec![false; 7]
        },
        
        // Advanced recurrence
        monthly_by_day: None,
        monthly_by_monthday: None,
        yearly_by_month: vec![false; 12],
        
        // Calendar selection - try to find the calendar this event belongs to
        selected_calendar: if let Some(ref calendar_path) = event.calendar_path {
            if available_calendars.iter().any(|cal| cal.path == *calendar_path) {
                Some(calendar_path.clone())
            } else if let Some(first_calendar) = available_calendars.first() {
                Some(first_calendar.path.clone())
            } else {
                None
            }
        } else if let Some(first_calendar) = available_calendars.first() {
            Some(first_calendar.path.clone())
        } else {
            None
        },
        
        // Edit tracking
        edit_scope: {
            web_sys::console::log_1(&"🐛 MODAL DEBUG: Setting edit_scope to None for vevent_to_creation_data".into());
            None // Will be set by the modal after creation
        },
        changed_fields: vec![],
        original_uid: Some(event.uid.clone()), // Preserve original UID for editing
        occurrence_date: Some(start_local.date()), // The occurrence date being edited
    }
}

// Parse RRULE frequency component
fn parse_rrule_frequency(rrule: &str) -> RecurrenceType {
    if rrule.contains("FREQ=DAILY") {
        RecurrenceType::Daily
    } else if rrule.contains("FREQ=WEEKLY") {
        RecurrenceType::Weekly
    } else if rrule.contains("FREQ=MONTHLY") {
        RecurrenceType::Monthly
    } else if rrule.contains("FREQ=YEARLY") {
        RecurrenceType::Yearly
    } else {
        RecurrenceType::None
    }
}

// Parse RRULE interval component
fn parse_rrule_interval(rrule: &str) -> u32 {
    if let Some(start) = rrule.find("INTERVAL=") {
        let interval_part = &rrule[start + 9..];
        if let Some(end) = interval_part.find(';') {
            interval_part[..end].parse().unwrap_or(1)
        } else {
            interval_part.parse().unwrap_or(1)
        }
    } else {
        1
    }
}

// Parse RRULE count component
fn parse_rrule_count(rrule: &str) -> Option<u32> {
    if let Some(start) = rrule.find("COUNT=") {
        let count_part = &rrule[start + 6..];
        if let Some(end) = count_part.find(';') {
            count_part[..end].parse().ok()
        } else {
            count_part.parse().ok()
        }
    } else {
        None
    }
}

// Parse RRULE until component
fn parse_rrule_until(rrule: &str) -> Option<chrono::NaiveDate> {
    if let Some(start) = rrule.find("UNTIL=") {
        let until_part = &rrule[start + 6..];
        let until_str = if let Some(end) = until_part.find(';') {
            &until_part[..end]
        } else {
            until_part
        };
        
        // UNTIL can be in format YYYYMMDD or YYYYMMDDTHHMMSSZ
        let date_part = if until_str.len() >= 8 {
            &until_str[..8]
        } else {
            until_str
        };
        
        // Parse YYYYMMDD format
        if date_part.len() == 8 {
            if let (Ok(year), Ok(month), Ok(day)) = (
                date_part[0..4].parse::<i32>(),
                date_part[4..6].parse::<u32>(),
                date_part[6..8].parse::<u32>(),
            ) {
                chrono::NaiveDate::from_ymd_opt(year, month, day)
            } else {
                None
            }
        } else {
            None
        }
    } else {
        None
    }
}

// Parse RRULE BYDAY component for weekly recurrence
fn parse_rrule_days(rrule: &str) -> Vec<bool> {
    let mut days = vec![false; 7]; // [Sun, Mon, Tue, Wed, Thu, Fri, Sat]
    
    if let Some(start) = rrule.find("BYDAY=") {
        let byday_part = &rrule[start + 6..];
        let byday_str = if let Some(end) = byday_part.find(';') {
            &byday_part[..end]
        } else {
            byday_part
        };
        
        // Parse comma-separated day codes: SU,MO,TU,WE,TH,FR,SA
        for day_code in byday_str.split(',') {
            match day_code.trim() {
                "SU" => days[0] = true, // Sunday
                "MO" => days[1] = true, // Monday
                "TU" => days[2] = true, // Tuesday
                "WE" => days[3] = true, // Wednesday
                "TH" => days[4] = true, // Thursday
                "FR" => days[5] = true, // Friday
                "SA" => days[6] = true, // Saturday
                _ => {} // Ignore unknown day codes
            }
        }
    }
    
    days
}