use axum::{
    extract::{Path, Query, State},
    http::HeaderMap,
    response::Json,
};
use chrono::Datelike;
use serde::Deserialize;
use std::sync::Arc;

use crate::calendar::{CalDAVClient, CalendarEvent};
use crate::{
    models::{
        ApiError, CreateEventRequest, CreateEventResponse, DeleteEventRequest, DeleteEventResponse,
        UpdateEventRequest, UpdateEventResponse,
    },
    AppState,
};
use calendar_models::{
    Attendee, CalendarUser, EventClass, EventStatus, VEvent,
};

use super::auth::{extract_bearer_token, extract_password_header};

#[derive(Deserialize)]
pub struct CalendarQuery {
    pub year: Option<i32>,
    pub month: Option<u32>,
}

pub async fn get_calendar_events(
    State(state): State<Arc<AppState>>,
    Query(params): Query<CalendarQuery>,
    headers: HeaderMap,
) -> Result<Json<Vec<CalendarEvent>>, ApiError> {
    // Extract and verify token
    let token = extract_bearer_token(&headers)?;
    let password = extract_password_header(&headers)?;

    // Create CalDAV config from token and password
    let config = state
        .auth_service
        .caldav_config_from_token(&token, &password)?;
    let client = CalDAVClient::new(config);

    // Discover calendars if needed
    let calendar_paths = client
        .discover_calendars()
        .await
        .map_err(|e| ApiError::Internal(format!("Failed to discover calendars: {}", e)))?;

    if calendar_paths.is_empty() {
        return Ok(Json(vec![])); // No calendars found
    }

    // Fetch events from all calendars
    let mut all_events = Vec::new();
    for calendar_path in &calendar_paths {
        match client.fetch_events(calendar_path).await {
            Ok(mut events) => {
                // Set calendar_path for each event to identify which calendar it belongs to
                for event in &mut events {
                    event.calendar_path = Some(calendar_path.clone());
                }
                all_events.extend(events);
            }
            Err(e) => {
                eprintln!(
                    "Failed to fetch events from calendar {}: {}",
                    calendar_path, e
                );
                // Continue with other calendars instead of failing completely
            }
        }
    }

    // If year and month are specified, filter events
    if let (Some(year), Some(month)) = (params.year, params.month) {
        let target_date = chrono::NaiveDate::from_ymd_opt(year, month, 1).unwrap();
        let month_start = target_date;
        let month_end = if month == 12 {
            chrono::NaiveDate::from_ymd_opt(year + 1, 1, 1).unwrap()
        } else {
            chrono::NaiveDate::from_ymd_opt(year, month + 1, 1).unwrap()
        } - chrono::Duration::days(1);

        all_events.retain(|event| {
            let event_date = event.dtstart.date();
            
            // For non-recurring events, check if the event date is within the month
            if event.rrule.is_none() || event.rrule.as_ref().unwrap().is_empty() {
                let event_year = event.dtstart.year();
                let event_month = event.dtstart.month();
                return event_year == year && event_month == month;
            }
            
            // For recurring events, check if they could have instances in this month
            // Include if:
            // 1. The event starts before or during the requested month
            // 2. The event doesn't have an UNTIL date, OR the UNTIL date is after the month start
            if event_date > month_end {
                // Event starts after the requested month
                return false;
            }
            
            // Check UNTIL date in RRULE if present
            if let Some(ref rrule) = event.rrule {
                if let Some(until_pos) = rrule.find("UNTIL=") {
                    let until_part = &rrule[until_pos + 6..];
                    let until_end = until_part.find(';').unwrap_or(until_part.len());
                    let until_str = &until_part[..until_end];
                    
                    // Try to parse UNTIL date (format: YYYYMMDDTHHMMSSZ or YYYYMMDD)
                    if until_str.len() >= 8 {
                        if let Ok(until_date) = chrono::NaiveDate::parse_from_str(&until_str[..8], "%Y%m%d") {
                            if until_date < month_start {
                                // Recurring event ended before the requested month
                                return false;
                            }
                        }
                    }
                }
            }
            
            // Include the recurring event - the frontend will do proper expansion
            true
        });
    }

    Ok(Json(all_events))
}

