//! Project context managing all lifecycle components

use crate::checklist::ChecklistManager;
use crate::config::ProjectConfig;
use crate::error::Result;
use crate::phase::PhaseManager;
use crate::tools::ToolManager;
use serde::{Deserialize, Serialize};
use std::path::PathBuf;

/// Complete syntaxis context
#[derive(Debug, Clone)]
pub struct ProjectContext {
    /// Project ID
    pub project_id: String,
    /// Project configuration
    pub config: ProjectConfig,
    /// Phase manager
    pub phase_manager: PhaseManager,
    /// Tool manager
    pub tool_manager: ToolManager,
    /// Checklist manager
    pub checklist_manager: ChecklistManager,
    /// Project root directory
    pub root_dir: PathBuf,
}

impl ProjectContext {
    /// Create new project context
    pub fn new(project_id: impl Into<String>, config: ProjectConfig, root_dir: PathBuf) -> Self {
        let phase_manager = PhaseManager::new(config.phase);
        let tool_manager = ToolManager::builtin();
        let checklist_manager = ChecklistManager::new();

        Self {
            project_id: project_id.into(),
            config,
            phase_manager,
            tool_manager,
            checklist_manager,
            root_dir,
        }
    }

    /// Get mutable phase manager
    pub fn phase_manager_mut(&mut self) -> &mut PhaseManager {
        &mut self.phase_manager
    }

    /// Get mutable tool manager
    pub fn tool_manager_mut(&mut self) -> &mut ToolManager {
        &mut self.tool_manager
    }

    /// Get mutable checklist manager
    pub fn checklist_manager_mut(&mut self) -> &mut ChecklistManager {
        &mut self.checklist_manager
    }

    /// Get active tools for current phase
    pub fn active_tools(&self) -> Vec<String> {
        self.tool_manager
            .get_active_tools(self.config.phase)
            .iter()
            .map(|t| t.name.clone())
            .collect()
    }

    /// Get lifecycle status summary
    pub fn status_summary(&self) -> String {
        let active_tools = self.active_tools();
        format!(
            "Project: {} | Phase: {} | Tools: {} | Transitions: {}",
            self.config.project.name,
            self.config.phase,
            active_tools.len(),
            self.phase_manager.transition_count()
        )
    }
}

/// Context persistence helper
#[derive(Debug, Serialize, Deserialize)]
pub struct ContextSnapshot {
    /// Project ID
    pub project_id: String,
    /// Configuration snapshot
    pub config: ProjectConfig,
    /// Phase transitions history
    pub phase_history: Vec<crate::phase::PhaseTransition>,
}

impl ContextSnapshot {
    /// Create snapshot from context
    pub fn from_context(ctx: &ProjectContext) -> Self {
        Self {
            project_id: ctx.project_id.clone(),
            config: ctx.config.clone(),
            phase_history: ctx
                .phase_manager
                .history()
                .iter()
                .map(|p| (*p).clone())
                .collect(),
        }
    }

    /// Restore context from snapshot
    pub fn to_context(&self, root_dir: PathBuf) -> Result<ProjectContext> {
        Ok(ProjectContext::new(
            self.project_id.clone(),
            self.config.clone(),
            root_dir,
        ))
    }

    /// Export to JSON
    pub fn to_json(&self) -> Result<String> {
        Ok(serde_json::to_string_pretty(self)?)
    }

    /// Import from JSON
    pub fn from_json(json: &str) -> Result<Self> {
        Ok(serde_json::from_str(json)?)
    }
}

#[cfg(test)]
mod tests {
    use super::*;
    use crate::ProjectConfig;
    use std::path::PathBuf;

    #[test]
    fn test_project_context_creation() {
        let config = ProjectConfig::new("test-project");
        let ctx = ProjectContext::new("proj-123", config, PathBuf::from("."));

        assert_eq!(ctx.project_id, "proj-123");
        assert_eq!(ctx.config.project.name, "test-project");
    }

    #[test]
    fn test_context_status_summary() {
        let config = ProjectConfig::new("my-app");
        let ctx = ProjectContext::new("proj-1", config, PathBuf::from("."));

        let summary = ctx.status_summary();
        assert!(summary.contains("my-app"));
        assert!(summary.contains("creation"));
    }

    #[test]
    fn test_context_snapshot() {
        let config = ProjectConfig::new("app");
        let ctx = ProjectContext::new("proj-1", config, PathBuf::from("."));

        let snapshot = ContextSnapshot::from_context(&ctx);
        assert_eq!(snapshot.project_id, "proj-1");

        let json = snapshot.to_json().unwrap();
        assert!(json.contains("proj-1"));
        assert!(json.contains("app"));

        let restored = ContextSnapshot::from_json(&json).unwrap();
        assert_eq!(restored.project_id, snapshot.project_id);
    }
}
