use db::database::AppDatabase;
use models::repos::repo;
use models::rooms::room_ai;
use models::rooms::room_message::{Column as RmCol, Entity as RoomMessage};
use sea_orm::{ColumnTrait, EntityTrait, QueryFilter, QueryOrder, QuerySelect};
use uuid::Uuid;

use super::patterns::mention_bracket_re;
use crate::error::RoomError;

pub async fn get_room_history(
    db: &AppDatabase,
    room_id: Uuid,
    limit: usize,
) -> Result<Vec<models::rooms::room_message::Model>, RoomError> {
    let messages = RoomMessage::find()
        .filter(RmCol::Room.eq(room_id))
        .order_by_desc(RmCol::Seq)
        .limit(limit as u64)
        .all(db)
        .await?;

    Ok(messages)
}

pub async fn get_user_names(
    db: &AppDatabase,
    user_ids: &[Uuid],
) -> std::collections::HashMap<Uuid, String> {
    use models::users::User;

    let mut names = std::collections::HashMap::new();
    if user_ids.is_empty() {
        return names;
    }

    let users = User::find()
        .filter(models::users::user::Column::Uid.is_in(user_ids.to_vec()))
        .all(db)
        .await
        .unwrap_or_default();

    for user in users {
        names.insert(user.uid, user.username);
    }

    names
}

pub async fn get_room_ai_config(
    db: &AppDatabase,
    room_id: Uuid,
) -> Result<Option<room_ai::Model>, RoomError> {
    let ai_config = room_ai::Entity::find()
        .filter(room_ai::Column::Room.eq(room_id))
        .one(db)
        .await?;

    Ok(ai_config)
}

pub async fn extract_mention_context(
    db: &AppDatabase,
    project_id: Uuid,
    content: &str,
) -> Vec<agent::chat::Mention> {
    let mut mentions: Vec<agent::chat::Mention> = Vec::new();
    let mut seen_repos: Vec<String> = Vec::new();

    for cap in mention_bracket_re().captures_iter(content) {
        if let (Some(type_m), Some(id_m)) = (cap.get(1), cap.get(2)) {
            if type_m.as_str() == "repo" {
                let repo_name = id_m.as_str().trim().to_string();
                if repo_name.is_empty() || seen_repos.contains(&repo_name) {
                    continue;
                }
                seen_repos.push(repo_name.clone());

                if let Ok(Some(repo_model)) = repo::Entity::find()
                    .filter(repo::Column::Project.eq(project_id))
                    .filter(repo::Column::RepoName.eq(&repo_name))
                    .one(db)
                    .await
                {
                    mentions.push(agent::chat::Mention::Repo(repo_model));
                }
            }
        }
    }

    mentions
}
