//! Phase management handler

use anyhow::{anyhow, Context, Result};
use colored::Colorize;
use std::path::Path;
use syntaxis_core::{PhaseExecutor, ProjectConfig, ProjectPhase};
use tools_shared::find_config_path_warn_conflicts;

/// Handler for phase operations
#[derive(Debug)]
pub struct PhaseHandler;

impl PhaseHandler {
    /// Show current phase
    pub fn show_current() -> Result<()> {
        // Load configuration from discovered path
        let config_path = Self::find_config()?;
        let config = ProjectConfig::load_from_file(&config_path)
            .context("Failed to load project configuration")?;

        println!("📍 Current Project Phase\n");

        let phase = config.phase;
        let phase_name = format!("{:?}", phase);

        println!("  Project: {}", config.project.name.bold());
        println!("  Phase: {}", phase_name.green().bold());
        println!("  Status: {}", "Active".green());
        println!(
            "  Config: {}",
            format!("{}", config_path.display()).dimmed()
        );

        println!("\n  Description:");
        Self::print_phase_description(&phase);

        Ok(())
    }

    /// Transition to a new phase
    pub fn transition_to(target_phase_str: &str, check_checklist: bool) -> Result<()> {
        let config_path = Self::find_config()?;
        let mut config = ProjectConfig::load_from_file(&config_path)
            .context("Failed to load project configuration")?;

        let current_phase = config.phase;
        let target_phase = parse_phase(target_phase_str)
            .ok_or_else(|| anyhow!("Invalid phase: {}", target_phase_str))?;

        println!(
            "🔄 Transitioning from {} to {}\n",
            format!("{:?}", current_phase).yellow(),
            format!("{:?}", target_phase).green().bold()
        );

        // Validate transition
        println!("  {} Validating transition...", "•".cyan());
        Self::validate_transition(&current_phase, &target_phase)?;
        println!("    ✓ Transition allowed");

        // Check checklist if required
        if check_checklist {
            println!("  {} Checking phase checklist...", "•".cyan());
            println!("    ⚠ Checklist validation (feature in progress)");
        }

        // Update configuration
        println!("  {} Updating configuration...", "•".cyan());
        config.phase = target_phase;
        config.project.last_updated = chrono::Utc::now();
        config
            .save_to_file(&config_path)
            .context("Failed to save configuration")?;
        println!("    ✓ Configuration updated");

        // Execute phase-specific actions
        println!("  {} Executing phase initialization actions...", "•".cyan());
        let project_root = config_path
            .parent()
            .and_then(|p| p.parent())
            .unwrap_or_else(|| Path::new("."));

        PhaseExecutor::execute_phase_actions(target_phase, &mut config, project_root)
            .context("Failed to execute phase actions")?;

        println!("\n✅ Phase transition completed!");
        println!(
            "  Current phase: {}",
            format!("{:?}", target_phase).green().bold()
        );
        println!("  Config saved: {}", config_path.display());

        Ok(())
    }

    // Helper: Find config file using tools-shared
    fn find_config() -> Result<std::path::PathBuf> {
        find_config_path_warn_conflicts("config.toml", None).ok_or_else(|| {
            anyhow!(
                "Configuration not found. Please create:\n\
                 - .project/lifecycle.toml, or\n\
                 - .vapora/lifecycle.toml"
            )
        })
    }

    // Helper: Validate phase transition
    pub fn validate_transition(from: &ProjectPhase, to: &ProjectPhase) -> Result<()> {
        use syntaxis_core::ProjectPhase::*;

        let allowed = matches!(
            (from, to),
            // Normal flow
            (Creation, Devel) |
            (Devel, Update) | (Devel, Review) |
            (Update, Devel) | (Update, Review) | (Update, Publish) |
            (Review, Devel) | (Review, Publish) | (Review, Status) |
            (Status, Devel) | (Status, Publish) | (Status, Archive) |
            (Publish, Status) | (Publish, Archive) |
            // Backwards compatibility
            (Prototype, Devel) | (Mvp, Devel)
        );

        if allowed {
            Ok(())
        } else {
            Err(anyhow!("Invalid transition: {:?} → {:?}", from, to))
        }
    }