pub async fn refresh_event(
    State(state): State<Arc<AppState>>,
    Path(uid): Path<String>,
    headers: HeaderMap,
) -> Result<Json<Option<CalendarEvent>>, ApiError> {
    let token = extract_bearer_token(&headers)?;
    let password = extract_password_header(&headers)?;

    // Create CalDAV config from token and password
    let config = state
        .auth_service
        .caldav_config_from_token(&token, &password)?;
    let client = CalDAVClient::new(config);

    // Discover calendars
    let calendar_paths = client
        .discover_calendars()
        .await
        .map_err(|e| ApiError::Internal(format!("Failed to discover calendars: {}", e)))?;

    // Search for the event by UID across all calendars
    for calendar_path in &calendar_paths {
        if let Ok(Some(mut event)) = client.fetch_event_by_uid(calendar_path, &uid).await {
            event.calendar_path = Some(calendar_path.clone());
            return Ok(Json(Some(event)));
        }
    }

    Ok(Json(None))
}

async fn fetch_event_by_href(
    client: &CalDAVClient,
    calendar_path: &str,
    event_href: &str,
) -> Result<Option<CalendarEvent>, crate::calendar::CalDAVError> {
    // This is a simplified implementation - in a real scenario, you'd want to fetch the specific event by href
    // For now, we'll fetch all events and find the matching one by href (inefficient but functional)
    let events = client.fetch_events(calendar_path).await?;

    println!("🔍 fetch_event_by_href: looking for href='{}'", event_href);
    println!(
        "🔍 Available events with hrefs: {:?}",
        events.iter().map(|e| (&e.uid, &e.href)).collect::<Vec<_>>()
    );

    // First try to match by exact href
    for event in &events {
        if let Some(stored_href) = &event.href {
            if stored_href == event_href {
                println!("✅ Found matching event by exact href: {}", event.uid);
                return Ok(Some(event.clone()));
            }
        }
    }

    // Fallback: try to match by UID extracted from href filename
    let filename = event_href.split('/').last().unwrap_or(event_href);
    let uid_from_href = filename.trim_end_matches(".ics");

    println!(
        "🔍 Fallback: trying UID match. filename='{}', uid='{}'",
        filename, uid_from_href
    );

    for event in events {
        if event.uid == uid_from_href {
            println!("✅ Found matching event by UID: {}", event.uid);
            return Ok(Some(event));
        }
    }

    println!("❌ No matching event found for href: {}", event_href);

    Ok(None)
}

