use async_graphql::{InputObject, SimpleObject};
use chrono::{DateTime, Utc};

use crate::services::google_calendar::{
    Attendee, CalendarEvent, CreateEventRequest, EventDateTime, EventReminder, EventReminders,
    UpdateEventRequest,
};

/// Date/time for a calendar event
#[derive(SimpleObject)]
pub struct EventDateTimeType {
    /// For timed events (RFC3339 format)
    pub date_time: Option<DateTime<Utc>>,
    /// For all-day events (YYYY-MM-DD format)
    pub date: Option<String>,
    /// Timezone (e.g., "America/New_York")
    pub time_zone: Option<String>,
}

impl From<EventDateTime> for EventDateTimeType {
    fn from(dt: EventDateTime) -> Self {
        Self {
            date_time: dt.date_time,
            date: dt.date,
            time_zone: dt.time_zone,
        }
    }
}

/// Input for event date/time
#[derive(InputObject)]
pub struct EventDateTimeInput {
    /// For timed events (RFC3339 format)
    pub date_time: Option<DateTime<Utc>>,
    /// For all-day events (YYYY-MM-DD format)
    pub date: Option<String>,
    /// Timezone (e.g., "America/New_York")
    pub time_zone: Option<String>,
}

impl From<EventDateTimeInput> for EventDateTime {
    fn from(input: EventDateTimeInput) -> Self {
        Self {
            date_time: input.date_time,
            date: input.date,
            time_zone: input.time_zone,
        }
    }
}

/// Calendar event attendee
#[derive(SimpleObject)]
pub struct AttendeeType {
    pub email: String,
    pub display_name: Option<String>,
    pub optional: Option<bool>,
    pub response_status: Option<String>,
}

impl From<Attendee> for AttendeeType {
    fn from(a: Attendee) -> Self {
        Self {
            email: a.email,
            display_name: a.display_name,
            optional: a.optional,
            response_status: a.response_status,
        }
    }
}

/// Input for attendee
#[derive(InputObject)]
pub struct AttendeeInput {
    pub email: String,
    pub display_name: Option<String>,
    pub optional: Option<bool>,
}

impl From<AttendeeInput> for Attendee {
    fn from(input: AttendeeInput) -> Self {
        Self {
            email: input.email,
            display_name: input.display_name,
            optional: input.optional,
            response_status: None,
        }
    }
}

/// Event reminder
#[derive(SimpleObject)]
pub struct EventReminderType {
    /// Method: "email" or "popup"
    pub method: String,
    /// Minutes before the event
    pub minutes: i32,
}

impl From<EventReminder> for EventReminderType {
    fn from(r: EventReminder) -> Self {
        Self {
            method: r.method,
            minutes: r.minutes,
        }
    }
}

/// Input for event reminder
#[derive(InputObject)]
pub struct EventReminderInput {
    /// Method: "email" or "popup"
    pub method: String,
    /// Minutes before the event
    pub minutes: i32,
}

impl From<EventReminderInput> for EventReminder {
    fn from(input: EventReminderInput) -> Self {
        Self {
            method: input.method,
            minutes: input.minutes,
        }
    }
}

/// Reminders settings for an event
#[derive(SimpleObject)]
pub struct EventRemindersType {
    pub use_default: bool,
    pub overrides: Option<Vec<EventReminderType>>,
}

impl From<EventReminders> for EventRemindersType {
    fn from(r: EventReminders) -> Self {
        Self {
            use_default: r.use_default,
            overrides: r.overrides.map(|v| v.into_iter().map(EventReminderType::from).collect()),
        }
    }
}

/// Input for reminders settings
#[derive(InputObject)]
pub struct EventRemindersInput {
    pub use_default: bool,
    pub overrides: Option<Vec<EventReminderInput>>,
}

impl From<EventRemindersInput> for EventReminders {
    fn from(input: EventRemindersInput) -> Self {
        Self {
            use_default: input.use_default,
            overrides: input.overrides.map(|v| v.into_iter().map(EventReminder::from).collect()),
        }
    }
}

/// Calendar event
#[derive(SimpleObject)]
pub struct CalendarEventType {
    pub id: String,
    pub summary: String,
    pub description: Option<String>,
    pub location: Option<String>,
    pub start: EventDateTimeType,
    pub end: EventDateTimeType,
    pub attendees: Option<Vec<AttendeeType>>,
    pub reminders: Option<EventRemindersType>,
    pub color_id: Option<String>,
    pub html_link: Option<String>,
    pub created: Option<DateTime<Utc>>,
    pub updated: Option<DateTime<Utc>>,
    pub status: Option<String>,
}

impl From<CalendarEvent> for CalendarEventType {
    fn from(e: CalendarEvent) -> Self {
        Self {
            id: e.id,
            summary: e.summary,
            description: e.description,
            location: e.location,
            start: EventDateTimeType::from(e.start),
            end: EventDateTimeType::from(e.end),
            attendees: e.attendees.map(|v| v.into_iter().map(AttendeeType::from).collect()),
            reminders: e.reminders.map(EventRemindersType::from),
            color_id: e.color_id,
            html_link: e.html_link,
            created: e.created,
            updated: e.updated,
            status: e.status,
        }
    }
}

/// Input for creating a calendar event
#[derive(InputObject)]
pub struct CreateCalendarEventInput {
    /// Custom event ID (optional, must be 5-1024 chars, a-v and 0-9 only)
    pub id: Option<String>,
    pub summary: String,
    pub description: Option<String>,
    pub location: Option<String>,
    pub start: EventDateTimeInput,
    pub end: EventDateTimeInput,
    pub attendees: Option<Vec<AttendeeInput>>,
    pub reminders: Option<EventRemindersInput>,
    pub color_id: Option<String>,
}

impl From<CreateCalendarEventInput> for CreateEventRequest {
    fn from(input: CreateCalendarEventInput) -> Self {
        Self {
            id: input.id,
            summary: input.summary,
            description: input.description,
            location: input.location,
            start: EventDateTime::from(input.start),
            end: EventDateTime::from(input.end),
            attendees: input.attendees.map(|v| v.into_iter().map(Attendee::from).collect()),
            reminders: input.reminders.map(EventReminders::from),
            color_id: input.color_id,
        }
    }
}

/// Input for updating a calendar event
#[derive(InputObject)]
pub struct UpdateCalendarEventInput {
    pub summary: Option<String>,
    pub description: Option<String>,
    pub location: Option<String>,
    pub start: Option<EventDateTimeInput>,
    pub end: Option<EventDateTimeInput>,
    pub attendees: Option<Vec<AttendeeInput>>,
    pub reminders: Option<EventRemindersInput>,
    pub color_id: Option<String>,
}

impl From<UpdateCalendarEventInput> for UpdateEventRequest {
    fn from(input: UpdateCalendarEventInput) -> Self {
        Self {
            summary: input.summary,
            description: input.description,
            location: input.location,
            start: input.start.map(EventDateTime::from),
            end: input.end.map(EventDateTime::from),
            attendees: input.attendees.map(|v| v.into_iter().map(Attendee::from).collect()),
            reminders: input.reminders.map(EventReminders::from),
            color_id: input.color_id,
        }
    }
}

/// Filter input for listing calendar events
#[derive(InputObject, Default)]
pub struct CalendarEventFilterInput {
    /// Filter events starting from this time
    pub time_min: Option<DateTime<Utc>>,
    /// Filter events ending before this time
    pub time_max: Option<DateTime<Utc>>,
    /// Maximum number of events to return
    pub max_results: Option<i32>,
    /// Search query
    pub q: Option<String>,
}