    // Helper: Print phase description
    fn print_phase_description(phase: &ProjectPhase) {
        match phase {
            ProjectPhase::Creation => {
                println!("    Initialize project structure, set up repositories,");
                println!("    and establish initial configuration.");
            }
            ProjectPhase::Devel => {
                println!("    Implement features, write code, and conduct");
                println!("    regular code reviews.");
            }
            ProjectPhase::Update => {
                println!("    Implement enhancements, bug fixes, and");
                println!("    feature improvements.");
            }
            ProjectPhase::Review => {
                println!("    Conduct comprehensive code review, testing,");
                println!("    and quality assurance.");
            }
            ProjectPhase::Status => {
                println!("    Monitor project status and health metrics.");
            }
            ProjectPhase::Publish => {
                println!("    Prepare for release, update documentation,");
                println!("    and deploy to production.");
            }
            ProjectPhase::Archive => {
                println!("    Preserve project state for historical reference.");
            }
            ProjectPhase::Mvp => {
                println!("    Develop minimum viable product.");
            }
            ProjectPhase::Prototype => {
                println!("    Build prototype and validate concepts.");
            }
        }
    }
}

/// Parse phase string to Option<ProjectPhase>
fn parse_phase(s: &str) -> Option<ProjectPhase> {
    match s.to_lowercase().as_str() {
        "creation" | "create" => Some(ProjectPhase::Creation),
        "devel" | "development" => Some(ProjectPhase::Devel),
        "review" | "qa" => Some(ProjectPhase::Review),
        "publish" | "release" => Some(ProjectPhase::Publish),
        "status" | "health" => Some(ProjectPhase::Status),
        "update" | "upgrade" => Some(ProjectPhase::Update),
        "archive" | "archived" => Some(ProjectPhase::Archive),
        "mvp" | "minimum-viable" => Some(ProjectPhase::Mvp),
        "prototype" | "proto" => Some(ProjectPhase::Prototype),
        _ => None,
    }
}

#[cfg(test)]
mod tests {
    use super::*;

    #[test]
    fn test_phase_handler_creation() {
        let handler = PhaseHandler;
        assert_eq!(format!("{:?}", handler), "PhaseHandler");
    }

    #[test]
    fn test_parse_phase_creation() {
        let phase = parse_phase("creation");
        assert_eq!(phase, Some(ProjectPhase::Creation));
    }

    #[test]
    fn test_parse_phase_devel() {
        let phase = parse_phase("devel");
        assert_eq!(phase, Some(ProjectPhase::Devel));
    }

    #[test]
    fn test_parse_phase_development() {
        let phase = parse_phase("development");
        assert_eq!(phase, Some(ProjectPhase::Devel));
    }

    #[test]
    fn test_parse_phase_review() {
        let phase = parse_phase("review");
        assert_eq!(phase, Some(ProjectPhase::Review));
    }

    #[test]
    fn test_parse_phase_publish() {
        let phase = parse_phase("publish");
        assert_eq!(phase, Some(ProjectPhase::Publish));
    }

    #[test]
    fn test_parse_phase_status() {
        let phase = parse_phase("status");
        assert_eq!(phase, Some(ProjectPhase::Status));
    }

    #[test]
    fn test_parse_phase_update() {
        let phase = parse_phase("update");
        assert_eq!(phase, Some(ProjectPhase::Update));
    }

    #[test]
    fn test_parse_phase_archive() {
        let phase = parse_phase("archive");
        assert_eq!(phase, Some(ProjectPhase::Archive));
    }

    #[test]
    fn test_parse_phase_mvp() {
        let phase = parse_phase("mvp");
        assert_eq!(phase, Some(ProjectPhase::Mvp));
    }

    #[test]
    fn test_parse_phase_prototype() {
        let phase = parse_phase("prototype");
        assert_eq!(phase, Some(ProjectPhase::Prototype));
    }

    #[test]
    fn test_parse_phase_invalid() {
        let phase = parse_phase("invalid_phase");
        assert_eq!(phase, None);
    }

    #[test]
    fn test_validate_transition_valid_creation_to_devel() {
        let result =
            PhaseHandler::validate_transition(&ProjectPhase::Creation, &ProjectPhase::Devel);
        assert!(result.is_ok());
    }

    #[test]
    fn test_validate_transition_valid_devel_to_review() {
        let result = PhaseHandler::validate_transition(&ProjectPhase::Devel, &ProjectPhase::Review);
        assert!(result.is_ok());
    }

    #[test]
    fn test_validate_transition_valid_review_to_publish() {
        let result =
            PhaseHandler::validate_transition(&ProjectPhase::Review, &ProjectPhase::Publish);
        assert!(result.is_ok());
    }

    #[test]
    fn test_validate_transition_invalid() {
        let result =
            PhaseHandler::validate_transition(&ProjectPhase::Archive, &ProjectPhase::Devel);
        assert!(result.is_err());
    }
}
