use crate::{
    models::*,
    utils::{
        datetime::{DateTimeWithTimezone, convert_utc_to_est_for_v1}, 
        urls::UrlBuilder
    },
    error::Result,
};

/// Hacky workaround: normalize recurring types for frontend compatibility
/// Maps problematic recurring types to frontend-supported values
fn normalize_recurring_type_for_frontend(recurring_type: Option<String>) -> Option<String> {
    recurring_type.map(|rt| {
        match rt.as_str() {
            "2nd/3rd Saturday Monthly" => "monthly".to_string(),
            "WEEKLY" => "weekly".to_string(),
            "DAILY" => "daily".to_string(),
            "BIWEEKLY" => "biweekly".to_string(),
            other => other.to_lowercase()
        }
    })
}

/// Convert Event to EventV2 with timezone handling
pub fn convert_event_to_v2(
    event: Event,
    timezone: &str,
    url_builder: &UrlBuilder,
) -> Result<EventV2> {
    Ok(EventV2 {
        id: event.id,
        title: event.title,
        description: event.description,
        start_time: DateTimeWithTimezone::new(event.start_time, timezone)?,
        end_time: DateTimeWithTimezone::new(event.end_time, timezone)?,
        location: event.location,
        location_url: event.location_url,
        image: event.image.map(|img| url_builder.build_image_url(&img)),
        thumbnail: event.thumbnail.map(|thumb| url_builder.build_image_url(&thumb)),
        category: event.category,
        is_featured: event.is_featured,
        recurring_type: normalize_recurring_type_for_frontend(event.recurring_type),
        timezone: timezone.to_string(),
        approved_from: event.approved_from,
        created_at: event.created_at.map(|dt| DateTimeWithTimezone::new(dt, timezone)).transpose()?,
        updated_at: event.updated_at.map(|dt| DateTimeWithTimezone::new(dt, timezone)).transpose()?,
    })
}

/// Convert PendingEvent to PendingEventV2 with timezone handling
pub fn convert_pending_event_to_v2(
    event: PendingEvent,
    timezone: &str,
    url_builder: &UrlBuilder,
) -> Result<PendingEventV2> {
    Ok(PendingEventV2 {
        id: event.id,
        title: event.title,
        description: event.description,
        start_time: DateTimeWithTimezone::new(event.start_time, timezone)?,
        end_time: DateTimeWithTimezone::new(event.end_time, timezone)?,
        location: event.location,
        location_url: event.location_url,
        image: event.image.map(|img| url_builder.build_image_url(&img)),
        thumbnail: event.thumbnail.map(|thumb| url_builder.build_image_url(&thumb)),
        category: event.category,
        is_featured: event.is_featured,
        recurring_type: normalize_recurring_type_for_frontend(event.recurring_type),
        timezone: timezone.to_string(),
        approval_status: event.approval_status,
        submitted_at: event.submitted_at.map(|dt| DateTimeWithTimezone::new(dt, timezone)).transpose()?,
        bulletin_week: event.bulletin_week,
        admin_notes: event.admin_notes,
        submitter_email: event.submitter_email,
        email_sent: event.email_sent,
        pending_email_sent: event.pending_email_sent,
        rejection_email_sent: event.rejection_email_sent,
        approval_email_sent: event.approval_email_sent,
        created_at: event.created_at.map(|dt| DateTimeWithTimezone::new(dt, timezone)).transpose()?,
        updated_at: event.updated_at.map(|dt| DateTimeWithTimezone::new(dt, timezone)).transpose()?,
    })
}

