//! # Actor Workflow
//!
//! Interactive actor management for creating and managing actors (personas and systems).
//! Provides guided workflows for actor operations.

use anyhow::Result;
use inquire::{Select, Text};
use std::collections::HashMap;

use crate::cli::interactive::{
    field_helpers::FieldHelpers, prompts, runner::InteractiveRunner, ui::UI,
};

/// Actor workflow handler
pub struct ActorWorkflow;

impl ActorWorkflow {
    /// Interactive actor creation workflow
    ///
    /// Creates a minimal actor with auto-generated ID from name.
    /// The ID is automatically generated by slugifying the name (e.g., "End User" → "end-user").
    /// Users can choose the actor type (Persona, System, Database, etc.).
    pub fn create_actor() -> Result<()> {
        use crate::core::utils::slugify_for_id;

        UI::show_section_header("Create Actor", "👤")?;

        // Select actor type first
        let actor_type_options = vec![
            "Persona (Human user)",
            "System (Application component)",
            "Database",
            "External Service",
            "Custom",
        ];

        let actor_type_choice = Select::new("Actor type:", actor_type_options)
            .with_help_message("Choose the type of actor you're creating")
            .prompt()?;

        let actor_type = match actor_type_choice {
            "Persona (Human user)" => "Persona",
            "System (Application component)" => "System",
            "Database" => "Database",
            "External Service" => "ExternalService",
            "Custom" => "Custom",
            _ => "Persona",
        };

        let name = Text::new("Actor name:")
            .with_help_message("Display name (e.g., 'John Doe', 'Payment API', 'Database')")
            .prompt()?;

        let function = Text::new("Function/Role:")
            .with_help_message(
                "Role or function (e.g., 'System Administrator', 'Authentication Service', 'PostgreSQL')",
            )
            .prompt()?;

        // Auto-generate ID from name
        let id = slugify_for_id(&name);

        // Show the generated ID to the user
        println!("  Generated ID: {}", id);

        // Create the actor based on type
        let mut runner = InteractiveRunner::new();
        let result = if actor_type == "Persona" {
            runner.create_persona_interactive(id.clone(), name, function)?
        } else {
            // For system actors, ask for emoji (optional)
            let default_emoji = match actor_type {
                "Database" => "💾",
                "System" => "🖥️",
                "ExternalService" => "🌐",
                _ => "⚙️",
            };

            let emoji = Text::new("Emoji (optional):")
                .with_default(default_emoji)
                .with_help_message("Visual identifier for this actor")
                .prompt()?;

            runner.create_system_actor_interactive(
                id.clone(),
                name,
                actor_type.to_string(),
                Some(emoji),
            )?
        };

        UI::show_success(&result)?;

        // Ask if user wants to add custom fields
        let add_fields = Select::new(
            "Would you like to add custom fields now?",
            vec!["No", "Yes"],
        )
        .with_help_message("You can always add/edit fields later")
        .prompt()?;

        if add_fields == "Yes" {
            let actor = runner.get_actor_details(&id)?;
            Self::edit_actor_fields(&mut runner, &id, &actor)?;
            // edit_actor_fields already has a pause, so we're done
        } else {
            UI::pause_for_input()?;
        }

        Ok(())
    }

    /// List all actors
    pub fn list_actors() -> Result<()> {
        UI::show_section_header("Actors", "👥")?;

        let runner = InteractiveRunner::new();
        runner.list_actors()?;

        UI::pause_for_input()?;
        Ok(())
    }

    /// Show actor details
    pub fn show_actor() -> Result<()> {
        UI::show_section_header("Show Actor Details", "👁️")?;

        let mut runner = InteractiveRunner::new();

        // Get list of actors
        let actor_ids = runner.get_actor_ids()?;

        if actor_ids.is_empty() {
            UI::show_error("No actors found.")?;
            UI::pause_for_input()?;
            return Ok(());
        }

        // Let user select which actor to view
        let selected_id =
            match prompts::select_or_cancel("Select actor to view:", actor_ids, |id| id.clone())? {
                Some(id) => id,
                None => return Ok(()),
            };

        runner.show_actor(selected_id)?;

        UI::pause_for_input()?;
        Ok(())
    }

    /// Delete an actor
    pub fn delete_actor() -> Result<()> {
        UI::show_section_header("Delete Actor", "🗑️")?;

        let mut runner = InteractiveRunner::new();

        // Get list of actors
        let actor_ids = runner.get_actor_ids()?;

        if actor_ids.is_empty() {
            UI::show_error("No actors found.")?;
            UI::pause_for_input()?;
            return Ok(());
        }

        // Let user select which actor to delete
        let selected_id =
            match prompts::select_or_cancel("Select actor to delete:", actor_ids, |id| id.clone())?
            {
                Some(id) => id,
                None => return Ok(()),
            };

        // Confirm deletion
        if prompts::confirm_delete(&selected_id, "actor")? {
            runner.delete_actor(&selected_id)?;
            UI::show_success("Actor deleted successfully")?;
        }

        UI::pause_for_input()?;
        Ok(())
    }

