use anyhow::Result;
use colored::*;

use super::Reporter;
use crate::types::{ScanResults, Severity, Vulnerability};

/// Console reporter for human-readable output (summary only, no detailed vulns)
pub struct ConsoleReporter;

impl ConsoleReporter {
    pub fn new() -> Self {
        Self
    }

    fn severity_color(&self, severity: Severity) -> ColoredString {
        match severity {
            Severity::Critical => "CRITICAL".red().bold(),
            Severity::High => "HIGH".yellow().bold(),
            Severity::Medium => "MEDIUM".yellow(),
            Severity::Low => "LOW".blue(),
        }
    }

    fn format_vulnerability(&self, vuln: &Vulnerability, index: usize) -> String {
        let mut output = Vec::new();

        output.push(format!(
            "\n{} {} {}",
            format!("[{}]", index + 1).dimmed(),
            self.severity_color(vuln.severity),
            vuln.vuln_type.to_string().white().bold()
        ));

        output.push(format!(
            "    {} {}:{}:{}",
            "Location:".blue(),
            vuln.location.file.display(),
            vuln.location.line,
            vuln.location.column
        ));

        output.push(format!("    {} {}", "Description:".blue(), vuln.description));

        if let Some(ref snippet) = vuln.code_snippet {
            output.push(format!("    {}:", "Code:".blue()));
            for line in snippet.lines() {
                output.push(format!("      {}", line.dimmed()));
            }
        }

        output.push(format!(
            "    {} {}",
            "Recommendation:".green(),
            vuln.recommendation
        ));

        if !vuln.migration_impacts.is_empty() {
            output.push(format!("    {}:", "Migration Impacts:".magenta()));
            for impact in &vuln.migration_impacts {
                output.push(format!(
                    "      {} {} - {}",
                    "•".cyan(),
                    impact.impact_type.to_string().cyan(),
                    impact.description
                ));
                output.push(format!(
                    "        {} {}",
                    "Effort:".dimmed(),
                    impact.estimated_effort
                ));
            }
        }

        if let Some(ref cwe) = vuln.cwe_id {
            output.push(format!("    {} {}", "CWE:".dimmed(), cwe));
        }

        if vuln.is_dependency {
            output.push(format!(
                "    {} Found in dependency",
                "⚠".yellow()
            ));
            if let Some(ref chain) = vuln.dependency_chain {
                output.push(format!("      Chain: {}", chain.join(" → ")));
            }
        }

        output.join("\n")
    }
}

impl Reporter for ConsoleReporter {
    fn generate(&self, results: &ScanResults) -> Result<String> {
        // This is only used for file output - return detailed view
        let mut output = Vec::new();

        output.push(format!("\n{}", "Scan Results".cyan().bold()));
        output.push("=".repeat(50));

        // Summary statistics
        output.push(format!("\n{}", "Statistics:".blue().bold()));
        output.push(format!("  Files scanned: {}", results.files_scanned));
        output.push(format!("  Lines scanned: {}", results.lines_scanned));
        output.push(format!(
            "  Scan duration: {}ms",
            (results.completed_at - results.started_at).num_milliseconds()
        ));

        // Severity breakdown
        output.push(format!("\n{}", "Vulnerabilities by Severity:".blue().bold()));
        output.push(format!(
            "  {} Critical: {}",
            "●".red(),
            results.summary.critical_count
        ));
        output.push(format!(
            "  {} High: {}",
            "●".yellow(),
            results.summary.high_count
        ));
        output.push(format!(
            "  {} Medium: {}",
            "●".yellow().dimmed(),
            results.summary.medium_count
        ));
        output.push(format!(
            "  {} Low: {}",
            "●".blue(),
            results.summary.low_count
        ));

        // Type breakdown
        if !results.summary.by_type.is_empty() {
            output.push(format!("\n{}", "Vulnerabilities by Type:".blue().bold()));
            for (vuln_type, count) in &results.summary.by_type {
                output.push(format!("  {} {}: {}", "•".cyan(), vuln_type, count));
            }
        }

        // Impact summary
        if results.has_db_impact || results.has_api_impact {
            output.push(format!("\n{}", "Impact Analysis:".magenta().bold()));
            if results.has_db_impact {
                output.push(format!(
                    "  {} Database schema changes will be required",
                    "⚠".yellow()
                ));
            }
            if results.has_api_impact {
                output.push(format!(
                    "  {} API payload sizes will increase",
                    "⚠".yellow()
                ));
            }
        }

        // Detailed findings (for file output only)
        if !results.vulnerabilities.is_empty() {
            output.push(format!("\n{}", "Detailed Findings:".blue().bold()));
            output.push("-".repeat(50));

            for (i, vuln) in results.vulnerabilities.iter().enumerate() {
                output.push(self.format_vulnerability(vuln, i));
            }
        } else {
            output.push(format!(
                "\n{} No quantum-vulnerable cryptography detected!",
                "✓".green().bold()
            ));
        }

        Ok(output.join("\n"))
    }

