use std::path::PathBuf;

use anyhow::Result;
use clap::Subcommand;

use crate::client::VaporaClient;
use crate::output;

#[derive(Subcommand)]
pub enum Commands {
    /// Workflow orchestration commands
    #[command(subcommand)]
    Workflow(WorkflowCommands),
}

impl Commands {
    pub async fn execute(self, client: VaporaClient) -> Result<()> {
        match self {
            Commands::Workflow(cmd) => cmd.execute(client).await,
        }
    }
}

#[derive(Subcommand)]
pub enum WorkflowCommands {
    /// Start a new workflow from template
    Start {
        /// Workflow template name
        #[arg(short, long)]
        template: String,

        /// Initial context JSON file (optional)
        #[arg(short, long)]
        context: Option<PathBuf>,

        /// Enrich with Kogral knowledge (default: true)
        #[arg(long, default_value_t = true)]
        kogral: bool,
    },

    /// List active workflows
    List,

    /// Get workflow status
    Status {
        /// Workflow ID
        workflow_id: String,
    },

    /// Approve a stage waiting for approval
    Approve {
        /// Workflow ID
        workflow_id: String,

        /// Approver name
        #[arg(short, long)]
        approver: String,
    },

    /// Cancel a running workflow
    Cancel {
        /// Workflow ID
        workflow_id: String,

        /// Reason for cancellation
        #[arg(short, long)]
        reason: String,
    },

    /// List available workflow templates
    Templates,
}

impl WorkflowCommands {
    pub async fn execute(self, client: VaporaClient) -> Result<()> {
        match self {
            WorkflowCommands::Start {
                template,
                context,
                kogral,
            } => {
                let context_value = if let Some(path) = context {
                    let content = tokio::fs::read_to_string(path).await?;
                    serde_json::from_str(&content)?
                } else {
                    serde_json::json!({})
                };

                let mut ctx = context_value;

                if kogral {
                    if let Some(obj) = ctx.as_object_mut() {
                        obj.insert("enable_kogral".to_string(), serde_json::json!(true));
                    }
                }

                let workflow_id = client.start_workflow(template.clone(), ctx).await?;

                output::print_success(&format!(
                    "Workflow started: {} (ID: {})",
                    template, workflow_id
                ));

                Ok(())
            }
            WorkflowCommands::List => {
                let workflows = client.list_workflows().await?;

                output::print_workflows_table(&workflows);

                Ok(())
            }
            WorkflowCommands::Status { workflow_id } => {
                let workflow = client.get_workflow(&workflow_id).await?;

                output::print_workflow_details(&workflow);

                Ok(())
            }
            WorkflowCommands::Approve {
                workflow_id,
                approver,
            } => {
                let message = client.approve_stage(&workflow_id, approver).await?;

                output::print_success(&message);

                Ok(())
            }
            WorkflowCommands::Cancel {
                workflow_id,
                reason,
            } => {
                let message = client.cancel_workflow(&workflow_id, reason).await?;

                output::print_success(&message);

                Ok(())
            }
            WorkflowCommands::Templates => {
                let templates = client.list_templates().await?;

                output::print_templates(&templates);

                Ok(())
            }
        }
    }
}
