use crate::AppService;
use crate::error::AppError;
use chrono::Utc;
use models::users::{user_activity_log, user_preferences};
use sea_orm::*;
use serde::{Deserialize, Serialize};
use session::Session;
use uuid::Uuid;

#[derive(Deserialize, Serialize, Clone, Debug, utoipa::ToSchema)]
pub struct PreferencesParams {
    pub language: Option<String>,
    pub theme: Option<String>,
    pub timezone: Option<String>,
    pub email_notifications: Option<bool>,
    pub in_app_notifications: Option<bool>,
}

#[derive(Deserialize, Serialize, Clone, Debug, utoipa::ToSchema)]
pub struct PreferencesResponse {
    pub language: String,
    pub theme: String,
    pub timezone: String,
    pub email_notifications: bool,
    pub in_app_notifications: bool,
    pub created_at: chrono::DateTime<Utc>,
    pub updated_at: chrono::DateTime<Utc>,
}

impl From<user_preferences::Model> for PreferencesResponse {
    fn from(prefs: user_preferences::Model) -> Self {
        PreferencesResponse {
            language: prefs.language,
            theme: prefs.theme,
            timezone: prefs.timezone,
            email_notifications: prefs.email_notifications,
            in_app_notifications: prefs.in_app_notifications,
            created_at: prefs.created_at,
            updated_at: prefs.updated_at,
        }
    }
}

impl AppService {
    pub async fn user_get_preferences(
        &self,
        context: &Session,
    ) -> Result<PreferencesResponse, AppError> {
        let user_uid = context.user().ok_or(AppError::Unauthorized)?;

        let prefs = user_preferences::Entity::find_by_id(user_uid)
            .one(&self.db)
            .await?;

        if let Some(prefs) = prefs {
            Ok(PreferencesResponse::from(prefs))
        } else {
            self.user_create_default_preferences(user_uid).await
        }
    }

    pub async fn user_update_preferences(
        &self,
        context: &Session,
        params: PreferencesParams,
    ) -> Result<PreferencesResponse, AppError> {
        let user_uid = context.user().ok_or(AppError::Unauthorized)?;

        let prefs = user_preferences::Entity::find_by_id(user_uid)
            .one(&self.db)
            .await?;

        let updated_prefs = if let Some(prefs) = prefs {
            let mut active_prefs: user_preferences::ActiveModel = prefs.into();

            if let Some(language) = params.language.clone() {
                active_prefs.language = Set(language);
            }
            if let Some(theme) = params.theme.clone() {
                active_prefs.theme = Set(theme);
            }
            if let Some(timezone) = params.timezone.clone() {
                active_prefs.timezone = Set(timezone);
            }
            if let Some(email_notifications) = params.email_notifications {
                active_prefs.email_notifications = Set(email_notifications);
            }
            if let Some(in_app_notifications) = params.in_app_notifications {
                active_prefs.in_app_notifications = Set(in_app_notifications);
            }
            active_prefs.updated_at = Set(Utc::now());

            active_prefs.update(&self.db).await?
        } else {
            let new_prefs = user_preferences::ActiveModel {
                user: Set(user_uid),
                language: Set(params.language.clone().unwrap_or_else(|| "en".to_string())),
                theme: Set(params.theme.clone().unwrap_or_else(|| "light".to_string())),
                timezone: Set(params.timezone.clone().unwrap_or_else(|| "UTC".to_string())),
                email_notifications: Set(params.email_notifications.unwrap_or(true)),
                in_app_notifications: Set(params.in_app_notifications.unwrap_or(true)),
                created_at: Set(Utc::now()),
                updated_at: Set(Utc::now()),
            };

            new_prefs.insert(&self.db).await?
        };

        let _ = user_activity_log::ActiveModel {
            user_uid: Set(Some(user_uid)),
            action: Set("preferences_update".to_string()),
            ip_address: Set(context.ip_address()),
            user_agent: Set(context.user_agent()),
            details: Set(serde_json::json!({
                "updated_fields": {
                    "language": params.language.is_some(),
                    "theme": params.theme.is_some(),
                    "timezone": params.timezone.is_some(),
                    "email_notifications": params.email_notifications.is_some(),
                    "in_app_notifications": params.in_app_notifications.is_some(),
                }
            })),
            created_at: Set(Utc::now()),
            ..Default::default()
        }
        .insert(&self.db)
        .await;

        Ok(PreferencesResponse::from(updated_prefs))
    }

    async fn user_create_default_preferences(
        &self,
        user_uid: Uuid,
    ) -> Result<PreferencesResponse, AppError> {
        let prefs = user_preferences::ActiveModel {
            user: Set(user_uid),
            language: Set("en".to_string()),
            theme: Set("light".to_string()),
            timezone: Set("UTC".to_string()),
            email_notifications: Set(true),
            in_app_notifications: Set(true),
            created_at: Set(Utc::now()),
            updated_at: Set(Utc::now()),
        };

        let created_prefs = prefs.insert(&self.db).await?;

        Ok(PreferencesResponse::from(created_prefs))
    }
}