    fn print(&self, results: &ScanResults) -> Result<()> {
        // Clean summary output for console - no individual vulnerabilities
        // Vulnerabilities are submitted to the dashboard for detailed viewing
        
        if results.vulnerabilities.is_empty() {
            println!(
                "\n{} No quantum-vulnerable cryptography detected!",
                "✓".green().bold()
            );
            return Ok(());
        }

        // Show severity breakdown as a compact bar
        let total = results.summary.total_vulnerabilities;
        let critical = results.summary.critical_count;
        let high = results.summary.high_count;
        let medium = results.summary.medium_count;
        let low = results.summary.low_count;

        println!();
        println!(
            "{} {} {} {}",
            "╔═══════════════════════════════════════════════════════════╗".cyan(),
            "",
            "",
            ""
        );
        println!(
            "{}  {}  {}",
            "║".cyan(),
            format!("QUANTUM VULNERABILITY SCAN RESULTS").white().bold(),
            "║".cyan()
        );
        println!(
            "{}",
            "╠═══════════════════════════════════════════════════════════╣".cyan()
        );
        
        // Total vulnerabilities
        println!(
            "{}  {} {} {}",
            "║".cyan(),
            "Total Vulnerabilities:".blue(),
            format!("{}", total).yellow().bold(),
            "║".cyan()
        );
        
        // Severity breakdown in one line
        println!(
            "{}  {} {} {} {} {} {} {} {} {}",
            "║".cyan(),
            format!("● {} CRITICAL", critical).red().bold(),
            "│".dimmed(),
            format!("● {} HIGH", high).yellow().bold(),
            "│".dimmed(),
            format!("● {} MEDIUM", medium).yellow(),
            "│".dimmed(),
            format!("● {} LOW", low).blue(),
            "",
            ""
        );

        println!(
            "{}",
            "╠═══════════════════════════════════════════════════════════╣".cyan()
        );

        // Top vulnerability types (limit to top 5)
        let mut types: Vec<_> = results.summary.by_type.iter().collect();
        types.sort_by(|a, b| b.1.cmp(a.1)); // Sort by count descending
        
        println!(
            "{}  {} {}",
            "║".cyan(),
            "Top Vulnerability Types:".blue(),
            "║".cyan()
        );
        
        for (vuln_type, count) in types.iter().take(5) {
            println!(
                "{}    {} {} {}{}",
                "║".cyan(),
                "→".dimmed(),
                format!("{}", vuln_type).white(),
                format!("({})", count).dimmed(),
                " ".repeat(40 - vuln_type.len().min(40))
            );
        }
        
        if types.len() > 5 {
            println!(
                "{}    {} {}",
                "║".cyan(),
                "...".dimmed(),
                format!("and {} more types", types.len() - 5).dimmed()
            );
        }

        println!(
            "{}",
            "╠═══════════════════════════════════════════════════════════╣".cyan()
        );

        // Impact indicators
        if results.has_db_impact || results.has_api_impact {
            println!(
                "{}  {} {}",
                "║".cyan(),
                "Migration Impacts:".magenta(),
                "║".cyan()
            );
            if results.has_db_impact {
                println!(
                    "{}    {} {} {}",
                    "║".cyan(),
                    "⚠".yellow(),
                    "Database schema changes required".white(),
                    ""
                );
            }
            if results.has_api_impact {
                println!(
                    "{}    {} {} {}",
                    "║".cyan(),
                    "⚠".yellow(),
                    "API payload size increases expected".white(),
                    ""
                );
            }
            println!(
                "{}",
                "╠═══════════════════════════════════════════════════════════╣".cyan()
            );
        }

        // Dependency vs direct
        let dep_count = results.summary.dependency_vulnerabilities;
        let direct_count = results.summary.direct_vulnerabilities;
        
        println!(
            "{}  {} {} {} {} {}",
            "║".cyan(),
            format!("{} direct", direct_count).white(),
            "│".dimmed(),
            format!("{} in dependencies", dep_count).dimmed(),
            "",
            ""
        );

        println!(
            "{}",
            "╚═══════════════════════════════════════════════════════════╝".cyan()
        );
        
        println!();
        println!(
            "{}",
            "View full details in your KyberCheck dashboard after submission.".dimmed()
        );

        Ok(())
    }
}