pub async fn delete_event(
    State(state): State<Arc<AppState>>,
    headers: HeaderMap,
    Json(request): Json<DeleteEventRequest>,
) -> Result<Json<DeleteEventResponse>, ApiError> {
    let token = extract_bearer_token(&headers)?;
    let password = extract_password_header(&headers)?;

    // Create CalDAV config from token and password
    let config = state
        .auth_service
        .caldav_config_from_token(&token, &password)?;
    let client = CalDAVClient::new(config);

    // Handle different delete actions for recurring events
    match request.delete_action.as_str() {
        "delete_this" => {
            if let Some(event) =
                fetch_event_by_href(&client, &request.calendar_path, &request.event_href)
                    .await
                    .map_err(|e| ApiError::Internal(format!("Failed to fetch event: {}", e)))?
            {
                // Check if this is a recurring event
                if event.rrule.is_some() && !event.rrule.as_ref().unwrap().is_empty() {
                    // Recurring event - add EXDATE for this occurrence
                    if let Some(occurrence_date) = &request.occurrence_date {
                        let exception_datetime = if let Ok(date) =
                            chrono::DateTime::parse_from_rfc3339(occurrence_date)
                        {
                            // RFC3339 format (with time and timezone) - convert to naive
                            date.naive_utc()
                        } else if let Ok(naive_date) =
                            chrono::NaiveDate::parse_from_str(occurrence_date, "%Y-%m-%d")
                        {
                            // Simple date format (YYYY-MM-DD)
                            naive_date.and_hms_opt(0, 0, 0).unwrap()
                        } else {
                            return Err(ApiError::BadRequest(format!("Invalid occurrence date format: {}. Expected RFC3339 or YYYY-MM-DD", occurrence_date)));
                        };

                        let mut updated_event = event;
                        updated_event.exdate.push(exception_datetime);

                        println!(
                            "🔄 Adding EXDATE {} to recurring event {}",
                            exception_datetime.format("%Y%m%dT%H%M%S"),
                            updated_event.uid
                        );

                        // Update the event with the new EXDATE
                        client
                            .update_event(
                                &request.calendar_path,
                                &updated_event,
                                &request.event_href,
                            )
                            .await
                            .map_err(|e| {
                                ApiError::Internal(format!(
                                    "Failed to update event with EXDATE: {}",
                                    e
                                ))
                            })?;

                        println!("✅ Successfully updated recurring event with EXDATE");

                        Ok(Json(DeleteEventResponse {
                            success: true,
                            message: "Single occurrence deleted successfully".to_string(),
                        }))
                    } else {
                        Err(ApiError::BadRequest("Occurrence date is required for single occurrence deletion of recurring events".to_string()))
                    }
                } else {
                    // Non-recurring event - delete the entire event
                    println!("🗑️ Deleting non-recurring event: {}", event.uid);

                    client
                        .delete_event(&request.calendar_path, &request.event_href)
                        .await
                        .map_err(|e| {
                            ApiError::Internal(format!("Failed to delete event: {}", e))
                        })?;

                    println!("✅ Successfully deleted non-recurring event");

                    Ok(Json(DeleteEventResponse {
                        success: true,
                        message: "Event deleted successfully".to_string(),
                    }))
                }
            } else {
                Err(ApiError::NotFound("Event not found".to_string()))
            }
        }
        "delete_following" => {
            // For "this and following" deletion, we need to:
            // 1. Fetch the recurring event
            // 2. Modify the RRULE to end before this occurrence
            // 3. Update the event

            if let Some(mut event) =
                fetch_event_by_href(&client, &request.calendar_path, &request.event_href)
                    .await
                    .map_err(|e| ApiError::Internal(format!("Failed to fetch event: {}", e)))?
            {
                if let Some(occurrence_date) = &request.occurrence_date {
                    let until_date = if let Ok(date) =
                        chrono::DateTime::parse_from_rfc3339(occurrence_date)
                    {
                        // RFC3339 format (with time and timezone)
                        date.with_timezone(&chrono::Utc)
                    } else if let Ok(naive_date) =
                        chrono::NaiveDate::parse_from_str(occurrence_date, "%Y-%m-%d")
                    {
                        // Simple date format (YYYY-MM-DD)
                        naive_date.and_hms_opt(0, 0, 0).unwrap().and_utc()
                    } else {
                        return Err(ApiError::BadRequest(format!(
                            "Invalid occurrence date format: {}. Expected RFC3339 or YYYY-MM-DD",
                            occurrence_date
                        )));
                    };

                    // Modify the RRULE to add an UNTIL clause
                    if let Some(rrule) = &event.rrule {
                        // Remove existing UNTIL if present and add new one
                        let parts: Vec<&str> = rrule
                            .split(';')
                            .filter(|part| {
                                !part.starts_with("UNTIL=") && !part.starts_with("COUNT=")
                            })
                            .collect();

                        let new_rrule = format!(
                            "{};UNTIL={}",
                            parts.join(";"),
                            until_date.format("%Y%m%dT%H%M%SZ")
                        );
                        event.rrule = Some(new_rrule);

                        // Update the event with the modified RRULE
                        client
                            .update_event(&request.calendar_path, &event, &request.event_href)
                            .await
                            .map_err(|e| {
                                ApiError::Internal(format!(
                                    "Failed to update event with modified RRULE: {}",
                                    e
                                ))
                            })?;

                        Ok(Json(DeleteEventResponse {
                            success: true,
                            message: "This and following occurrences deleted successfully"
                                .to_string(),
                        }))
                    } else {
                        // No RRULE, just delete the single event
                        client
                            .delete_event(&request.calendar_path, &request.event_href)
                            .await
                            .map_err(|e| {
                                ApiError::Internal(format!("Failed to delete event: {}", e))
                            })?;

                        Ok(Json(DeleteEventResponse {
                            success: true,
                            message: "Event deleted successfully".to_string(),
                        }))
                    }
                } else {
                    Err(ApiError::BadRequest(
                        "Occurrence date is required for following deletion".to_string(),
                    ))
                }
            } else {
                Err(ApiError::NotFound("Event not found".to_string()))
            }
        }
        "delete_series" | _ => {
            // Delete the entire event/series
            client
                .delete_event(&request.calendar_path, &request.event_href)
                .await
                .map_err(|e| ApiError::Internal(format!("Failed to delete event: {}", e)))?;

            Ok(Json(DeleteEventResponse {
                success: true,
                message: "Event deleted successfully".to_string(),
            }))
        }
    }
}