/// Convert Bulletin to BulletinV2 with timezone handling
pub fn convert_bulletin_to_v2(
    bulletin: Bulletin,
    url_builder: &UrlBuilder,
) -> Result<BulletinV2> {
    Ok(BulletinV2 {
        id: bulletin.id,
        title: bulletin.title,
        date: bulletin.date,
        url: bulletin.url,
        cover_image: bulletin.cover_image.clone(),
        cover_image_url: bulletin.cover_image.map(|img| url_builder.build_image_url(&img)),
        pdf_url: bulletin.pdf_url,
        is_active: bulletin.is_active,
        pdf_file: bulletin.pdf_file,
        sabbath_school: bulletin.sabbath_school,
        divine_worship: bulletin.divine_worship,
        scripture_reading: bulletin.scripture_reading,
        sunset: bulletin.sunset,
        pdf_path: bulletin.pdf_path,
        created_at: bulletin.created_at.map(|dt| DateTimeWithTimezone::new(dt, "UTC")).transpose()?,
        updated_at: bulletin.updated_at.map(|dt| DateTimeWithTimezone::new(dt, "UTC")).transpose()?,
    })
}

/// Convert Schedule to ScheduleV2 with timezone handling
pub fn convert_schedule_to_v2(schedule: Schedule) -> Result<ScheduleV2> {
    Ok(ScheduleV2 {
        id: schedule.id,
        date: schedule.date,
        song_leader: schedule.song_leader,
        ss_teacher: schedule.ss_teacher,
        ss_leader: schedule.ss_leader,
        mission_story: schedule.mission_story,
        special_program: schedule.special_program,
        sermon_speaker: schedule.sermon_speaker,
        scripture: schedule.scripture,
        offering: schedule.offering,
        deacons: schedule.deacons,
        special_music: schedule.special_music,
        childrens_story: schedule.childrens_story,
        afternoon_program: schedule.afternoon_program,
        created_at: schedule.created_at.map(|dt| DateTimeWithTimezone::new(dt, "UTC")).transpose()?,
        updated_at: schedule.updated_at.map(|dt| DateTimeWithTimezone::new(dt, "UTC")).transpose()?,
    })
}

/// Convert BibleVerse to BibleVerseV2 with timezone handling
pub fn convert_bible_verse_to_v2(verse: BibleVerse) -> Result<BibleVerseV2> {
    Ok(BibleVerseV2 {
        id: verse.id,
        reference: verse.reference,
        text: verse.text,
        is_active: verse.is_active,
        created_at: verse.created_at.map(|dt| DateTimeWithTimezone::new(dt, "UTC")).transpose()?,
        updated_at: verse.updated_at.map(|dt| DateTimeWithTimezone::new(dt, "UTC")).transpose()?,
    })
}

/// Generic collection converter
pub fn convert_collection<T, U, F>(items: Vec<T>, converter: F) -> Result<Vec<U>>
where
    F: Fn(T) -> Result<U>,
{
    items.into_iter().map(converter).collect()
}

/// Batch convert events to V2 format
pub fn convert_events_to_v2(
    events: Vec<Event>,
    timezone: &str,
    url_builder: &UrlBuilder,
) -> Result<Vec<EventV2>> {
    convert_collection(events, |event| convert_event_to_v2(event, timezone, url_builder))
}

/// Batch convert pending events to V2 format
pub fn convert_pending_events_to_v2(
    events: Vec<PendingEvent>,
    timezone: &str,
    url_builder: &UrlBuilder,
) -> Result<Vec<PendingEventV2>> {
    convert_collection(events, |event| convert_pending_event_to_v2(event, timezone, url_builder))
}

/// Batch convert bulletins to V2 format
pub fn convert_bulletins_to_v2(
    bulletins: Vec<Bulletin>,
    url_builder: &UrlBuilder,
) -> Result<Vec<BulletinV2>> {
    convert_collection(bulletins, |bulletin| convert_bulletin_to_v2(bulletin, url_builder))
}

/// Batch convert schedules to V2 format
pub fn convert_schedules_to_v2(schedules: Vec<Schedule>) -> Result<Vec<ScheduleV2>> {
    convert_collection(schedules, convert_schedule_to_v2)
}

/// Batch convert bible verses to V2 format
pub fn convert_bible_verses_to_v2(verses: Vec<BibleVerse>) -> Result<Vec<BibleVerseV2>> {
    convert_collection(verses, convert_bible_verse_to_v2)
}

