use std::sync::Arc;

use tokio::sync::Mutex;

use crate::agent::AgentError;

use super::session::Session;
use super::session_factory::SessionFactory;
use super::session_pool::SessionPool;

#[derive(Clone)]
pub(crate) struct SessionLifecycleService {
    session_pool: SessionPool,
}

impl SessionLifecycleService {
    pub(crate) fn new(session_factory: SessionFactory, session_ttl_hours: Option<u64>) -> Self {
        Self {
            session_pool: SessionPool::new(session_factory, session_ttl_hours),
        }
    }

    pub(crate) async fn ensure_session(&self, channel_name: &str) -> Result<(), AgentError> {
        self.session_pool.ensure_session(channel_name).await
    }

    pub(crate) async fn get(&self, channel_name: &str) -> Option<Arc<Mutex<Session>>> {
        self.session_pool.get(channel_name).await
    }

    pub(crate) async fn touch(&self, channel_name: &str) {
        self.session_pool.touch(channel_name).await;
    }

    /// 获取活跃的主 Session（用于用户消息）
    pub(crate) async fn active_session(
        &self,
        channel_name: &str,
    ) -> Result<Arc<Mutex<Session>>, AgentError> {
        self.ensure_session(channel_name).await?;
        self.touch(channel_name).await;
        self.get(channel_name)
            .await
            .ok_or_else(|| AgentError::Other("Session not found".to_string()))
    }

    /// 根据 chat_id 自动选择并获取 Session
    /// - scheduler/ 开头：返回定时任务专用 Session
    /// - 其他：返回主 Session
    pub(crate) async fn active_session_for_chat_id(
        &self,
        channel_name: &str,
        chat_id: &str,
    ) -> Result<Arc<Mutex<Session>>, AgentError> {
        self.session_pool.ensure_session_for_chat_id(channel_name, chat_id).await?;
        self.touch(channel_name).await;
        self.session_pool.get_for_chat_id(channel_name, chat_id)
            .await
            .ok_or_else(|| AgentError::Other("Session not found".to_string()))
    }

    pub(crate) async fn cleanup_expired_sessions(&self) -> usize {
        self.session_pool.cleanup_expired_sessions().await
    }
}
