use anyhow::Result;
use plotters::prelude::*;
use std::path::Path;

use crate::metrics::LoadTestReport;

pub fn generate_html_report<P: AsRef<Path>>(output_path: P, report: LoadTestReport) -> Result<()> {
    let output_path = output_path.as_ref();
    tracing::info!("Generating HTML report: {:?}", output_path);

    // Generate plots
    let rps_chart_path = output_path.with_extension("rps.svg");
    let latency_chart_path = output_path.with_extension("latency.svg");
    let error_chart_path = output_path.with_extension("errors.svg");

    generate_rps_chart(&rps_chart_path, &report)?;
    generate_latency_chart(&latency_chart_path, &report)?;
    generate_error_rate_chart(&error_chart_path, &report)?;

    // Generate HTML
    let html = format!(
        r#"<!DOCTYPE html>
<html>
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Load Test Report: {test_name}</title>
    <style>
        body {{
            font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, Ubuntu, Cantarell, sans-serif;
            line-height: 1.6;
            color: #333;
            max-width: 1200px;
            margin: 0 auto;
            padding: 20px;
            background: #f5f5f5;
        }}
        .container {{
            background: white;
            padding: 30px;
            border-radius: 8px;
            box-shadow: 0 2px 4px rgba(0,0,0,0.1);
        }}
        h1 {{
            color: #2c3e50;
            border-bottom: 3px solid #3498db;
            padding-bottom: 10px;
        }}
        h2 {{
            color: #34495e;
            margin-top: 30px;
        }}
        .summary {{
            display: grid;
            grid-template-columns: repeat(auto-fit, minmax(250px, 1fr));
            gap: 20px;
            margin: 20px 0;
        }}
        .metric-card {{
            background: #ecf0f1;
            padding: 20px;
            border-radius: 6px;
            border-left: 4px solid #3498db;
        }}
        .metric-card h3 {{
            margin: 0 0 10px 0;
            color: #2c3e50;
            font-size: 14px;
            text-transform: uppercase;
        }}
        .metric-card .value {{
            font-size: 32px;
            font-weight: bold;
            color: #2c3e50;
        }}
        .metric-card .unit {{
            font-size: 16px;
            color: #7f8c8d;
        }}
        .success {{ border-left-color: #27ae60; }}
        .warning {{ border-left-color: #f39c12; }}
        .error {{ border-left-color: #e74c3c; }}
        .chart {{
            margin: 30px 0;
            text-align: center;
        }}
        .chart img {{
            max-width: 100%;
            height: auto;
            border: 1px solid #ddd;
            border-radius: 4px;
        }}
        .recommendation {{
            background: #e8f5e9;
            border-left: 4px solid #4caf50;
            padding: 20px;
            margin: 20px 0;
            border-radius: 4px;
        }}
        .recommendation h3 {{
            margin-top: 0;
            color: #2e7d32;
        }}
        table {{
            width: 100%;
            border-collapse: collapse;
            margin: 20px 0;
        }}
        th, td {{
            padding: 12px;
            text-align: left;
            border-bottom: 1px solid #ddd;
        }}
        th {{
            background-color: #3498db;
            color: white;
        }}
        tr:hover {{
            background-color: #f5f5f5;
        }}
        .timestamp {{
            color: #7f8c8d;
            font-size: 14px;
        }}
    </style>
</head>
<body>
    <div class="container">
        <h1>{test_name}</h1>
        <p class="timestamp">
            Test Period: {start_time} to {end_time}<br>
            Duration: {duration_secs} seconds ({duration_hours:.2} hours)
        </p>

        <h2>Summary</h2>
        <div class="summary">
            <div class="metric-card success">
                <h3>Total Requests</h3>
                <div class="value">{total_requests}</div>
            </div>
            <div class="metric-card {rps_class}">
                <h3>Requests/Second</h3>
                <div class="value">{rps:.0}</div>
            </div>
            <div class="metric-card {error_class}">
                <h3>Error Rate</h3>
                <div class="value">{error_rate:.2}<span class="unit">%</span></div>
            </div>
            <div class="metric-card {latency_class}">
                <h3>P99 Latency</h3>
                <div class="value">{p99_latency:.2}<span class="unit">ms</span></div>
            </div>
        </div>

        <h2>Latency Statistics</h2>
        <table>
            <tr>
                <th>Percentile</th>
                <th>Latency (ms)</th>
            </tr>
            <tr><td>Minimum</td><td>{min_latency:.3}</td></tr>
            <tr><td>P50 (Median)</td><td>{p50_latency:.3}</td></tr>
            <tr><td>P90</td><td>{p90_latency:.3}</td></tr>
            <tr><td>P95</td><td>{p95_latency:.3}</td></tr>
            <tr><td>P99</td><td>{p99_latency:.3}</td></tr>
            <tr><td>P99.9</td><td>{p99_9_latency:.3}</td></tr>
            <tr><td>Maximum</td><td>{max_latency:.3}</td></tr>
            <tr><td>Mean</td><td>{mean_latency:.3}</td></tr>
            <tr><td>Std Dev</td><td>{stddev_latency:.3}</td></tr>
        </table>

        <h2>Request Breakdown</h2>
        <table>
            <tr>
                <th>Status</th>
                <th>Count</th>
                <th>Percentage</th>
            </tr>
            <tr>
                <td>Successful</td>
                <td>{successful_requests}</td>
                <td>{success_pct:.2}%</td>
            </tr>
            <tr>
                <td>Failed</td>
                <td>{failed_requests}</td>
                <td>{failed_pct:.2}%</td>
            </tr>
            <tr>
                <td>Timeout</td>
                <td>{timeout_requests}</td>
                <td>{timeout_pct:.2}%</td>
            </tr>
            <tr>
                <td>Rate Limited</td>
                <td>{rate_limited_requests}</td>
                <td>{rate_limited_pct:.2}%</td>
            </tr>
            <tr>
                <td>Circuit Breaker</td>
                <td>{circuit_breaker_requests}</td>
                <td>{circuit_breaker_pct:.2}%</td>
            </tr>
        </table>

        {per_service_stats}

        {capacity_recommendation}

        <h2>Performance Over Time</h2>

        <div class="chart">
            <h3>Requests Per Second</h3>
            <img src="{rps_chart_filename}" alt="RPS Chart">
        </div>

        <div class="chart">
            <h3>P99 Latency</h3>
            <img src="{latency_chart_filename}" alt="Latency Chart">
        </div>

        <div class="chart">
            <h3>Error Rate</h3>
            <img src="{error_chart_filename}" alt="Error Rate Chart">
        </div>
    </div>
</body>
</html>"#,
        test_name = report.test_name,
        start_time = report.start_time.format("%Y-%m-%d %H:%M:%S UTC"),
        end_time = report.end_time.format("%Y-%m-%d %H:%M:%S UTC"),
        duration_secs = report.metrics.duration.as_secs(),
        duration_hours = report.metrics.duration.as_secs_f64() / 3600.0,
        total_requests = report.metrics.total_requests,
        rps = report.metrics.requests_per_second,
        rps_class = if report.metrics.requests_per_second > 1000.0 {
            "success"
        } else {
            "warning"
        },
        error_rate = report.metrics.error_rate_pct,
        error_class = if report.metrics.error_rate_pct < 1.0 {
            "success"
        } else if report.metrics.error_rate_pct < 5.0 {
            "warning"
        } else {
            "error"
        },
        p99_latency = report.metrics.latency_stats.p99_ms,
        latency_class = if report.metrics.latency_stats.p99_ms < 10.0 {
            "success"
        } else if report.metrics.latency_stats.p99_ms < 50.0 {
            "warning"
        } else {
            "error"
        },
        min_latency = report.metrics.latency_stats.min_ms,
        p50_latency = report.metrics.latency_stats.p50_ms,
        p90_latency = report.metrics.latency_stats.p90_ms,
        p95_latency = report.metrics.latency_stats.p95_ms,
        p99_9_latency = report.metrics.latency_stats.p99_9_ms,
        max_latency = report.metrics.latency_stats.max_ms,
        mean_latency = report.metrics.latency_stats.mean_ms,
        stddev_latency = report.metrics.latency_stats.stddev_ms,
        successful_requests = report.metrics.successful_requests,
        success_pct =
            (f64::from(u32::try_from(report.metrics.successful_requests).unwrap_or(u32::MAX))
                / f64::from(u32::try_from(report.metrics.total_requests).unwrap_or(u32::MAX)))
                * 100.0,
        failed_requests = report.metrics.failed_requests,
        failed_pct = (f64::from(u32::try_from(report.metrics.failed_requests).unwrap_or(u32::MAX))
            / f64::from(u32::try_from(report.metrics.total_requests).unwrap_or(u32::MAX)))
            * 100.0,
        timeout_requests = report.metrics.timeout_requests,
        timeout_pct =
            (f64::from(u32::try_from(report.metrics.timeout_requests).unwrap_or(u32::MAX))
                / f64::from(u32::try_from(report.metrics.total_requests).unwrap_or(u32::MAX)))
                * 100.0,
        rate_limited_requests = report.metrics.rate_limited_requests,
        rate_limited_pct =
            (f64::from(u32::try_from(report.metrics.rate_limited_requests).unwrap_or(u32::MAX))
                / f64::from(u32::try_from(report.metrics.total_requests).unwrap_or(u32::MAX)))
                * 100.0,
        circuit_breaker_requests = report.metrics.circuit_breaker_requests,
        circuit_breaker_pct =
            (f64::from(u32::try_from(report.metrics.circuit_breaker_requests).unwrap_or(u32::MAX))
                / f64::from(u32::try_from(report.metrics.total_requests).unwrap_or(u32::MAX)))
                * 100.0,
        per_service_stats = generate_per_service_stats_html(&report),
        capacity_recommendation = generate_capacity_recommendation_html(&report),
        rps_chart_filename = rps_chart_path.file_name().unwrap().to_str().expect("INVARIANT: Path should be valid UTF-8"),
        latency_chart_filename = latency_chart_path.file_name().unwrap().to_str().expect("INVARIANT: Path should be valid UTF-8"),
        error_chart_filename = error_chart_path.file_name().unwrap().to_str().expect("INVARIANT: Path should be valid UTF-8"),
    );

    std::fs::write(output_path, html)?;

    tracing::info!("HTML report generated: {:?}", output_path);

    Ok(())
}

fn generate_per_service_stats_html(report: &LoadTestReport) -> String {
    if report.metrics.per_service_stats.is_empty() {
        return String::new();
    }

    let mut html = String::from("<h2>Per-Service Statistics</h2><table>");
    html.push_str("<tr><th>Service</th><th>Requests</th><th>Error Rate</th><th>P50</th><th>P95</th><th>P99</th></tr>");

    for (service, stats) in &report.metrics.per_service_stats {
        html.push_str(&format!(
            "<tr><td>{}</td><td>{}</td><td>{:.2}%</td><td>{:.2}ms</td><td>{:.2}ms</td><td>{:.2}ms</td></tr>",
            service, stats.total_requests, stats.error_rate_pct,
            stats.latency_stats.p50_ms, stats.latency_stats.p95_ms, stats.latency_stats.p99_ms
        ));
    }

    html.push_str("</table>");
    html
}

fn generate_capacity_recommendation_html(report: &LoadTestReport) -> String {
    if let Some(rec) = &report.capacity_recommendation {
        format!(
            r#"<div class="recommendation">
                <h3>Capacity Recommendation</h3>
                <p><strong>Max Sustainable Clients:</strong> {}</p>
                <p><strong>Max Sustainable RPS:</strong> {:.0}</p>
                {}
                <p>{}</p>
            </div>"#,
            rec.max_sustainable_clients,
            rec.max_sustainable_rps,
            rec.bottleneck_identified
                .as_ref()
                .map(|b| format!("<p><strong>Bottleneck:</strong> {}</p>", b))
                .unwrap_or_default(),
            rec.recommendation
        )
    } else {
        String::new()
    }
}

fn generate_rps_chart<P: AsRef<Path>>(path: P, report: &LoadTestReport) -> Result<()> {
    let root = SVGBackend::new(path.as_ref(), (800_u32, 400)).into_drawing_area();
    root.fill(&WHITE)?;

    let max_rps = report
        .time_series
        .iter()
        .map(|p| p.rps)
        .fold(0.0f64, f64::max);

    let mut chart = ChartBuilder::on(&root)
        .caption("Requests Per Second", ("sans-serif", 30))
        .margin(10)
        .x_label_area_size(30)
        .y_label_area_size(50)
        .build_cartesian_2d(0..report.time_series.len(), 0f64..max_rps * 1.1)?;

    chart.configure_mesh().draw()?;

    chart.draw_series(LineSeries::new(
        report
            .time_series
            .iter()
            .enumerate()
            .map(|(i, p)| (i, p.rps)),
        &BLUE,
    ))?;

    root.present()?;
    Ok(())
}

fn generate_latency_chart<P: AsRef<Path>>(path: P, report: &LoadTestReport) -> Result<()> {
    let root = SVGBackend::new(path.as_ref(), (800_u32, 400)).into_drawing_area();
    root.fill(&WHITE)?;

    let max_latency = report
        .time_series
        .iter()
        .map(|p| p.p99_latency_ms)
        .fold(0.0f64, f64::max);

    let mut chart = ChartBuilder::on(&root)
        .caption("P99 Latency (ms)", ("sans-serif", 30))
        .margin(10)
        .x_label_area_size(30)
        .y_label_area_size(50)
        .build_cartesian_2d(0..report.time_series.len(), 0f64..max_latency * 1.1)?;

    chart.configure_mesh().draw()?;

    chart.draw_series(LineSeries::new(
        report
            .time_series
            .iter()
            .enumerate()
            .map(|(i, p)| (i, p.p99_latency_ms)),
        &RED,
    ))?;

    root.present()?;
    Ok(())
}

fn generate_error_rate_chart<P: AsRef<Path>>(path: P, report: &LoadTestReport) -> Result<()> {
    let root = SVGBackend::new(path.as_ref(), (800_u32, 400)).into_drawing_area();
    root.fill(&WHITE)?;

    let max_error_rate = report
        .time_series
        .iter()
        .map(|p| p.error_rate_pct)
        .fold(0.0f64, f64::max);

    let mut chart = ChartBuilder::on(&root)
        .caption("Error Rate (%)", ("sans-serif", 30))
        .margin(10)
        .x_label_area_size(30)
        .y_label_area_size(50)
        .build_cartesian_2d(
            0..report.time_series.len(),
            0f64..(max_error_rate * 1.1).max(1.0),
        )?;

    chart.configure_mesh().draw()?;

    chart.draw_series(LineSeries::new(
        report
            .time_series
            .iter()
            .enumerate()
            .map(|(i, p)| (i, p.error_rate_pct)),
        &RED,
    ))?;

    root.present()?;
    Ok(())
}
