use super::html_escape;
use compliance_core::models::dast::DastFinding;

pub(super) fn executive_summary(
    findings: &[DastFinding],
    target_name: &str,
    target_url: &str,
    tool_count: usize,
    tool_invocations: u32,
    success_rate: f64,
) -> String {
    let critical = findings
        .iter()
        .filter(|f| f.severity.to_string() == "critical")
        .count();
    let high = findings
        .iter()
        .filter(|f| f.severity.to_string() == "high")
        .count();
    let medium = findings
        .iter()
        .filter(|f| f.severity.to_string() == "medium")
        .count();
    let low = findings
        .iter()
        .filter(|f| f.severity.to_string() == "low")
        .count();
    let info = findings
        .iter()
        .filter(|f| f.severity.to_string() == "info")
        .count();
    let exploitable = findings.iter().filter(|f| f.exploitable).count();
    let total = findings.len();

    let overall_risk = if critical > 0 {
        "CRITICAL"
    } else if high > 0 {
        "HIGH"
    } else if medium > 0 {
        "MEDIUM"
    } else if low > 0 {
        "LOW"
    } else {
        "INFORMATIONAL"
    };

    let risk_color = match overall_risk {
        "CRITICAL" => "#991b1b",
        "HIGH" => "#c2410c",
        "MEDIUM" => "#a16207",
        "LOW" => "#1d4ed8",
        _ => "#4b5563",
    };

    let risk_score: usize =
        std::cmp::min(100, critical * 25 + high * 15 + medium * 8 + low * 3 + info);

    let severity_bar = build_severity_bar(critical, high, medium, low, info, total);

    // Table of contents finding sub-entries
    let severity_order = ["critical", "high", "medium", "low", "info"];
    let toc_findings_sub = if !findings.is_empty() {
        let mut sub = String::new();
        let mut fnum = 0usize;
        for &sev_key in severity_order.iter() {
            let count = findings
                .iter()
                .filter(|f| f.severity.to_string() == sev_key)
                .count();
            if count == 0 {
                continue;
            }
            for f in findings
                .iter()
                .filter(|f| f.severity.to_string() == sev_key)
            {
                fnum += 1;
                sub.push_str(&format!(
                    r#"<div class="toc-sub">F-{:03} — {}</div>"#,
                    fnum,
                    html_escape(&f.title),
                ));
            }
        }
        sub
    } else {
        String::new()
    };

    let critical_high_str = format!("{} / {}", critical, high);
    let escaped_target_name = html_escape(target_name);
    let escaped_target_url = html_escape(target_url);

    format!(
        r##"<!-- ═══════════════ TABLE OF CONTENTS ═══════════════ -->
<div class="report-body">

<div class="toc">
    <h2>Table of Contents</h2>
    <div class="toc-entry"><span class="toc-num">1</span><span class="toc-label">Executive Summary</span></div>
    <div class="toc-entry"><span class="toc-num">2</span><span class="toc-label">Scope &amp; Methodology</span></div>
    <div class="toc-entry"><span class="toc-num">3</span><span class="toc-label">Findings ({total_findings})</span></div>
    {toc_findings_sub}
    <div class="toc-entry"><span class="toc-num">4</span><span class="toc-label">Attack Chain Timeline</span></div>
    <div class="toc-entry"><span class="toc-num">5</span><span class="toc-label">Appendix</span></div>
</div>

<!-- ═══════════════ 1. EXECUTIVE SUMMARY ═══════════════ -->
<h2><span class="section-num">1.</span> Executive Summary</h2>

<div class="risk-gauge">
    <div class="risk-gauge-meter">
        <div class="risk-gauge-track">
            <div class="risk-gauge-fill" style="width: {risk_score}%; background: {risk_color};"></div>
        </div>
        <div class="risk-gauge-score" style="color: {risk_color};">{risk_score} / 100</div>
    </div>
    <div class="risk-gauge-text">
        <div class="risk-gauge-label" style="color: {risk_color};">Overall Risk: {overall_risk}</div>
        <div class="risk-gauge-desc">
            Based on {total_findings} finding{findings_plural} identified across the target application.
        </div>
    </div>
</div>

<div class="exec-grid">
    <div class="kpi-card">
        <div class="kpi-value">{total_findings}</div>
        <div class="kpi-label">Total Findings</div>
    </div>
    <div class="kpi-card">
        <div class="kpi-value" style="color: var(--sev-critical);">{critical_high}</div>
        <div class="kpi-label">Critical / High</div>
    </div>
    <div class="kpi-card">
        <div class="kpi-value" style="color: var(--sev-critical);">{exploitable_count}</div>
        <div class="kpi-label">Exploitable</div>
    </div>
    <div class="kpi-card">
        <div class="kpi-value">{tool_count}</div>
        <div class="kpi-label">Tools Used</div>
    </div>
</div>

<h3>Severity Distribution</h3>
{severity_bar}

<p>
    This report presents the results of an automated penetration test conducted against
    <strong>{target_name}</strong> (<code>{target_url}</code>) using the Compliance Scanner
    AI-powered testing engine. A total of <strong>{total_findings} vulnerabilities</strong> were
    identified, of which <strong>{exploitable_count}</strong> were confirmed exploitable with
    working proof-of-concept payloads. The assessment employed <strong>{tool_count} security tools</strong>
    across <strong>{tool_invocations} invocations</strong> ({success_rate:.0}% success rate).
</p>"##,
        total_findings = total,
        findings_plural = if total == 1 { "" } else { "s" },
        critical_high = critical_high_str,
        exploitable_count = exploitable,
        target_name = escaped_target_name,
        target_url = escaped_target_url,
    )
}

