//! Hook Commands - clap-noun-verb v3.4.0 Migration
//!
//! This module implements hook commands using the v3.4.0 #[verb] pattern.

use clap_noun_verb_macros::verb;
use clap_noun_verb::Result;
use serde::Serialize;
use std::path::PathBuf;

use crate::runtime_helper::execute_async_verb;
use ggen_domain::hook::{
    CreateInput, execute_create,
    ListInput, execute_list, HookInfo as DomainHookInfo,
    RemoveInput, execute_remove,
    MonitorInput, execute_monitor,
};

// ============================================================================
// Output Types
// ============================================================================

#[derive(Serialize)]
struct CreateOutput {
    hook_id: String,
    status: String,
}

#[derive(Serialize)]
struct ListOutput {
    hooks: Vec<HookInfo>,
    total: usize,
}

#[derive(Serialize)]
struct HookInfo {
    id: String,
    trigger: String,
    action: String,
    created_at: String,
}

#[derive(Serialize)]
struct RemoveOutput {
    hook_id: String,
    status: String,
}

#[derive(Serialize)]
struct MonitorOutput {
    active_hooks: usize,
    watching: usize,
    hooks: Vec<HookInfo>,
}

// ============================================================================
// Verb Functions
// ============================================================================

/// Create a new hook
#[verb]
fn create(
    event: String,
    script: PathBuf,
    name: Option<String>,
) -> Result<CreateOutput> {
    let input = CreateInput {
        trigger: event,
        action: script.to_string_lossy().to_string(),
        name,
    };

    execute_async_verb(async move {
        let result = execute_create(input).await
            .map_err(|e| clap_noun_verb::NounVerbError::execution_error(e.to_string()))?;

        Ok(CreateOutput {
            hook_id: result.hook_id,
            status: format!("{:?}", result.status),
        })
    })
}

/// List all hooks
#[verb]
fn list(
    filter: Option<String>,
    verbose: bool,
) -> Result<ListOutput> {
    let input = ListInput {
        verbose,
        filter,
    };

    execute_async_verb(async move {
        let result = execute_list(input).await
            .map_err(|e| clap_noun_verb::NounVerbError::execution_error(e.to_string()))?;

        let hooks = result.into_iter().map(|h| HookInfo {
            id: h.id,
            trigger: h.trigger,
            action: h.action,
            created_at: h.created_at,
        }).collect::<Vec<_>>();

        let total = hooks.len();

        Ok(ListOutput { hooks, total })
    })
}

/// Remove a hook
#[verb]
fn remove(
    id: String,
    force: bool,
) -> Result<RemoveOutput> {
    let input = RemoveInput {
        hook_id: id.clone(),
        force,
    };

    execute_async_verb(async move {
        let result = execute_remove(input).await
            .map_err(|e| clap_noun_verb::NounVerbError::execution_error(e.to_string()))?;

        Ok(RemoveOutput {
            hook_id: result.hook_id,
            status: format!("{:?}", result.status),
        })
    })
}

/// Monitor hook events
#[verb]
fn monitor(
    graph: String,
    interval: u64,
    once: bool,
) -> Result<MonitorOutput> {
    let input = MonitorInput {
        graph,
        interval,
        once,
    };

    execute_async_verb(async move {
        let result = execute_monitor(input).await
            .map_err(|e| clap_noun_verb::NounVerbError::execution_error(e.to_string()))?;

        let hooks = result.hooks.into_iter().map(|h| HookInfo {
            id: h.id,
            trigger: h.trigger,
            action: h.action,
            created_at: h.created_at,
        }).collect();

        Ok(MonitorOutput {
            active_hooks: result.active_hooks,
            watching: result.watching,
            hooks,
        })
    })
}