/// Helper trait for automatic conversion
pub trait ToV2<T> {
    fn to_v2(&self, timezone: &str, url_builder: &UrlBuilder) -> Result<T>;
}

impl ToV2<EventV2> for Event {
    fn to_v2(&self, timezone: &str, url_builder: &UrlBuilder) -> Result<EventV2> {
        convert_event_to_v2(self.clone(), timezone, url_builder)
    }
}

impl ToV2<PendingEventV2> for PendingEvent {
    fn to_v2(&self, timezone: &str, url_builder: &UrlBuilder) -> Result<PendingEventV2> {
        convert_pending_event_to_v2(self.clone(), timezone, url_builder)
    }
}

impl ToV2<BulletinV2> for Bulletin {
    fn to_v2(&self, _timezone: &str, url_builder: &UrlBuilder) -> Result<BulletinV2> {
        convert_bulletin_to_v2(self.clone(), url_builder)
    }
}

impl ToV2<ScheduleV2> for Schedule {
    fn to_v2(&self, _timezone: &str, _url_builder: &UrlBuilder) -> Result<ScheduleV2> {
        convert_schedule_to_v2(self.clone())
    }
}

impl ToV2<BibleVerseV2> for BibleVerse {
    fn to_v2(&self, _timezone: &str, _url_builder: &UrlBuilder) -> Result<BibleVerseV2> {
        convert_bible_verse_to_v2(self.clone())
    }
}

// ============================================================================
// V1 Conversion Functions for Backward Compatibility
// ============================================================================

/// Convert Event UTC times to EST for V1 endpoint backward compatibility
/// 
/// V1 clients expect EST times (even though they were labeled as UTC before).
/// This function converts UTC times from the database to EST times while
/// preserving the DateTime<Utc> type for V1 compatibility.
pub fn convert_event_to_v1(event: Event, url_builder: &UrlBuilder) -> Result<Event> {
    Ok(Event {
        id: event.id,
        title: event.title,
        description: event.description,
        start_time: convert_utc_to_est_for_v1(&event.start_time)?,
        end_time: convert_utc_to_est_for_v1(&event.end_time)?,
        location: event.location,
        location_url: event.location_url,
        image: event.image.map(|img| url_builder.build_image_url(&img)),
        thumbnail: event.thumbnail.map(|thumb| url_builder.build_image_url(&thumb)),
        category: event.category,
        is_featured: event.is_featured,
        recurring_type: normalize_recurring_type_for_frontend(event.recurring_type),
        approved_from: event.approved_from,
        created_at: event.created_at.map(|dt| convert_utc_to_est_for_v1(&dt)).transpose()?,
        updated_at: event.updated_at.map(|dt| convert_utc_to_est_for_v1(&dt)).transpose()?,
    })
}

/// Convert PendingEvent UTC times to EST for V1 endpoint backward compatibility
pub fn convert_pending_event_to_v1(event: PendingEvent, url_builder: &UrlBuilder) -> Result<PendingEvent> {
    Ok(PendingEvent {
        id: event.id,
        title: event.title,
        description: event.description,
        start_time: convert_utc_to_est_for_v1(&event.start_time)?,
        end_time: convert_utc_to_est_for_v1(&event.end_time)?,
        location: event.location,
        location_url: event.location_url,
        image: event.image.map(|img| url_builder.build_image_url(&img)),
        thumbnail: event.thumbnail.map(|thumb| url_builder.build_image_url(&thumb)),
        category: event.category,
        is_featured: event.is_featured,
        recurring_type: normalize_recurring_type_for_frontend(event.recurring_type),
        approval_status: event.approval_status,
        submitted_at: event.submitted_at.map(|dt| convert_utc_to_est_for_v1(&dt)).transpose()?,
        bulletin_week: event.bulletin_week,
        admin_notes: event.admin_notes,
        submitter_email: event.submitter_email,
        email_sent: event.email_sent,
        pending_email_sent: event.pending_email_sent,
        rejection_email_sent: event.rejection_email_sent,
        approval_email_sent: event.approval_email_sent,
        created_at: event.created_at.map(|dt| convert_utc_to_est_for_v1(&dt)).transpose()?,
        updated_at: event.updated_at.map(|dt| convert_utc_to_est_for_v1(&dt)).transpose()?,
    })
}

