//! Phase-specific actions and initialization logic
//!
//! Defines what happens when a project enters a specific lifecycle phase.
//! Each phase has associated actions that set up necessary infrastructure,
//! enable/disable tools, and initialize tracking.

use crate::error::Result;
use crate::{ProjectConfig, ProjectPhase};
use chrono::Utc;
use std::fs;
use std::path::Path;

/// Phase executor that runs actions for each lifecycle phase
#[derive(Debug)]
pub struct PhaseExecutor;

impl PhaseExecutor {
    /// Execute phase-specific initialization actions
    ///
    /// This is called when transitioning to a new phase.
    /// It ensures all necessary infrastructure is set up for that phase.
    pub fn execute_phase_actions(
        phase: ProjectPhase,
        config: &mut ProjectConfig,
        project_root: &Path,
    ) -> Result<()> {
        match phase {
            ProjectPhase::Creation => Self::on_creation(config, project_root),
            ProjectPhase::Devel => Self::on_devel(config, project_root),
            ProjectPhase::Update => Self::on_update(config, project_root),
            ProjectPhase::Review => Self::on_review(config, project_root),
            ProjectPhase::Status => Self::on_status(config, project_root),
            ProjectPhase::Publish => Self::on_publish(config, project_root),
            ProjectPhase::Archive => Self::on_archive(config, project_root),
            ProjectPhase::Mvp => Self::on_mvp(config, project_root),
            ProjectPhase::Prototype => Self::on_prototype(config, project_root),
        }
    }

    /// Actions for Creation phase:
    /// - Initialize project structure
    /// - Create .project directory
    /// - Create data directory for databases
    /// - Create logs directory
    /// - Initialize tracking database
    fn on_creation(config: &mut ProjectConfig, project_root: &Path) -> Result<()> {
        println!("  • Creating project structure...");

        // Create .project directory
        let tools_dir = project_root.join(".project");
        fs::create_dir_all(&tools_dir)?;
        println!("    ✓ Created .project directory");

        // Create data directory for databases
        let data_dir = project_root.join("data");
        fs::create_dir_all(&data_dir)?;
        println!("    ✓ Created data directory");

        // Create logs directory
        let logs_dir = project_root.join(".project/logs");
        fs::create_dir_all(&logs_dir)?;
        println!("    ✓ Created logs directory");

        // Create .coder directory for tracking
        let coder_dir = project_root.join(".coder");
        fs::create_dir_all(&coder_dir)?;
        println!("    ✓ Created .coder tracking directory");

        // Initialize project metadata file
        let metadata_path = tools_dir.join("project.json");
        if !metadata_path.exists() {
            let metadata = serde_json::json!({
                "created_at": Utc::now().to_rfc3339(),
                "name": config.project.name,
                "version": config.project.version,
                "project_type": format!("{:?}", config.project_type),
            });
            fs::write(&metadata_path, serde_json::to_string_pretty(&metadata)?)?;
            println!("    ✓ Created project metadata");
        }

        Ok(())
    }

    /// Actions for Devel phase:
    /// - Enable development tools (tracking, docs)
    /// - Create development configuration
    /// - Initialize development database
    /// - Set up local development environment
    fn on_devel(config: &mut ProjectConfig, project_root: &Path) -> Result<()> {
        println!("  • Setting up development environment...");

        // Enable tracking tool if available
        if let Some(tracking) = config.tools.tools.get_mut("tracking") {
            if !tracking.enabled {
                tracking.enabled = true;
                println!("    ✓ Enabled tracking tool");
            }
        }

        // Enable docs tool if available
        if let Some(docs) = config.tools.tools.get_mut("docs") {
            if !docs.enabled {
                docs.enabled = true;
                println!("    ✓ Enabled documentation tool");
            }
        }

        // Create dev config if doesn't exist
        let dev_config_path = project_root.join(".project/dev.toml");
        if !dev_config_path.exists() {
            let dev_config = r#"# Development configuration
[development]
hot_reload = true
debug_logging = true
test_on_save = false
watch_patterns = ["src/**/*.rs", "Cargo.toml"]
"#;
            fs::write(&dev_config_path, dev_config)?;
            println!("    ✓ Created development configuration");
        }

        // Initialize tracking database
        let tracking_db = project_root.join("data/tracking.db");
        if !tracking_db.exists() {
            println!("    ✓ Tracking database ready for initialization");
        }

        Ok(())
    }