pub async fn create_event(
    State(state): State<Arc<AppState>>,
    headers: HeaderMap,
    Json(request): Json<CreateEventRequest>,
) -> Result<Json<CreateEventResponse>, ApiError> {
    println!(
        "📝 Create event request received: title='{}', all_day={}, calendar_path={:?}",
        request.title, request.all_day, request.calendar_path
    );

    // Extract and verify token
    let token = extract_bearer_token(&headers)?;
    let password = extract_password_header(&headers)?;

    // Validate request
    if request.title.trim().is_empty() {
        return Err(ApiError::BadRequest("Event title is required".to_string()));
    }

    if request.title.len() > 200 {
        return Err(ApiError::BadRequest(
            "Event title too long (max 200 characters)".to_string(),
        ));
    }

    // Create CalDAV config from token and password
    let config = state
        .auth_service
        .caldav_config_from_token(&token, &password)?;
    let client = CalDAVClient::new(config);

    // Determine which calendar to use
    let calendar_path = if let Some(path) = request.calendar_path {
        path
    } else {
        // Use the first available calendar
        let calendar_paths = client
            .discover_calendars()
            .await
            .map_err(|e| ApiError::Internal(format!("Failed to discover calendars: {}", e)))?;

        if calendar_paths.is_empty() {
            return Err(ApiError::BadRequest(
                "No calendars available for event creation".to_string(),
            ));
        }

        calendar_paths[0].clone()
    };

    // Parse dates and times as local times (no UTC conversion)
    let start_datetime =
        parse_event_datetime_local(&request.start_date, &request.start_time, request.all_day)
            .map_err(|e| ApiError::BadRequest(format!("Invalid start date/time: {}", e)))?;

    let end_datetime = parse_event_datetime_local(&request.end_date, &request.end_time, request.all_day)
        .map_err(|e| ApiError::BadRequest(format!("Invalid end date/time: {}", e)))?;

    // Note: Frontend already converts inclusive UI dates to exclusive dates for all-day events
    // No additional conversion needed here

    // Validate that end is after start (allow equal times for all-day events)
    if request.all_day {
        if end_datetime < start_datetime {
            return Err(ApiError::BadRequest(
                "End date must be on or after start date for all-day events".to_string(),
            ));
        }
    } else {
        if end_datetime <= start_datetime {
            return Err(ApiError::BadRequest(
                "End date/time must be after start date/time".to_string(),
            ));
        }
    }

    // Generate a unique UID for the event
    let uid = format!(
        "{}-{}",
        uuid::Uuid::new_v4(),
        chrono::Utc::now().timestamp()
    );

    // Parse status
    let status = match request.status.to_lowercase().as_str() {
        "tentative" => EventStatus::Tentative,
        "cancelled" => EventStatus::Cancelled,
        _ => EventStatus::Confirmed,
    };

    // Parse class
    let class = match request.class.to_lowercase().as_str() {
        "private" => EventClass::Private,
        "confidential" => EventClass::Confidential,
        _ => EventClass::Public,
    };

    // Parse attendees (comma-separated email list)
    let attendees: Vec<String> = if request.attendees.trim().is_empty() {
        Vec::new()
    } else {
        request
            .attendees
            .split(',')
            .map(|s| s.trim().to_string())
            .filter(|s| !s.is_empty())
            .collect()
    };

    // Parse categories (comma-separated list)
    let categories: Vec<String> = if request.categories.trim().is_empty() {
        Vec::new()
    } else {
        request
            .categories
            .split(',')
            .map(|s| s.trim().to_string())
            .filter(|s| !s.is_empty())
            .collect()
    };

    // Use VAlarms directly from request (no conversion needed)
    let alarms = request.alarms;

    // Check if recurrence is already a full RRULE or just a simple type
    let rrule = if request.recurrence.starts_with("FREQ=") {
        // Frontend sent a complete RRULE string, use it directly
        if request.recurrence.is_empty() {
            None
        } else {
            Some(request.recurrence.clone())
        }
    } else {
        // Legacy path: Parse recurrence with BYDAY support for weekly recurrence
        match request.recurrence.to_uppercase().as_str() {
            "DAILY" => Some("FREQ=DAILY".to_string()),
            "WEEKLY" => {
                // Handle weekly recurrence with optional BYDAY parameter
                let mut rrule = "FREQ=WEEKLY".to_string();

                // Check if specific days are selected (recurrence_days has 7 elements: [Sun, Mon, Tue, Wed, Thu, Fri, Sat])
                if request.recurrence_days.len() == 7 {
                    let selected_days: Vec<&str> = request
                        .recurrence_days
                        .iter()
                        .enumerate()
                        .filter_map(|(i, &selected)| {
                            if selected {
                                Some(match i {
                                    0 => "SU", // Sunday
                                    1 => "MO", // Monday
                                    2 => "TU", // Tuesday
                                    3 => "WE", // Wednesday
                                    4 => "TH", // Thursday
                                    5 => "FR", // Friday
                                    6 => "SA", // Saturday
                                    _ => return None,
                                })
                            } else {
                                None
                            }
                        })
                        .collect();

                    if !selected_days.is_empty() {
                        rrule = format!("{};BYDAY={}", rrule, selected_days.join(","));
                    }
                }

                Some(rrule)
            }
            "MONTHLY" => Some("FREQ=MONTHLY".to_string()),
            "YEARLY" => Some("FREQ=YEARLY".to_string()),
            _ => None,
        }
    };

    // Create the VEvent struct (RFC 5545 compliant) with local times
    let mut event = VEvent::new(uid, start_datetime);
    event.dtend = Some(end_datetime);
    
    // Set timezone information from client
    event.dtstart_tzid = Some(request.timezone.clone());
    event.dtend_tzid = Some(request.timezone.clone());
    event.summary = if request.title.trim().is_empty() {
        None
    } else {
        Some(request.title.clone())
    };
    event.description = if request.description.trim().is_empty() {
        None
    } else {
        Some(request.description)
    };
    event.location = if request.location.trim().is_empty() {
        None
    } else {
        Some(request.location)
    };
    event.status = Some(status);
    event.class = Some(class);
    event.priority = request.priority;
    event.organizer = if request.organizer.trim().is_empty() {
        None
    } else {
        Some(CalendarUser {
            cal_address: request.organizer,
            common_name: None,
            dir_entry_ref: None,
            sent_by: None,
            language: None,
        })
    };
    event.attendees = attendees
        .into_iter()
        .map(|email| Attendee {
            cal_address: email,
            common_name: None,
            role: None,
            part_stat: None,
            rsvp: None,
            cu_type: None,
            member: Vec::new(),
            delegated_to: Vec::new(),
            delegated_from: Vec::new(),
            sent_by: None,
            dir_entry_ref: None,
            language: None,
        })
        .collect();
    event.categories = categories;
    event.rrule = rrule;
    event.all_day = request.all_day;
    event.alarms = alarms;
    event.calendar_path = Some(calendar_path.clone());

    // Create the event on the CalDAV server
    let event_href = client
        .create_event(&calendar_path, &event)
        .await
        .map_err(|e| ApiError::Internal(format!("Failed to create event: {}", e)))?;

    println!(
        "✅ Event created successfully with UID: {} at href: {}",
        event.uid, event_href
    );

    Ok(Json(CreateEventResponse {
        success: true,
        message: "Event created successfully".to_string(),
        event_href: Some(event_href),
    }))
}

