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

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

#[derive(Debug, Clone, Serialize, Deserialize, utoipa::ToSchema)]
pub struct JoinAnswerResponse {
    pub question: String,
    pub answer: String,
    pub created_at: DateTime<Utc>,
}

#[derive(Debug, Clone, Serialize, Deserialize, utoipa::ToSchema)]
pub struct JoinAnswersListResponse {
    pub request_id: i64,
    pub project_uid: String,
    pub answers: Vec<JoinAnswerResponse>,
}

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

        // Verify the request exists and belongs to this project
        let join_request = project_member_join_request::Entity::find_by_id(request_id)
            .filter(project_member_join_request::Column::Project.eq(project.id))
            .one(&self.db)
            .await?
            .ok_or(AppError::NotFound("Join request not found".to_string()))?;

        let answers = project_member_join_answers::Entity::find()
            .filter(project_member_join_answers::Column::RequestId.eq(request_id))
            .order_by_asc(project_member_join_answers::Column::Id)
            .all(&self.db)
            .await?;

        let answer_responses = answers
            .into_iter()
            .map(|a| JoinAnswerResponse {
                question: a.question,
                answer: a.answer,
                created_at: a.created_at,
            })
            .collect();

        Ok(JoinAnswersListResponse {
            request_id: join_request.id,
            project_uid: project.id.to_string(),
            answers: answer_responses,
        })
    }

    pub async fn project_submit_join_answers(
        &self,
        project_name: String,
        request_id: i64,
        answers: Vec<AnswerRequest>,
        ctx: &Session,
    ) -> Result<(), AppError> {
        let user_uid = ctx.user().ok_or(AppError::Unauthorized)?;
        let project = self
            .utils_find_project_by_name(project_name.clone())
            .await?;

        // Verify the request exists, belongs to this project, and belongs to the user
        let join_request = project_member_join_request::Entity::find_by_id(request_id)
            .filter(project_member_join_request::Column::Project.eq(project.id))
            .filter(project_member_join_request::Column::User.eq(user_uid))
            .one(&self.db)
            .await?
            .ok_or(AppError::NotFound("Join request not found".to_string()))?;

        if join_request.status != "pending" {
            return Err(AppError::InternalServerError(
                "Cannot update answers for processed request".to_string(),
            ));
        }

        // Delete existing answers
        project_member_join_answers::Entity::delete_many()
            .filter(project_member_join_answers::Column::RequestId.eq(request_id))
            .exec(&self.db)
            .await?;

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

        // Insert new answers
        for answer in answers {
            let answer_model = project_member_join_answers::ActiveModel {
                id: Default::default(),
                project: Set(project.id),
                user: Set(user_uid),
                request_id: Set(request_id),
                question: Set(answer.question),
                answer: Set(answer.answer),
                created_at: Set(Utc::now()),
            };
            answer_model.insert(&txn).await?;
        }

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

        txn.commit().await?;

        Ok(())
    }
}