    /// Actions for Update phase:
    /// - Verify tracking is enabled
    /// - Create update changelog entry point
    /// - Prepare version update files
    fn on_update(config: &mut ProjectConfig, project_root: &Path) -> Result<()> {
        println!("  • Preparing for updates...");

        // Ensure tracking is enabled
        if let Some(tracking) = config.tools.tools.get_mut("tracking") {
            tracking.enabled = true;
        }

        // Create updates directory if needed
        let updates_dir = project_root.join(".coder/updates");
        fs::create_dir_all(&updates_dir)?;
        println!("    ✓ Created updates tracking directory");

        // Create update log
        let update_log = updates_dir.join("UPDATES.md");
        if !update_log.exists() {
            let content = format!(
                "# Update Log\n\nProject: {}\nStarted: {}\n\n## Updates\n",
                config.project.name,
                Utc::now().to_rfc3339()
            );
            fs::write(&update_log, content)?;
            println!("    ✓ Created update log");
        }

        Ok(())
    }

    /// Actions for Review phase:
    /// - Enable code review tools
    /// - Prepare review checklist
    /// - Set up review documentation
    fn on_review(_config: &mut ProjectConfig, project_root: &Path) -> Result<()> {
        println!("  • Preparing for code review...");

        // Create review directory
        let review_dir = project_root.join(".coder/review");
        fs::create_dir_all(&review_dir)?;
        println!("    ✓ Created review directory");

        // Create review checklist template
        let checklist_path = review_dir.join("CHECKLIST.md");
        if !checklist_path.exists() {
            let checklist = r#"# Code Review Checklist

## Code Quality
- [ ] Code follows project standards
- [ ] No hardcoded values
- [ ] Proper error handling
- [ ] Tests included and passing

## Documentation
- [ ] API documented
- [ ] Complex logic explained
- [ ] Examples provided
- [ ] README updated

## Security
- [ ] No security vulnerabilities
- [ ] Input validation present
- [ ] Dependencies up to date
- [ ] No hardcoded secrets

## Performance
- [ ] No obvious performance issues
- [ ] Database queries optimized
- [ ] Memory usage reasonable
"#;
            fs::write(&checklist_path, checklist)?;
            println!("    ✓ Created review checklist");
        }

        Ok(())
    }

    /// Actions for Status phase:
    /// - Generate status report
    /// - Collect metrics
    /// - Archive status snapshots
    fn on_status(config: &mut ProjectConfig, project_root: &Path) -> Result<()> {
        println!("  • Generating status snapshot...");

        // Create status snapshots directory
        let status_dir = project_root.join(".coder/status");
        fs::create_dir_all(&status_dir)?;
        println!("    ✓ Created status directory");

        // Create status snapshot
        let timestamp = Utc::now();
        let snapshot_name = format!("status_{}.json", timestamp.format("%Y%m%d_%H%M%S"));
        let snapshot_path = status_dir.join(&snapshot_name);

        let snapshot = serde_json::json!({
            "timestamp": timestamp.to_rfc3339(),
            "project": config.project.name,
            "version": config.project.version,
            "phase": format!("{:?}", config.phase),
            "tools_enabled": config.tools.tools.iter()
                .filter(|(_, t)| t.enabled)
                .map(|(name, _)| name.clone())
                .collect::<Vec<_>>(),
        });

        fs::write(&snapshot_path, serde_json::to_string_pretty(&snapshot)?)?;
        println!("    ✓ Created status snapshot: {}", snapshot_name);

        Ok(())
    }

