/// Completer Orchestrator
///
/// Coordinates gap analysis, merging, and rendering to complete
/// an existing declaration with missing or inferred requirements.
use super::gap_analyzer::{GapAnalysisResult, GapAnalyzer};
use super::merger::{CurrentTaskserv, IncrementalMerger};
use crate::models::ProjectAnalysis;

/// Completion result
#[derive(Debug)]
pub struct CompletionResult {
    pub gaps: GapAnalysisResult,
    pub changes_needed: usize,
    pub is_safe: bool,
    pub version_bump: String,
    pub change_summary: String,
}

impl CompletionResult {
    pub fn success(&self) -> bool {
        !self.gaps.has_errors()
    }
}

/// Main completer orchestrator
pub struct Completer {
    min_completeness: f32, // 0.0-1.0
}

impl Completer {
    pub fn new() -> Self {
        Self {
            min_completeness: 0.90, // 90% completeness required
        }
    }

    pub fn with_completeness_threshold(mut self, threshold: f32) -> Self {
        self.min_completeness = threshold;
        self
    }

    /// Complete a declaration based on project analysis
    pub fn complete(
        &self,
        analysis: &ProjectAnalysis,
        current_taskservs: Vec<CurrentTaskserv>,
    ) -> CompletionResult {
        // Step 1: Analyze gaps
        let required_taskservs: Vec<String> = analysis
            .requirements
            .iter()
            .filter(|r| r.required)
            .map(|r| r.taskserv.clone())
            .collect();

        let gaps = GapAnalyzer::analyze(analysis, &required_taskservs);

        // Step 2: Check if completeness is acceptable
        if gaps.completeness < self.min_completeness && gaps.has_errors() {
            return CompletionResult {
                gaps,
                changes_needed: 0,
                is_safe: false,
                version_bump: "None".into(),
                change_summary: "Cannot complete: too many critical gaps".into(),
            };
        }

        // Step 3: Plan merge
        let desired = analysis.requirements.to_vec();
        let merge_result = IncrementalMerger::merge(current_taskservs, desired);

        let is_safe = IncrementalMerger::is_safe_merge(&merge_result);
        let version_bump = merge_result.change_tracker.suggest_version_bump();
        let changes_needed =
            merge_result.added.len() + merge_result.removed.len() + merge_result.updated.len();

        // Step 4: Generate summary
        let mut summary_lines = Vec::new();

        if !merge_result.added.is_empty() {
            summary_lines.push(format!("+ Adding: {}", merge_result.added.join(", ")));
        }

        if !merge_result.removed.is_empty() {
            summary_lines.push(format!("- Removing: {}", merge_result.removed.join(", ")));
        }

        if !merge_result.updated.is_empty() {
            for (name, old, new) in &merge_result.updated {
                summary_lines.push(format!("~ Updating {}: {} → {}", name, old, new));
            }
        }

        if !merge_result.preserved.is_empty() {
            summary_lines.push(format!(
                "✓ Preserving {} customization(s)",
                merge_result.preserved.len()
            ));
        }

        let change_summary = if summary_lines.is_empty() {
            "No changes needed".into()
        } else {
            summary_lines.join("\n")
        };

        CompletionResult {
            gaps,
            changes_needed,
            is_safe,
            version_bump: format!("{:?}", version_bump),
            change_summary,
        }
    }
}

impl Default for Completer {
    fn default() -> Self {
        Self::new()
    }
}

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

    use super::*;

    #[test]
    fn test_completer_safe_mode() {
        let completer = Completer::new();

        let mut analysis = ProjectAnalysis::new(PathBuf::from("/test"));
        analysis
            .requirements
            .push(crate::models::Requirement::new("postgres", "DB", 1.0, true));

        let current = vec![];
        let result = completer.complete(&analysis, current);

        // Should suggest changes and be safe (adding new requirements without removals)
        assert!(result.changes_needed > 0);
        assert!(result.is_safe); // Adding new taskservs without removals is
                                 // safe
    }
}
