use crate::error::RoomError;
use crate::service::RoomService;
use crate::ws_context::WsUserContext;
use chrono::Utc;
use models::rooms::{room_message, room_thread};
use sea_orm::*;
use uuid::Uuid;

impl RoomService {
    pub async fn room_thread_list(
        &self,
        room_id: Uuid,
        ctx: &WsUserContext,
    ) -> Result<Vec<super::RoomThreadResponse>, RoomError> {
        let user_id = ctx.user_id;
        self.require_room_member(room_id, user_id).await?;

        let models = room_thread::Entity::find()
            .filter(room_thread::Column::Room.eq(room_id))
            .order_by_desc(room_thread::Column::LastMessageAt)
            .all(&self.db)
            .await?;

        Ok(models
            .into_iter()
            .map(super::RoomThreadResponse::from)
            .collect())
    }

    pub async fn room_thread_create(
        &self,
        room_id: Uuid,
        request: super::RoomThreadCreateRequest,
        ctx: &WsUserContext,
    ) -> Result<super::RoomThreadResponse, RoomError> {
        let user_id = ctx.user_id;
        self.require_room_member(room_id, user_id).await?;

        let parent = room_message::Entity::find()
            .filter(room_message::Column::Room.eq(room_id))
            .filter(room_message::Column::Seq.eq(request.parent_seq))
            .one(&self.db)
            .await?;
        if parent.is_none() {
            return Err(RoomError::NotFound("Parent message not found".to_string()));
        }

        let now = Utc::now();
        let participants = serde_json::json!([user_id]);
        let model = room_thread::ActiveModel {
            id: Set(Uuid::now_v7()),
            room: Set(room_id),
            parent: Set(request.parent_seq),
            created_by: Set(user_id),
            participants: Set(participants),
            last_message_at: Set(now),
            last_message_preview: Set(None),
            created_at: Set(now),
            updated_at: Set(now),
        }
        .insert(&self.db)
        .await?;

        Ok(super::RoomThreadResponse::from(model))
    }

    pub async fn room_thread_messages(
        &self,
        thread_id: Uuid,
        before_seq: Option<i64>,
        after_seq: Option<i64>,
        limit: Option<u64>,
        ctx: &WsUserContext,
    ) -> Result<super::RoomMessageListResponse, RoomError> {
        let user_id = ctx.user_id;
        let thread = room_thread::Entity::find_by_id(thread_id)
            .one(&self.db)
            .await?
            .ok_or_else(|| RoomError::NotFound("Thread not found".to_string()))?;
        self.require_room_member(thread.room, user_id).await?;

        let mut query =
            room_message::Entity::find().filter(room_message::Column::Thread.eq(Some(thread.id)));
        if let Some(before_seq) = before_seq {
            query = query.filter(room_message::Column::Seq.lt(before_seq));
        }
        if let Some(after_seq) = after_seq {
            query = query.filter(room_message::Column::Seq.gt(after_seq));
        }

        let total = query.clone().count(&self.db).await? as i64;
        let models = query
            .order_by_desc(room_message::Column::Seq)
            .limit(limit.unwrap_or(50))
            .all(&self.db)
            .await?;
        let mut messages: Vec<super::RoomMessageResponse> = models
            .into_iter()
            .map(super::RoomMessageResponse::from)
            .collect();
        messages.reverse();

        Ok(super::RoomMessageListResponse { messages, total })
    }
}
