use crate::command::context::CommandContext;
use crate::command::handler::{CommandHandler, CommandMetadata};
use crate::command::response::{CommandError, CommandResponse};
use crate::command::Command;
use crate::protocol::{SchedulerJobSessionLookup, SchedulerJobSummary};
use crate::storage::SessionStore;
use async_trait::async_trait;
use std::sync::Arc;

pub struct ListSchedulerJobsCommandHandler {
    store: Arc<SessionStore>,
}

impl ListSchedulerJobsCommandHandler {
    pub fn new(store: Arc<SessionStore>) -> Self {
        Self { store }
    }
}

#[async_trait]
impl CommandHandler for ListSchedulerJobsCommandHandler {
    fn can_handle(&self, cmd: &Command) -> bool {
        matches!(cmd, Command::ListSchedulerJobs)
    }

    fn metadata(&self) -> Option<CommandMetadata> {
        Some(CommandMetadata {
            name: "list_scheduler_jobs",
            description: "列出所有定时任务",
            usage: "/list_scheduler_jobs",
        })
    }

    async fn handle(
        &self,
        _cmd: Command,
        ctx: CommandContext,
    ) -> Result<CommandResponse, CommandError> {
        let records = self
            .store
            .list_scheduler_jobs(false)
            .map_err(|e| CommandError::new("LIST_JOBS_ERROR", e.to_string()))?;

        let summaries: Vec<SchedulerJobSummary> = records
            .into_iter()
            .map(|r| {
                let session_lookup = build_session_lookup(&r);

                SchedulerJobSummary {
                    id: r.id,
                    kind: r.kind,
                    schedule: r.schedule,
                    enabled: r.enabled,
                    state: r.state.as_str().to_string(),
                    last_status: r.last_status.map(|s| s.as_str().to_string()),
                    last_error: r.last_error,
                    run_count: r.run_count,
                    max_runs: r.max_runs,
                    last_fired_at: r.last_fired_at,
                    next_fire_at: r.next_fire_at,
                    created_at: r.created_at,
                    session_lookup,
                }
            })
            .collect();

        let jobs_json = serde_json::to_string(&summaries)
            .map_err(|e| CommandError::new("SERIALIZE_ERROR", e.to_string()))?;

        Ok(CommandResponse::success(ctx.request_id)
            .with_metadata("scheduler_jobs", &jobs_json))
    }
}

/// 从 job 的 target_json 推导 session_lookup。
/// 只有 agent_task / silent_agent_task 才有执行对话可查看。
fn build_session_lookup(
    r: &crate::storage::SchedulerJobRecord,
) -> Option<SchedulerJobSessionLookup> {
    let target: serde_json::Value = r.target.clone();

    match r.kind.as_str() {
        "agent_task" => {
            let channel = target.get("channel")?.as_str()?.to_string();
            let chat_id = target.get("chat_id")?.as_str()?.to_string();
            Some(SchedulerJobSessionLookup { channel, chat_id })
        }
        "silent_agent_task" => {
            let channel = target.get("channel")?.as_str()?.to_string();
            // silent_agent_task 使用虚拟 chat_id: scheduler/{job_id}
            let chat_id = format!("scheduler/{}", r.id);
            Some(SchedulerJobSessionLookup { channel, chat_id })
        }
        _ => None, // internal_event / outbound_message 无执行对话
    }
}