    /// Actions for Publish phase:
    /// - Prepare release documentation
    /// - Create release notes template
    /// - Archive release information
    fn on_publish(config: &mut ProjectConfig, project_root: &Path) -> Result<()> {
        println!("  • Preparing for publication...");

        // Create releases directory
        let releases_dir = project_root.join(".coder/releases");
        fs::create_dir_all(&releases_dir)?;
        println!("    ✓ Created releases directory");

        // Create release notes template
        let version = &config.project.version;
        let release_notes_path = releases_dir.join(format!("RELEASE_{}.md", version));
        if !release_notes_path.exists() {
            let content = format!(
                r#"# Release {}

**Date**: {}
**Project**: {}

## Changes
-

## New Features
-

## Bug Fixes
-

## Breaking Changes
-

## Migration Guide
N/A

## Contributors
-
"#,
                version,
                Utc::now().format("%Y-%m-%d"),
                config.project.name
            );
            fs::write(&release_notes_path, content)?;
            println!("    ✓ Created release notes template");
        }

        Ok(())
    }

    /// Actions for Archive phase:
    /// - Create archive snapshot
    /// - Preserve final state
    /// - Document deprecation
    fn on_archive(config: &mut ProjectConfig, project_root: &Path) -> Result<()> {
        println!("  • Creating archive snapshot...");

        // Create archive directory
        let archive_dir = project_root.join(".coder/archive");
        fs::create_dir_all(&archive_dir)?;
        println!("    ✓ Created archive directory");

        // Create archive manifest
        let manifest_path = archive_dir.join("ARCHIVE_MANIFEST.json");
        let manifest = serde_json::json!({
            "archived_at": Utc::now().to_rfc3339(),
            "project": config.project.name,
            "version": config.project.version,
            "final_phase": "Archive",
            "reason": "Project archived",
            "restoration_notes": "Contact maintainers for restoration procedures"
        });
        fs::write(&manifest_path, serde_json::to_string_pretty(&manifest)?)?;
        println!("    ✓ Created archive manifest");

        Ok(())
    }

    /// Actions for MVP phase:
    /// - Set up minimal viable product
    /// - Enable essential tools only
    /// - Create MVP-specific documentation
    fn on_mvp(config: &mut ProjectConfig, project_root: &Path) -> Result<()> {
        println!("  • Setting up MVP environment...");

        // Create mvp directory
        let mvp_dir = project_root.join(".project/mvp");
        fs::create_dir_all(&mvp_dir)?;
        println!("    ✓ Created MVP configuration directory");

        // Create MVP documentation
        let mvp_doc = mvp_dir.join("MVP_PLAN.md");
        if !mvp_doc.exists() {
            let content = format!(
                r#"# MVP Plan - {}

## Scope
Minimal set of features for initial release.

## Core Features
-

## Out of Scope
-

## Timeline
-

## Success Criteria
-
"#,
                config.project.name
            );
            fs::write(&mvp_doc, content)?;
            println!("    ✓ Created MVP plan");
        }

        Ok(())
    }

    /// Actions for Prototype phase:
    /// - Set up experimental environment
    /// - Enable all experimental tools
    /// - Create prototype documentation
    fn on_prototype(config: &mut ProjectConfig, project_root: &Path) -> Result<()> {
        println!("  • Setting up prototype environment...");

        // Create prototype directory
        let prototype_dir = project_root.join(".project/prototype");
        fs::create_dir_all(&prototype_dir)?;
        println!("    ✓ Created prototype configuration directory");

        // Create prototype notes
        let notes_path = prototype_dir.join("PROTOTYPE_NOTES.md");
        if !notes_path.exists() {
            let content = format!(
                r#"# Prototype Notes - {}

## Experimental Features
-

## Known Limitations
-

## Testing Notes
-

## Learnings & Feedback
-
"#,
                config.project.name
            );
            fs::write(&notes_path, content)?;
            println!("    ✓ Created prototype notes");
        }

        Ok(())
    }
}
