//! Enhanced phase management with advanced features

use crate::error::Result;
use crate::phase::{PhaseManager, PhaseTransition, ProjectPhase};
use crate::LifecycleError;
use serde::{Deserialize, Serialize};
use std::collections::HashMap;

/// Phase prerequisites
#[derive(Debug, Clone, Serialize, Deserialize, Default)]
pub struct PhasePrerequisites {
    /// Required items to complete before transition
    pub required_items: Vec<String>,
    /// Minimum time in current phase (seconds)
    pub min_duration_secs: Option<u64>,
    /// Custom validation logic
    pub validation_fn: Option<String>,
}

/// Enhanced phase manager with prerequisites and metrics
#[derive(Debug, Clone)]
pub struct EnhancedPhaseManager {
    base_manager: PhaseManager,
    prerequisites: HashMap<ProjectPhase, PhasePrerequisites>,
    metrics: PhaseMetrics,
}

/// Phase transition metrics
#[derive(Debug, Clone, Serialize, Deserialize, Default)]
pub struct PhaseMetrics {
    /// Total transitions
    pub total_transitions: usize,
    /// Failed transition attempts
    pub failed_attempts: usize,
    /// Total time in project (seconds)
    pub total_time_secs: u64,
    /// Average time per phase (seconds)
    pub avg_phase_duration_secs: u64,
}

impl EnhancedPhaseManager {
    /// Create new enhanced phase manager
    pub fn new(initial_phase: ProjectPhase) -> Self {
        Self {
            base_manager: PhaseManager::new(initial_phase),
            prerequisites: HashMap::new(),
            metrics: PhaseMetrics::default(),
        }
    }

    /// Set prerequisites for phase
    pub fn set_prerequisites(&mut self, phase: ProjectPhase, prereqs: PhasePrerequisites) {
        self.prerequisites.insert(phase, prereqs);
    }

    /// Validate prerequisites before transition
    pub fn validate_prerequisites(&self, to: ProjectPhase) -> Result<()> {
        if let Some(prereqs) = self.prerequisites.get(&to) {
            // Check minimum duration in current phase
            if let Some(min_duration) = prereqs.min_duration_secs {
                if let Some(duration) = self.base_manager.time_in_current_phase() {
                    let secs = duration.as_secs();
                    if secs < min_duration {
                        return Err(LifecycleError::invalid_transition(
                            self.base_manager.current_phase().to_string(),
                            to.to_string(),
                            format!(
                                "Minimum duration of {} seconds not met (only {} seconds elapsed)",
                                min_duration, secs
                            ),
                        ));
                    }
                }
            }

            // Check required items (can be extended for checklist integration)
            if !prereqs.required_items.is_empty() {
                // This would integrate with checklist manager in real implementation
                tracing::info!("Checking required items: {:?}", prereqs.required_items);
            }
        }

        Ok(())
    }

    /// Transition with prerequisite validation
    pub fn transition_with_validation(
        &mut self,
        to: ProjectPhase,
        checklist_completed: bool,
    ) -> Result<()> {
        // Validate transition is allowed
        if !self.base_manager.can_transition(to) {
            self.metrics.failed_attempts += 1;
            return Err(LifecycleError::invalid_transition(
                self.base_manager.current_phase().to_string(),
                to.to_string(),
                "Transition not allowed",
            ));
        }

        // Validate prerequisites
        self.validate_prerequisites(to)?;

        // Perform transition
        self.base_manager.transition_to(to, checklist_completed)?;
        self.metrics.total_transitions += 1;

        Ok(())
    }

    /// Get current phase
    pub fn current_phase(&self) -> ProjectPhase {
        self.base_manager.current_phase()
    }

    /// Get metrics
    pub fn metrics(&self) -> &PhaseMetrics {
        &self.metrics
    }

    /// Get base manager
    pub fn base_manager(&self) -> &PhaseManager {
        &self.base_manager
    }

    /// Get phase history
    pub fn history(&self) -> Vec<&PhaseTransition> {
        self.base_manager.history()
    }
}

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

    #[test]
    fn test_enhanced_phase_manager_creation() {
        let manager = EnhancedPhaseManager::new(ProjectPhase::Creation);
        assert_eq!(manager.current_phase(), ProjectPhase::Creation);
        assert_eq!(manager.metrics.total_transitions, 0);
    }

    #[test]
    fn test_prerequisites_validation() {
        let mut manager = EnhancedPhaseManager::new(ProjectPhase::Creation);

        let prereqs = PhasePrerequisites {
            required_items: vec!["setup-ci".to_string(), "write-tests".to_string()],
            ..Default::default()
        };
        manager.set_prerequisites(ProjectPhase::Devel, prereqs);

        // Should pass validation (no items to check in this test)
        assert!(manager.validate_prerequisites(ProjectPhase::Devel).is_ok());
    }

    #[test]
    fn test_transition_with_validation() {
        let mut manager = EnhancedPhaseManager::new(ProjectPhase::Creation);

        assert!(manager
            .transition_with_validation(ProjectPhase::Devel, false)
            .is_ok());
        assert_eq!(manager.current_phase(), ProjectPhase::Devel);
        assert_eq!(manager.metrics.total_transitions, 1);
    }

    #[test]
    fn test_failed_transition_tracking() {
        let mut manager = EnhancedPhaseManager::new(ProjectPhase::Archive);

        // Archive is final state, should fail
        let result = manager.transition_with_validation(ProjectPhase::Devel, false);
        assert!(result.is_err());
        assert_eq!(manager.metrics.failed_attempts, 1);
    }
}