pub async fn update_event(
    State(state): State<Arc<AppState>>,
    headers: HeaderMap,
    Json(request): Json<UpdateEventRequest>,
) -> Result<Json<UpdateEventResponse>, ApiError> {
    // Handle update request

    // Extract and verify token
    let token = extract_bearer_token(&headers)?;
    let password = extract_password_header(&headers)?;

    // Validate request
    if request.uid.trim().is_empty() {
        return Err(ApiError::BadRequest("Event UID is required".to_string()));
    }

    if request.title.trim().is_empty() {
        return Err(ApiError::BadRequest("Event title is required".to_string()));
    }

    if request.title.len() > 200 {
        return Err(ApiError::BadRequest(
            "Event title too long (max 200 characters)".to_string(),
        ));
    }

    // Create CalDAV config from token and password
    let config = state
        .auth_service
        .caldav_config_from_token(&token, &password)?;
    let client = CalDAVClient::new(config);

    // Find the event across all calendars (or in the specified calendar)
    let calendar_paths = if let Some(path) = &request.calendar_path {
        vec![path.clone()]
    } else {
        client
            .discover_calendars()
            .await
            .map_err(|e| ApiError::Internal(format!("Failed to discover calendars: {}", e)))?
    };

    let mut found_event: Option<(CalendarEvent, String, String)> = None; // (event, calendar_path, event_href)

    for calendar_path in &calendar_paths {
        match client.fetch_events(calendar_path).await {
            Ok(events) => {
                for event in events {
                    if event.uid == request.uid {
                        // Use the actual href from the event, or generate one if missing
                        let event_href = event
                            .href
                            .clone()
                            .unwrap_or_else(|| format!("{}.ics", event.uid));
                        println!("🔍 Found event {} with href: {}", event.uid, event_href);
                        found_event = Some((event, calendar_path.clone(), event_href));
                        break;
                    }
                }
                if found_event.is_some() {
                    break;
                }
            }
            Err(e) => {
                eprintln!(
                    "Failed to fetch events from calendar {}: {}",
                    calendar_path, e
                );
                continue;
            }
        }
    }

    let (mut event, calendar_path, event_href) = found_event
        .ok_or_else(|| ApiError::NotFound(format!("Event with UID '{}' not found", request.uid)))?;

    // Parse dates and times as local times (no UTC conversion)
    println!("🕐 UPDATE: Received start_date: '{}', start_time: '{}', timezone: '{}'", 
             request.start_date, request.start_time, request.timezone);
    let start_datetime =
        parse_event_datetime_local(&request.start_date, &request.start_time, request.all_day)
            .map_err(|e| ApiError::BadRequest(format!("Invalid start date/time: {}", e)))?;

    let end_datetime = parse_event_datetime_local(&request.end_date, &request.end_time, request.all_day)
        .map_err(|e| ApiError::BadRequest(format!("Invalid end date/time: {}", e)))?;

    // Note: Frontend already converts inclusive UI dates to exclusive dates for all-day events
    // No additional conversion needed here

    // Validate that end is after start (allow equal times for all-day events)
    if request.all_day {
        if end_datetime < start_datetime {
            return Err(ApiError::BadRequest(
                "End date must be on or after start date for all-day events".to_string(),
            ));
        }
    } else {
        if end_datetime <= start_datetime {
            return Err(ApiError::BadRequest(
                "End date/time must be after start date/time".to_string(),
            ));
        }
    }

    // Update event properties with local times and timezone info
    event.dtstart = start_datetime;
    event.dtend = Some(end_datetime);
    event.dtstart_tzid = Some(request.timezone.clone());
    event.dtend_tzid = Some(request.timezone.clone());
    event.summary = if request.title.trim().is_empty() {
        None
    } else {
        Some(request.title)
    };
    event.description = if request.description.trim().is_empty() {
        None
    } else {
        Some(request.description)
    };
    event.location = if request.location.trim().is_empty() {
        None
    } else {
        Some(request.location)
    };
    event.all_day = request.all_day;

    // Parse and update status
    event.status = Some(match request.status.to_lowercase().as_str() {
        "tentative" => EventStatus::Tentative,
        "cancelled" => EventStatus::Cancelled,
        _ => EventStatus::Confirmed,
    });

    // Parse and update class
    event.class = Some(match request.class.to_lowercase().as_str() {
        "private" => EventClass::Private,
        "confidential" => EventClass::Confidential,
        _ => EventClass::Public,
    });

    event.priority = request.priority;

    // Process recurrence information to set RRULE
    println!("🔄 Processing recurrence: '{}'", request.recurrence);
    println!("🔄 Recurrence days: {:?}", request.recurrence_days);
    println!("🔄 Recurrence interval: {:?}", request.recurrence_interval);
    println!("🔄 Recurrence count: {:?}", request.recurrence_count);
    println!("🔄 Recurrence end date: {:?}", request.recurrence_end_date);
    
    let rrule = if request.recurrence.starts_with("FREQ=") {
        // Frontend sent a complete RRULE string, use it directly
        if request.recurrence.is_empty() {
            None
        } else {
            Some(request.recurrence.clone())
        }
    } else {
        // Parse recurrence type and build RRULE with all parameters
        let base_rrule = match request.recurrence.to_uppercase().as_str() {
            "DAILY" => Some("FREQ=DAILY".to_string()),
            "WEEKLY" => {
                // Handle weekly recurrence with optional BYDAY parameter
                let mut rrule = "FREQ=WEEKLY".to_string();

                // Check if specific days are selected (recurrence_days has 7 elements: [Sun, Mon, Tue, Wed, Thu, Fri, Sat])
                if request.recurrence_days.len() == 7 {
                    let selected_days: Vec<&str> = request
                        .recurrence_days
                        .iter()
                        .enumerate()
                        .filter_map(|(i, &selected)| {
                            if selected {
                                Some(match i {
                                    0 => "SU", // Sunday
                                    1 => "MO", // Monday
                                    2 => "TU", // Tuesday
                                    3 => "WE", // Wednesday
                                    4 => "TH", // Thursday
                                    5 => "FR", // Friday
                                    6 => "SA", // Saturday
                                    _ => return None,
                                })
                            } else {
                                None
                            }
                        })
                        .collect();

                    if !selected_days.is_empty() {
                        rrule = format!("{};BYDAY={}", rrule, selected_days.join(","));
                    }
                }

                Some(rrule)
            }
            "MONTHLY" => Some("FREQ=MONTHLY".to_string()),
            "YEARLY" => Some("FREQ=YEARLY".to_string()),
            "NONE" | "" => None, // Clear any existing recurrence
            _ => None,
        };

        // Add INTERVAL, COUNT, and UNTIL parameters if specified
        if let Some(mut rrule_string) = base_rrule {
            // Add INTERVAL parameter (every N days/weeks/months/years)
            if let Some(interval) = request.recurrence_interval {
                if interval > 1 {
                    rrule_string = format!("{};INTERVAL={}", rrule_string, interval);
                }
            }

            // Add COUNT or UNTIL parameter (but not both - COUNT takes precedence)
            if let Some(count) = request.recurrence_count {
                rrule_string = format!("{};COUNT={}", rrule_string, count);
            } else if let Some(end_date) = &request.recurrence_end_date {
                // Convert YYYY-MM-DD to YYYYMMDD format for UNTIL
                if let Ok(date) = chrono::NaiveDate::parse_from_str(end_date, "%Y-%m-%d") {
                    rrule_string = format!("{};UNTIL={}", rrule_string, date.format("%Y%m%d"));
                }
            }

            Some(rrule_string)
        } else {
            None
        }
    };

    event.rrule = rrule.clone();
    println!("🔄 Set event RRULE to: {:?}", rrule);
    
    if rrule.is_some() {
        println!("✨ Converting singleton event to recurring series with RRULE: {}", rrule.as_ref().unwrap());
    } else {
        println!("📝 Event remains non-recurring (no RRULE set)");
    }

    // Update the event on the CalDAV server
    println!(
        "📝 Updating event {} at calendar_path: {}, event_href: {}",
        event.uid, calendar_path, event_href
    );
    client
        .update_event(&calendar_path, &event, &event_href)
        .await
        .map_err(|e| ApiError::Internal(format!("Failed to update event: {}", e)))?;

    println!("✅ Successfully updated event {}", event.uid);

    Ok(Json(UpdateEventResponse {
        success: true,
        message: "Event updated successfully".to_string(),
    }))
}

fn parse_event_datetime_local(
    date_str: &str,
    time_str: &str,
    all_day: bool,
) -> Result<chrono::NaiveDateTime, String> {
    use chrono::{NaiveDate, NaiveDateTime, NaiveTime};

    // Parse the date
    let date = NaiveDate::parse_from_str(date_str, "%Y-%m-%d")
        .map_err(|_| format!("Invalid date format: {}. Expected YYYY-MM-DD", date_str))?;

    if all_day {
        // For all-day events, use start of day
        let datetime = date
            .and_hms_opt(0, 0, 0)
            .ok_or_else(|| "Failed to create start-of-day datetime".to_string())?;
        Ok(datetime)
    } else {
        // Parse the time
        let time = NaiveTime::parse_from_str(time_str, "%H:%M")
            .map_err(|_| format!("Invalid time format: {}. Expected HH:MM", time_str))?;

        // Combine date and time - now keeping as local time
        Ok(NaiveDateTime::new(date, time))
    }
}
