use crate::AppService;
use crate::error::AppError;
use models::users::{user, user_activity_log};
use sea_orm::prelude::Expr;
use sea_orm::*;
use session::Session;
use std::io;

impl AppService {
    pub async fn user_avatar_upload(
        &self,
        context: Session,
        file: Vec<u8>,
        file_ext: &str,
    ) -> Result<String, AppError> {
        let user_id = context.user().ok_or(AppError::Unauthorized)?;
        let time = chrono::Utc::now().timestamp();
        let file_name = format!("{}-{}", user_id, time);
        self.avatar
            .upload(file, file_name.clone(), file_ext)
            .await
            .map_err(|e| {
                AppError::Io(io::Error::new(
                    io::ErrorKind::Other,
                    format!("Failed to upload avatar: {}", e),
                ))
            })?;
        let static_url = self
            .config
            .static_domain()
            .unwrap_or_else(|_| "/static".to_string());
        let file_url = format!(
            "{}/{}",
            static_url.trim_end_matches('/'),
            format!("{}.{}", file_name, file_ext)
        );
        user::Entity::update_many()
            .filter(user::Column::Uid.eq(user_id))
            .col_expr(user::Column::AvatarUrl, Expr::value(file_url.clone()))
            .exec(&self.db)
            .await?;

        let _ = user_activity_log::ActiveModel {
            user_uid: Set(Some(user_id)),
            action: Set("avatar_upload".to_string()),
            ip_address: Set(context.ip_address()),
            user_agent: Set(context.user_agent()),
            details: Set(serde_json::json!({
                "file_url": file_url
            })),
            created_at: Set(chrono::Utc::now()),
            ..Default::default()
        }
        .insert(&self.db)
        .await;

        Ok(file_url)
    }
}