/// Convert Bulletin UTC times to EST for V1 endpoint backward compatibility
pub fn convert_bulletin_to_v1(bulletin: Bulletin, url_builder: &UrlBuilder) -> Result<Bulletin> {
    Ok(Bulletin {
        id: bulletin.id,
        title: bulletin.title,
        date: bulletin.date,
        url: bulletin.url,
        pdf_url: bulletin.pdf_url,
        is_active: bulletin.is_active,
        pdf_file: bulletin.pdf_file,
        sabbath_school: bulletin.sabbath_school,
        divine_worship: bulletin.divine_worship,
        scripture_reading: bulletin.scripture_reading,
        sunset: bulletin.sunset,
        cover_image: bulletin.cover_image.map(|img| url_builder.build_image_url(&img)),
        pdf_path: bulletin.pdf_path,
        created_at: bulletin.created_at.map(|dt| convert_utc_to_est_for_v1(&dt)).transpose()?,
        updated_at: bulletin.updated_at.map(|dt| convert_utc_to_est_for_v1(&dt)).transpose()?,
    })
}

/// Convert Schedule UTC times to EST for V1 endpoint backward compatibility
pub fn convert_schedule_to_v1(schedule: Schedule) -> Result<Schedule> {
    Ok(Schedule {
        id: schedule.id,
        date: schedule.date,
        song_leader: schedule.song_leader,
        ss_teacher: schedule.ss_teacher,
        ss_leader: schedule.ss_leader,
        mission_story: schedule.mission_story,
        special_program: schedule.special_program,
        sermon_speaker: schedule.sermon_speaker,
        scripture: schedule.scripture,
        offering: schedule.offering,
        deacons: schedule.deacons,
        special_music: schedule.special_music,
        childrens_story: schedule.childrens_story,
        afternoon_program: schedule.afternoon_program,
        created_at: schedule.created_at.map(|dt| convert_utc_to_est_for_v1(&dt)).transpose()?,
        updated_at: schedule.updated_at.map(|dt| convert_utc_to_est_for_v1(&dt)).transpose()?,
    })
}

/// Convert BibleVerse UTC times to EST for V1 endpoint backward compatibility  
pub fn convert_bible_verse_to_v1(verse: BibleVerse) -> Result<BibleVerse> {
    Ok(BibleVerse {
        id: verse.id,
        reference: verse.reference,
        text: verse.text,
        is_active: verse.is_active,
        created_at: verse.created_at.map(|dt| convert_utc_to_est_for_v1(&dt)).transpose()?,
        updated_at: verse.updated_at.map(|dt| convert_utc_to_est_for_v1(&dt)).transpose()?,
    })
}

/// Convert User UTC times to EST for V1 endpoint backward compatibility
pub fn convert_user_to_v1(user: User) -> Result<User> {
    Ok(User {
        id: user.id,
        username: user.username,
        email: user.email,
        name: user.name,
        avatar_url: user.avatar_url,
        role: user.role,
        verified: user.verified,
        created_at: user.created_at.map(|dt| convert_utc_to_est_for_v1(&dt)).transpose()?,
        updated_at: user.updated_at.map(|dt| convert_utc_to_est_for_v1(&dt)).transpose()?,
    })
}

