use crate::agent::AgentError;
use crate::bus::OutboundMessage;
use crate::scheduler::{
    AgentTaskExecutor as SchedulerAgentTaskExecutor, MaintenanceExecutor, MaintenanceRunSummary,
    ScheduledAgentTaskOptions,
};
use async_trait::async_trait;

use super::memory_maintenance::MemoryMaintenanceScopeResult;
use super::session::SessionManager;

#[derive(Clone)]
pub struct AgentTaskExecutor {
    session_manager: SessionManager,
}

impl AgentTaskExecutor {
    pub fn new(session_manager: SessionManager) -> Self {
        Self { session_manager }
    }

    async fn execute_agent_task(
        &self,
        channel_name: &str,
        chat_id: &str,
        prompt: &str,
        options: ScheduledAgentTaskOptions,
    ) -> Result<Vec<OutboundMessage>, AgentError> {
        self.session_manager
            .run_scheduled_agent_task(channel_name, chat_id, prompt, options)
            .await
    }

    async fn execute_silent_agent_task(
        &self,
        channel_name: &str,
        session_chat_id: &str,
        notification_chat_id: Option<&str>,
        prompt: &str,
        options: ScheduledAgentTaskOptions,
    ) -> Result<Vec<OutboundMessage>, AgentError> {
        self.session_manager
            .run_silent_agent_task(channel_name, session_chat_id, notification_chat_id, prompt, options)
            .await
    }
}

#[async_trait]
impl SchedulerAgentTaskExecutor for AgentTaskExecutor {
    async fn execute(
        &self,
        channel_name: &str,
        chat_id: &str,
        prompt: &str,
        options: ScheduledAgentTaskOptions,
    ) -> anyhow::Result<Vec<OutboundMessage>> {
        self.execute_agent_task(channel_name, chat_id, prompt, options)
            .await
            .map_err(|error| anyhow::anyhow!(error.to_string()))
    }

    async fn execute_silent(
        &self,
        channel_name: &str,
        session_chat_id: &str,
        notification_chat_id: Option<&str>,
        prompt: &str,
        options: ScheduledAgentTaskOptions,
    ) -> anyhow::Result<Vec<OutboundMessage>> {
        self.execute_silent_agent_task(
            channel_name,
            session_chat_id,
            notification_chat_id,
            prompt,
            options,
        )
        .await
        .map_err(|error| anyhow::anyhow!(error.to_string()))
    }
}

#[derive(Clone)]
pub struct SchedulerMaintenanceService {
    session_manager: SessionManager,
}

impl SchedulerMaintenanceService {
    pub fn new(session_manager: SessionManager) -> Self {
        Self { session_manager }
    }

    async fn cleanup_sessions(&self) -> usize {
        self.session_manager.cleanup_expired_sessions().await
    }

    async fn run_memory_maintenance(&self) -> Result<Option<MemoryMaintenanceScopeResult>, AgentError> {
        self.session_manager.run_memory_maintenance_for_all_scopes().await
    }
}

#[async_trait]
impl MaintenanceExecutor for SchedulerMaintenanceService {
    async fn cleanup_expired_sessions(&self) -> usize {
        self.cleanup_sessions().await
    }

    async fn run_memory_maintenance_for_all_scopes(&self) -> anyhow::Result<Vec<MaintenanceRunSummary>> {
        self.run_memory_maintenance()
            .await
            .map(|results| {
                results
                    .into_iter()
                    .map(|result| MaintenanceRunSummary {
                        scope_key: result.scope_key,
                        merges: result.output.merges.len(),
                        conflicts: result.output.conflicts.len(),
                        low_value: result.output.low_value_ids.len(),
                    })
                    .collect()
            })
            .map_err(|error| anyhow::anyhow!(error.to_string()))
    }
}