    /// Edit an existing actor
    pub fn edit_actor() -> Result<()> {
        UI::show_section_header("Edit Actor", "✏️")?;

        let mut runner = InteractiveRunner::new();

        // Get list of all actors (personas and system actors)
        let actor_ids = runner.get_actor_ids()?;

        if actor_ids.is_empty() {
            UI::show_error("No actors found. Please create an actor first.")?;
            UI::pause_for_input()?;
            return Ok(());
        }

        // Let user select which actor to edit
        let selected_id =
            match prompts::select_or_cancel("Select actor to edit:", actor_ids, |id| id.clone())? {
                Some(id) => id,
                None => return Ok(()),
            };

        // Load actor details
        let actor = runner.get_actor_entity(&selected_id)?;

        // Show edit menu
        loop {
            UI::clear_screen()?;
            UI::show_section_header(&format!("Editing: {}", actor.name), "✏️")?;
            UI::show_info(&format!("ID: {} ({})", actor.id, actor.actor_type))?;

            // Build menu based on actor type
            let mut edit_options = vec!["Edit Name", "Edit Emoji"];

            // Only personas have custom fields
            if actor.actor_type == crate::core::ActorType::Persona {
                edit_options.push("Edit Custom Fields");
            }

            edit_options.push("Back to Menu");

            let choice = Select::new("What would you like to edit?", edit_options).prompt()?;

            match choice {
                "Edit Name" => Self::edit_actor_entity_name(&mut runner, &selected_id, &actor)?,
                "Edit Emoji" => Self::edit_actor_entity_emoji(&mut runner, &selected_id, &actor)?,
                "Edit Custom Fields" => {
                    // Only for personas - get persona details and edit fields
                    let persona = runner.get_actor_details(&selected_id)?;
                    Self::edit_actor_fields(&mut runner, &selected_id, &persona)?
                }
                "Back to Menu" => break,
                _ => {}
            }

            // Reload actor after edits
            let _actor = runner.get_actor_entity(&selected_id)?;
        }

        Ok(())
    }

    /// Edit actor entity name (works for all actor types)
    fn edit_actor_entity_name(
        runner: &mut InteractiveRunner,
        actor_id: &str,
        actor: &crate::core::ActorEntity,
    ) -> Result<()> {
        UI::show_section_header("Edit Actor Name", "📝")?;

        if let Some(new_name) = prompts::edit_field_with_change(
            "Name:",
            &actor.name,
            Some("Press Enter to keep current value"),
        )? {
            let result = runner.update_actor_entity_name(actor_id.to_string(), new_name)?;
            UI::show_success(&result)?;
        } else {
            UI::show_info("No changes made.")?;
        }

        UI::pause_for_input()?;
        Ok(())
    }

    /// Edit actor entity emoji (works for all actor types)
    fn edit_actor_entity_emoji(
        runner: &mut InteractiveRunner,
        actor_id: &str,
        actor: &crate::core::ActorEntity,
    ) -> Result<()> {
        UI::show_section_header("Edit Actor Emoji", "🎭")?;

        if let Some(new_emoji) = prompts::edit_field_with_change(
            "Emoji:",
            &actor.emoji,
            Some("Enter a single emoji character"),
        )? {
            let result = runner.update_actor_entity_emoji(actor_id.to_string(), new_emoji)?;
            UI::show_success(&result)?;
        } else {
            UI::show_info("No changes made.")?;
        }

        UI::pause_for_input()?;
        Ok(())
    }

    /// Edit actor custom fields
    fn edit_actor_fields(
        runner: &mut InteractiveRunner,
        actor_id: &str,
        _actor: &crate::core::Persona,
    ) -> Result<()> {
        UI::show_section_header("Edit Custom Fields", "🎯")?;

        // Get field configuration
        let field_config = runner.get_actor_field_config()?;

        if field_config.is_empty() {
            UI::show_info("No custom fields defined in project configuration.")?;
            UI::pause_for_input()?;
            return Ok(());
        }

        // Get current values
        let current_values = runner.get_actor_field_values(actor_id)?;

        // Prompt for each field
        let mut updated_fields = HashMap::new();

        UI::show_info("Edit fields (smart input based on field type):")?;

        for (field_name, field_def) in &field_config {
            let current_json = current_values.get(field_name);
            let help_msg = field_def
                .description
                .clone()
                .unwrap_or_else(|| format!("{} field", field_def.field_type));

            // Use FieldHelpers to handle different field types automatically
            if let Some(new_value) = FieldHelpers::edit_by_type(
                &field_def.field_type,
                field_name,
                current_json,
                &help_msg,
            )? {
                updated_fields.insert(field_name.clone(), new_value);
            }
        }

        if updated_fields.is_empty() {
            UI::show_info("No changes made.")?;
            return Ok(());
        }

        let result = runner.update_actor_fields(actor_id.to_string(), updated_fields)?;

        UI::show_success(&result)?;
        UI::pause_for_input()?;
        Ok(())
    }

    /// Interactive actor management menu
    pub fn manage_actors() -> Result<()> {
        UI::clear_screen()?;
        UI::show_section_header("Actor Management", "👤")?;

        loop {
            let options = vec![
                "Create New Actor",
                "Edit Actor",
                "List All Actors",
                "Show Actor Details",
                "Delete Actor",
                "Back to Main Menu",
            ];

            let choice = Select::new("What would you like to do?", options).prompt()?;

            match choice {
                "Create New Actor" => Self::create_actor()?,
                "Edit Actor" => Self::edit_actor()?,
                "List All Actors" => Self::list_actors()?,
                "Show Actor Details" => Self::show_actor()?,
                "Delete Actor" => Self::delete_actor()?,
                "Back to Main Menu" => break,
                _ => {}
            }
        }

        Ok(())
    }
}