fn build_severity_bar(
    critical: usize,
    high: usize,
    medium: usize,
    low: usize,
    info: usize,
    total: usize,
) -> String {
    if total == 0 {
        return String::new();
    }

    let crit_pct = (critical as f64 / total as f64 * 100.0) as usize;
    let high_pct = (high as f64 / total as f64 * 100.0) as usize;
    let med_pct = (medium as f64 / total as f64 * 100.0) as usize;
    let low_pct = (low as f64 / total as f64 * 100.0) as usize;
    let info_pct = 100_usize.saturating_sub(crit_pct + high_pct + med_pct + low_pct);

    let mut bar = String::from(r#"<div class="sev-bar">"#);
    if critical > 0 {
        bar.push_str(&format!(
            r#"<div class="sev-bar-seg sev-bar-critical" style="width:{}%"><span>{}</span></div>"#,
            std::cmp::max(crit_pct, 4),
            critical
        ));
    }
    if high > 0 {
        bar.push_str(&format!(
            r#"<div class="sev-bar-seg sev-bar-high" style="width:{}%"><span>{}</span></div>"#,
            std::cmp::max(high_pct, 4),
            high
        ));
    }
    if medium > 0 {
        bar.push_str(&format!(
            r#"<div class="sev-bar-seg sev-bar-medium" style="width:{}%"><span>{}</span></div>"#,
            std::cmp::max(med_pct, 4),
            medium
        ));
    }
    if low > 0 {
        bar.push_str(&format!(
            r#"<div class="sev-bar-seg sev-bar-low" style="width:{}%"><span>{}</span></div>"#,
            std::cmp::max(low_pct, 4),
            low
        ));
    }
    if info > 0 {
        bar.push_str(&format!(
            r#"<div class="sev-bar-seg sev-bar-info" style="width:{}%"><span>{}</span></div>"#,
            std::cmp::max(info_pct, 4),
            info
        ));
    }
    bar.push_str("</div>");
    bar.push_str(r#"<div class="sev-bar-legend">"#);
    if critical > 0 {
        bar.push_str(r#"<span><i class="sev-dot" style="background:#991b1b"></i> Critical</span>"#);
    }
    if high > 0 {
        bar.push_str(r#"<span><i class="sev-dot" style="background:#c2410c"></i> High</span>"#);
    }
    if medium > 0 {
        bar.push_str(r#"<span><i class="sev-dot" style="background:#a16207"></i> Medium</span>"#);
    }
    if low > 0 {
        bar.push_str(r#"<span><i class="sev-dot" style="background:#1d4ed8"></i> Low</span>"#);
    }
    if info > 0 {
        bar.push_str(r#"<span><i class="sev-dot" style="background:#4b5563"></i> Info</span>"#);
    }
    bar.push_str("</div>");
    bar
}
