use std::path::Path;

use colored::Colorize;

use super::{MAX_FLAT_ITEMS, format_path, health::format_window, relative_path, thousands};

pub(super) fn render_runtime_coverage(
    lines: &mut Vec<String>,
    report: &crate::health_types::HealthReport,
    root: &Path,
) {
    let Some(ref production) = report.runtime_coverage else {
        return;
    };

    let verdict = match production.verdict {
        crate::health_types::RuntimeCoverageReportVerdict::Clean => "clean",
        crate::health_types::RuntimeCoverageReportVerdict::HotPathTouched => "hot path touched",
        crate::health_types::RuntimeCoverageReportVerdict::ColdCodeDetected => "cold code detected",
        crate::health_types::RuntimeCoverageReportVerdict::LicenseExpiredGrace => {
            "license expired grace"
        }
        crate::health_types::RuntimeCoverageReportVerdict::Unknown => "unknown",
    };
    lines.push(format!(
        "{} {} {}",
        "\u{25cf}".cyan(),
        "Runtime coverage:".cyan().bold(),
        verdict
    ));
    lines.push(format!(
        "  {} tracked, {} hit, {} unhit, {} untracked ({:.1}% covered)",
        thousands(production.summary.functions_tracked),
        thousands(production.summary.functions_hit),
        thousands(production.summary.functions_unhit),
        thousands(production.summary.functions_untracked),
        production.summary.coverage_percent,
    ));
    if production.summary.trace_count > 0 || production.summary.period_days > 0 {
        lines.push(format!(
            "  based on {} traces over {} day{} ({} deployment{})",
            thousands(production.summary.trace_count as usize),
            production.summary.period_days,
            if production.summary.period_days == 1 {
                ""
            } else {
                "s"
            },
            production.summary.deployments_seen,
            if production.summary.deployments_seen == 1 {
                ""
            } else {
                "s"
            },
        ));
    }
    if matches!(
        production.watermark,
        Some(crate::health_types::RuntimeCoverageWatermark::LicenseExpiredGrace)
    ) {
        lines.push(
            "  license expired grace active; refresh with `fallow license refresh`".to_owned(),
        );
    }
    render_capture_quality_warning(lines, production);
    let shown_findings = production.findings.len().min(MAX_FLAT_ITEMS);
    for finding in &production.findings[..shown_findings] {
        let relative = format_path(&relative_path(&finding.path, root).display().to_string());
        let invocations = finding.invocations.map_or_else(
            || "untracked".to_owned(),
            |hits| format!("{hits} invocations"),
        );
        lines.push(format!(
            "  {relative}:{} {} [{}, {}]",
            finding.line,
            finding.function,
            invocations,
            finding.verdict.human_label(),
        ));
    }
    if production.findings.len() > MAX_FLAT_ITEMS {
        lines.push(format!(
            "  ... and {} more production findings (--format json for full list)",
            production.findings.len() - MAX_FLAT_ITEMS
        ));
    }
    if !production.hot_paths.is_empty() {
        lines.push("  hot paths:".to_owned());
        for entry in production.hot_paths.iter().take(5) {
            let relative = format_path(&relative_path(&entry.path, root).display().to_string());
            lines.push(format!(
                "    {relative}:{} {} ({} invocations, p{})",
                entry.line,
                entry.function,
                thousands(entry.invocations as usize),
                entry.percentile,
            ));
        }
    }
    for warning in &production.warnings {
        lines.push(format!("  warning [{}]: {}", warning.code, warning.message));
    }
    render_upgrade_prompt(lines, production);
    lines.push(String::new());
}

fn render_capture_quality_warning(
    lines: &mut Vec<String>,
    production: &crate::health_types::RuntimeCoverageReport,
) {
    let Some(ref quality) = production.summary.capture_quality else {
        return;
    };
    if !quality.lazy_parse_warning {
        return;
    }
    let instances = quality.instances_observed;
    let instance_label = if instances == 1 {
        "instance"
    } else {
        "instances"
    };
    let window = format_window(quality.window_seconds);
    lines.push(format!(
        "  {}",
        format!(
            "note: short capture ({window} from {instances} {instance_label}); {:.1}% of functions untracked, lazy-parsed scripts may not appear.",
            quality.untracked_ratio_percent,
        )
        .yellow()
    ));
    lines.push(
        "  extend the capture or switch to continuous monitoring for a trustworthy reading."
            .to_owned(),
    );
}

fn render_upgrade_prompt(
    lines: &mut Vec<String>,
    production: &crate::health_types::RuntimeCoverageReport,
) {
    let Some(ref quality) = production.summary.capture_quality else {
        return;
    };
    if !quality.lazy_parse_warning {
        return;
    }
    let window = format_window(quality.window_seconds);
    let instances = quality.instances_observed;
    let instance_label = if instances == 1 {
        "instance"
    } else {
        "instances"
    };
    lines.push(format!(
        "  captured {window} from {instances} {instance_label}."
    ));
    lines.push(
        "  continuous monitoring over 30 days evaluates more paths and surfaces additional candidates the local capture missed."
            .to_owned(),
    );
    lines.push(
        "  start a trial: `fallow license activate --trial --email you@company.com`".to_owned(),
    );
}
