use crate::AppService;
use crate::error::AppError;
use chrono::Utc;
use models::projects::{project_audit_log, project_member_join_settings};
use sea_orm::*;
use serde::{Deserialize, Serialize};
use session::Session;

#[derive(Debug, Clone, Serialize, Deserialize, utoipa::ToSchema)]
pub struct JoinSettingsResponse {
    pub project_uid: String,
    pub require_approval: bool,
    pub require_questions: bool,
    pub questions: serde_json::Value,
}

#[derive(Debug, Clone, Deserialize, Serialize, utoipa::ToSchema)]
pub struct UpdateJoinSettingsRequest {
    pub require_approval: bool,
    pub require_questions: bool,
    pub questions: Vec<QuestionSchema>,
}

#[derive(Debug, Clone, Deserialize, Serialize, utoipa::ToSchema)]
pub struct QuestionSchema {
    pub question: String,
}

impl AppService {
    pub async fn project_get_join_settings(
        &self,
        project_name: String,
        ctx: &Session,
    ) -> Result<JoinSettingsResponse, AppError> {
        let _user_uid = ctx.user().ok_or(AppError::Unauthorized)?;
        let project = self.utils_find_project_by_name(project_name).await?;

        let settings = project_member_join_settings::Entity::find()
            .filter(project_member_join_settings::Column::Project.eq(project.id))
            .one(&self.db)
            .await?;

        match settings {
            Some(s) => Ok(JoinSettingsResponse {
                project_uid: project.id.to_string(),
                require_approval: s.require_approval,
                require_questions: s.require_questions,
                questions: s.questions,
            }),
            None => Ok(JoinSettingsResponse {
                project_uid: project.id.to_string(),
                require_approval: false,
                require_questions: false,
                questions: serde_json::json!([]),
            }),
        }
    }

    pub async fn project_update_join_settings(
        &self,
        project_name: String,
        request: UpdateJoinSettingsRequest,
        ctx: &Session,
    ) -> Result<JoinSettingsResponse, AppError> {
        let user_uid = ctx.user().ok_or(AppError::Unauthorized)?;
        let project = self
            .utils_find_project_by_name(project_name.clone())
            .await?;

        let role = self
            .utils_project_context_role(&ctx, project_name.clone())
            .await
            .map_err(|_| AppError::NoPower)?;

        if role != models::projects::MemberRole::Owner
            && role != models::projects::MemberRole::Admin
        {
            return Err(AppError::NoPower);
        }

        let txn = self.db.begin().await?;

        let existing = project_member_join_settings::Entity::find()
            .filter(project_member_join_settings::Column::Project.eq(project.id))
            .one(&txn)
            .await?;

        let questions_json: serde_json::Value = serde_json::json!(
            request
                .questions
                .iter()
                .map(|q| q.question.clone())
                .collect::<Vec<_>>()
        );

        if let Some(settings) = existing {
            let mut active: project_member_join_settings::ActiveModel = settings.into();
            active.require_approval = Set(request.require_approval);
            active.require_questions = Set(request.require_questions);
            active.questions = Set(questions_json.clone());
            active.updated_at = Set(Utc::now());
            active.update(&txn).await?;
        } else {
            let new_settings = project_member_join_settings::ActiveModel {
                id: Default::default(),
                project: Set(project.id),
                require_approval: Set(request.require_approval),
                require_questions: Set(request.require_questions),
                questions: Set(questions_json.clone()),
                created_at: Set(Utc::now()),
                updated_at: Set(Utc::now()),
            };
            new_settings.insert(&txn).await?;
        }

        let log = project_audit_log::ActiveModel {
            project: Set(project.id),
            actor: Set(user_uid),
            action: Set("update_join_settings".to_string()),
            details: Set(Some(serde_json::json!({
                "require_approval": request.require_approval,
                "require_questions": request.require_questions,
                "questions_count": request.questions.len(),
            }))),
            created_at: Set(Utc::now()),
            ..Default::default()
        };
        log.insert(&txn).await?;

        txn.commit().await?;

        Ok(JoinSettingsResponse {
            project_uid: project.id.to_string(),
            require_approval: request.require_approval,
            require_questions: request.require_questions,
            questions: questions_json,
        })
    }
}