/// Convert ChurchConfig UTC times to EST for V1 endpoint backward compatibility
pub fn convert_church_config_to_v1(config: ChurchConfig) -> Result<ChurchConfig> {
    Ok(ChurchConfig {
        id: config.id,
        church_name: config.church_name,
        contact_email: config.contact_email,
        contact_phone: config.contact_phone,
        church_address: config.church_address,
        po_box: config.po_box,
        google_maps_url: config.google_maps_url,
        about_text: config.about_text,
        api_keys: config.api_keys,
        jellyfin_server_url: config.jellyfin_server_url,
        brand_color: config.brand_color,
        created_at: config.created_at.map(|dt| convert_utc_to_est_for_v1(&dt)).transpose()?,
        updated_at: config.updated_at.map(|dt| convert_utc_to_est_for_v1(&dt)).transpose()?,
    })
}

// ============================================================================
// V1 Batch Conversion Functions
// ============================================================================

/// Batch convert events to V1 format with EST times
pub fn convert_events_to_v1(
    events: Vec<Event>,
    url_builder: &UrlBuilder,
) -> Result<Vec<Event>> {
    convert_collection(events, |event| convert_event_to_v1(event, url_builder))
}

/// Batch convert pending events to V1 format with EST times
pub fn convert_pending_events_to_v1(
    events: Vec<PendingEvent>,
    url_builder: &UrlBuilder,
) -> Result<Vec<PendingEvent>> {
    convert_collection(events, |event| convert_pending_event_to_v1(event, url_builder))
}

/// Batch convert bulletins to V1 format with EST times
pub fn convert_bulletins_to_v1(
    bulletins: Vec<Bulletin>,
    url_builder: &UrlBuilder,
) -> Result<Vec<Bulletin>> {
    convert_collection(bulletins, |bulletin| convert_bulletin_to_v1(bulletin, url_builder))
}

/// Batch convert schedules to V1 format with EST times
pub fn convert_schedules_to_v1(schedules: Vec<Schedule>) -> Result<Vec<Schedule>> {
    convert_collection(schedules, convert_schedule_to_v1)
}

/// Batch convert bible verses to V1 format with EST times
pub fn convert_bible_verses_to_v1(verses: Vec<BibleVerse>) -> Result<Vec<BibleVerse>> {
    convert_collection(verses, convert_bible_verse_to_v1)
}

/// Batch convert users to V1 format with EST times
pub fn convert_users_to_v1(users: Vec<User>) -> Result<Vec<User>> {
    convert_collection(users, convert_user_to_v1)
}

// ============================================================================
// V1 Helper Trait for Automatic Conversion
// ============================================================================

/// Helper trait for automatic V1 conversion with timezone handling
pub trait ToV1<T> {
    fn to_v1(&self, url_builder: &UrlBuilder) -> Result<T>;
}

impl ToV1<Event> for Event {
    fn to_v1(&self, url_builder: &UrlBuilder) -> Result<Event> {
        convert_event_to_v1(self.clone(), url_builder)
    }
}

impl ToV1<PendingEvent> for PendingEvent {
    fn to_v1(&self, url_builder: &UrlBuilder) -> Result<PendingEvent> {
        convert_pending_event_to_v1(self.clone(), url_builder)
    }
}

impl ToV1<Bulletin> for Bulletin {
    fn to_v1(&self, url_builder: &UrlBuilder) -> Result<Bulletin> {
        convert_bulletin_to_v1(self.clone(), url_builder)
    }
}

impl ToV1<Schedule> for Schedule {
    fn to_v1(&self, _url_builder: &UrlBuilder) -> Result<Schedule> {
        convert_schedule_to_v1(self.clone())
    }
}

impl ToV1<BibleVerse> for BibleVerse {
    fn to_v1(&self, _url_builder: &UrlBuilder) -> Result<BibleVerse> {
        convert_bible_verse_to_v1(self.clone())
    }
}

impl ToV1<User> for User {
    fn to_v1(&self, _url_builder: &UrlBuilder) -> Result<User> {
        convert_user_to_v1(self.clone())
    }
}

impl ToV1<ChurchConfig> for ChurchConfig {
    fn to_v1(&self, _url_builder: &UrlBuilder) -> Result<ChurchConfig> {
        convert_church_config_to_v1(self.clone())
    }
}