use std::collections::HashMap;

use anyhow::Result;
use async_trait::async_trait;
use sea_orm::DatabaseConnection;

use robson_core::plugin::{MessageEvent, ProcessEventKind, Worker};

use crate::commands::execute_task_list;

pub struct TaskListWorker {
    workflow_db: DatabaseConnection,
}

impl TaskListWorker {
    pub const PATTERN: &'static str = r"(?i)(^<@\S+>\s*)?/task\s+list";

    pub fn new(workflow_db: DatabaseConnection) -> Self {
        Self { workflow_db }
    }
}

#[async_trait]
impl Worker for TaskListWorker {
    fn name(&self) -> &'static str {
        "TaskListWorker"
    }

    fn description(&self) -> &'static str {
        "Show all tasks with their current status, repo URL and PR URL."
    }

    fn example(&self) -> &'static str {
        "`/task list`"
    }

    async fn handle(
        &self,
        db: DatabaseConnection,
        msg: MessageEvent,
        _args: HashMap<String, String>,
    ) -> Result<bool> {
        let (kind, response) = match execute_task_list(&self.workflow_db).await {
            Ok(text) => (ProcessEventKind::Completed, text),
            Err(e) => (
                ProcessEventKind::Failed,
                format!(":x: Failed to list tasks: {:#}", e),
            ),
        };

        if let Some(conv_id) = msg.conversation_id {
            if let Err(e) = robson_core::entities::process_event::Model::insert(
                &db,
                conv_id,
                kind.as_str(),
                &response,
            )
            .await
            {
                tracing::warn!(error = %e, "failed to persist process event");
            }
        }

        Ok(true)
    }
}
