use crate::AppService;
use crate::error::AppError;
use chrono::Utc;
use models::workspaces::{WorkspaceRole, workspace};
use sea_orm::*;
use serde::{Deserialize, Serialize};
use session::Session;

#[derive(Debug, Clone, Serialize, Deserialize, utoipa::ToSchema)]
pub struct WorkspaceUpdateParams {
    pub name: Option<String>,
    pub description: Option<String>,
    pub avatar_url: Option<String>,
    pub billing_email: Option<String>,
}

impl AppService {
    pub async fn workspace_update(
        &self,
        ctx: &Session,
        workspace_slug: String,
        params: WorkspaceUpdateParams,
    ) -> Result<workspace::Model, AppError> {
        let user_uid = ctx.user().ok_or(AppError::Unauthorized)?;
        let ws = self
            .utils_find_workspace_by_slug(workspace_slug.clone())
            .await?;

        self.utils_check_workspace_permission(ws.id, user_uid, &[WorkspaceRole::Admin])
            .await?;

        let mut m: workspace::ActiveModel = ws.into();

        if let Some(name) = params.name {
            // Check name uniqueness
            if workspace::Entity::find()
                .filter(workspace::Column::Name.eq(&name))
                .filter(workspace::Column::DeletedAt.is_null())
                .filter(workspace::Column::Id.ne(m.id.clone().unwrap()))
                .one(&self.db)
                .await?
                .is_some()
            {
                return Err(AppError::WorkspaceNameAlreadyExists);
            }
            m.name = Set(name);
        }

        if let Some(description) = params.description {
            m.description = Set(Some(description));
        }
        if let Some(avatar_url) = params.avatar_url {
            m.avatar_url = Set(Some(avatar_url));
        }
        if let Some(billing_email) = params.billing_email {
            m.billing_email = Set(Some(billing_email));
        }

        m.updated_at = Set(Utc::now());
        m.update(&self.db).await.map_err(Into::into)
    }

    /// Soft-delete a workspace. Only owner can delete.
    pub async fn workspace_delete(
        &self,
        ctx: &Session,
        workspace_slug: String,
    ) -> Result<(), AppError> {
        let user_uid = ctx.user().ok_or(AppError::Unauthorized)?;
        let ws = self.utils_find_workspace_by_slug(workspace_slug).await?;

        self.utils_check_workspace_permission(ws.id, user_uid, &[WorkspaceRole::Owner])
            .await?;

        let mut m: workspace::ActiveModel = ws.into();
        m.deleted_at = Set(Some(Utc::now()));
        m.updated_at = Set(Utc::now());
        m.update(&self.db).await?;

        Ok(())
    }
}
