use std::sync::Arc;

use chrono::Utc;
use db::cache::AppCache;
use db::database::AppDatabase;
use models::rooms::room_ai;
use queue::MessageProducer;
use sea_orm::{sea_query::Expr, ColumnTrait, EntityTrait, ExprTrait, QueryFilter};
use uuid::Uuid;

use super::ai_common::create_and_publish_ai_message;
use crate::connection::RoomConnectionManager;
use agent::chat::{AiRequest, ChatService};

pub async fn process_message_ai_nonstreaming(
    chat_service: Arc<ChatService>,
    request: AiRequest,
    room_id: Uuid,
    project_id: Uuid,
    model_id: Uuid,
    lock_guard: crate::room_ai_queue::RoomAiLockGuard,
    db: AppDatabase,
    cache: AppCache,
    queue: MessageProducer,
    room_manager: Arc<RoomConnectionManager>,
) {
    let chat_service = chat_service.clone();

    tokio::spawn(async move {
        let _lock_guard = lock_guard;
        let model_display_name = request.model.name.clone();
        match chat_service.process(request).await {
            Ok(result) => {
                if let Err(e) = create_and_publish_ai_message(
                    &db,
                    &cache,
                    &queue,
                    &room_manager,
                    room_id,
                    project_id,
                    Uuid::now_v7(),
                    result.content,
                    model_id,
                    Some(model_display_name),
                )
                .await
                {
                    tracing::error!(error = %e, "Failed to create AI message");
                } else {
                    let now = Utc::now();
                    if let Err(e) = room_ai::Entity::update_many()
                        .col_expr(
                            room_ai::Column::CallCount,
                            Expr::col(room_ai::Column::CallCount).add(1),
                        )
                        .col_expr(room_ai::Column::LastCallAt, Expr::value(Some(now)))
                        .filter(room_ai::Column::Room.eq(room_id))
                        .filter(room_ai::Column::Model.eq(model_id))
                        .exec(&db)
                        .await
                    {
                        tracing::warn!(error = %e, "Failed to update room_ai call stats");
                    }

                    // Record billing (non-fatal)
                    let _ = super::billing::record_ai_usage(
                        &db,
                        project_id,
                        model_id,
                        result.input_tokens,
                        result.output_tokens,
                    )
                    .await;
                }
            }
            Err(e) => {
                tracing::error!(error = %e, "AI processing failed");
                let _ = create_and_publish_ai_message(
                    &db,
                    &cache,
                    &queue,
                    &room_manager,
                    room_id,
                    project_id,
                    Uuid::now_v7(),
                    format!("[AI error: {}]", e),
                    model_id,
                    Some(model_display_name),
                )
                .await;
            }
        }
    });
}
