use std::fs;
use std::path::PathBuf;

use serde_json::json;
use sgclaw::compat::lineloss_xlsx_export::{export_lineloss_xlsx, LinelossExportRequest};

fn temp_output_path(name: &str) -> PathBuf {
    let dir = std::env::temp_dir().join("sgclaw-test-xlsx");
    fs::create_dir_all(&dir).unwrap();
    dir.join(name)
}

#[test]
fn export_month_lineloss_produces_valid_xlsx() {
    let output_path = temp_output_path("month-test.xlsx");
    if output_path.exists() {
        fs::remove_file(&output_path).unwrap();
    }

    let request = LinelossExportRequest {
        sheet_name: "国网兰州供电公司月度线损分析报表(2026-03)".to_string(),
        column_defs: vec![
            ("ORG_NAME".to_string(), "供电单位".to_string()),
            ("YGDL".to_string(), "累计供电量".to_string()),
            ("YYDL".to_string(), "累计售电量".to_string()),
            ("YXSL".to_string(), "线损完成率(%)".to_string()),
            ("RAT_SCOPE".to_string(), "线损率累计目标值".to_string()),
            ("BLANK3".to_string(), "目标完成率".to_string()),
            ("BLANK2".to_string(), "排行".to_string()),
        ],
        rows: vec![
            serde_json::from_value(json!({
                "ORG_NAME": "城关供电",
                "YGDL": "12345.67",
                "YYDL": "11234.56",
                "YXSL": "9.00",
                "RAT_SCOPE": "9.50",
                "BLANK3": "94.74",
                "BLANK2": "1"
            }))
            .unwrap(),
            serde_json::from_value(json!({
                "ORG_NAME": "七里河供电",
                "YGDL": "9876.54",
                "YYDL": "8765.43",
                "YXSL": "11.24",
                "RAT_SCOPE": "10.00",
                "BLANK3": "112.40",
                "BLANK2": "2"
            }))
            .unwrap(),
        ],
        output_path: output_path.clone(),
    };

    let result_path = export_lineloss_xlsx(&request).unwrap();
    assert_eq!(result_path, output_path);
    assert!(output_path.exists());

    // Verify it's a valid ZIP (xlsx is a zip archive)
    let file = fs::File::open(&output_path).unwrap();
    let mut archive = zip::ZipArchive::new(file).unwrap();

    // Must contain the standard OpenXML entries
    let entry_names: Vec<String> = (0..archive.len())
        .map(|i| archive.by_index(i).unwrap().name().to_string())
        .collect();

    assert!(entry_names.contains(&"[Content_Types].xml".to_string()));
    assert!(entry_names.contains(&"xl/worksheets/sheet1.xml".to_string()));
    assert!(entry_names.contains(&"xl/workbook.xml".to_string()));

    // Read sheet1.xml and verify it contains our data
    let mut sheet = archive.by_name("xl/worksheets/sheet1.xml").unwrap();
    let mut xml = String::new();
    std::io::Read::read_to_string(&mut sheet, &mut xml).unwrap();

    assert!(xml.contains("供电单位"), "header row should contain 供电单位");
    assert!(xml.contains("累计供电量"), "header row should contain 累计供电量");
    assert!(xml.contains("城关供电"), "data should contain 城关供电");
    assert!(xml.contains("12345.67"), "data should contain 12345.67");
    assert!(xml.contains("七里河供电"), "data should contain second row");

    // Cleanup
    fs::remove_file(&output_path).unwrap();
}

#[test]
fn export_empty_rows_returns_error() {
    let output_path = temp_output_path("empty-test.xlsx");

    let request = LinelossExportRequest {
        sheet_name: "test".to_string(),
        column_defs: vec![("A".to_string(), "ColA".to_string())],
        rows: vec![],
        output_path: output_path.clone(),
    };

    let result = export_lineloss_xlsx(&request);
    assert!(result.is_err());
    assert!(
        result.unwrap_err().to_string().contains("rows must not be empty"),
        "should reject empty rows"
    );
}
