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

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

        let pins = room_pin::Entity::find()
            .filter(room_pin::Column::Room.eq(room_id))
            .order_by_desc(room_pin::Column::PinnedAt)
            .all(&self.db)
            .await?;

        Ok(pins.into_iter().map(super::RoomPinResponse::from).collect())
    }

    pub async fn room_pin_add(
        &self,
        message_id: Uuid,
        ctx: &WsUserContext,
    ) -> Result<super::RoomPinResponse, RoomError> {
        let user_id = ctx.user_id;
        let message = room_message::Entity::find_by_id(message_id)
            .one(&self.db)
            .await?
            .ok_or_else(|| RoomError::NotFound("Message not found".to_string()))?;
        self.require_room_admin(message.room, user_id).await?;

        if let Some(existing) = room_pin::Entity::find_by_id((message.room, message.id))
            .one(&self.db)
            .await?
        {
            return Ok(super::RoomPinResponse::from(existing));
        }

        let model = room_pin::ActiveModel {
            room: Set(message.room),
            message: Set(message.id),
            pinned_by: Set(user_id),
            pinned_at: Set(Utc::now()),
        }
        .insert(&self.db)
        .await?;

        let room = self.find_room_or_404(message.room).await?;
        self.publish_room_event(
            room.project,
            super::RoomEventType::MessagePinned,
            Some(message.room),
            None,
            Some(message.id),
            None,
        )
        .await;

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

    pub async fn room_pin_remove(
        &self,
        message_id: Uuid,
        ctx: &WsUserContext,
    ) -> Result<(), RoomError> {
        let user_id = ctx.user_id;
        let message = room_message::Entity::find_by_id(message_id)
            .one(&self.db)
            .await?
            .ok_or_else(|| RoomError::NotFound("Message not found".to_string()))?;
        self.require_room_admin(message.room, user_id).await?;

        room_pin::Entity::delete_by_id((message.room, message.id))
            .exec(&self.db)
            .await?;

        let room = self.find_room_or_404(message.room).await?;
        self.publish_room_event(
            room.project,
            super::RoomEventType::MessageUnpinned,
            Some(message.room),
            None,
            Some(message.id),
            None,
        )
        .await;

        Ok(())
    }
}
