//! Probe Fixed Tsat on suction line + free `evap/z_ua` (model embedding).
//!
//! HVAC placement: SST lives on the suction line (`evap:outlet → probe → comp:inlet`),
//! never on the two-phase EXV→evap inlet.

use entropyk_cli::run::{run_simulation, SimulationResult, SimulationStatus};
use tempfile::tempdir;

fn run_config(json: &str) -> SimulationResult {
    let dir = tempdir().unwrap();
    let path = dir.path().join("probe_sst_calib.json");
    std::fs::write(&path, json).unwrap();
    run_simulation(&path, None, false).unwrap()
}

#[test]
fn probe_based_sst_evap_calibration() {
    let json = r#"
{
  "name": "Probe-based SST calibration (R134a BPHX chiller)",
  "description": "Suction Probe Fixed Tsat drives evap/z_ua via model embedding.",
  "fluid": "R134a",
  "fluid_backend": "CoolProp",
  "circuits": [
    {
      "id": 0,
      "name": "Refrigerant + water loops",
      "components": [
        {
          "type": "IsentropicCompressor",
          "name": "comp",
          "isentropic_efficiency": 0.7,
          "t_cond_k": 318.15,
          "t_evap_k": 278.15,
          "superheat_k": 5.0,
          "emergent_pressure": true,
          "displacement_m3": 6.5e-05,
          "speed_hz": 50.0,
          "volumetric_efficiency": 0.92
        },
        {
          "type": "BphxCondenser",
          "name": "cond",
          "refrigerant": "R134a",
          "secondary_fluid": "Water",
          "n_plates": 40,
          "plate_length_m": 0.4,
          "plate_width_m": 0.12,
          "target_subcooling_k": 5.0,
          "emergent_pressure": true,
          "correlation": "Longo2004",
          "dp_correlation": "SimplifiedChannel",
          "ua": 2500.0
        },
        {
          "type": "Probe",
          "name": "evap_sst_probe",
          "measure": "SST",
          "fluid": "R134a"
        },
        {
          "type": "IsenthalpicExpansionValve",
          "name": "exv",
          "t_evap_k": 278.15,
          "emergent_pressure": true
        },
        {
          "type": "BphxEvaporator",
          "name": "evap",
          "refrigerant": "R134a",
          "secondary_fluid": "Water",
          "n_plates": 40,
          "plate_length_m": 0.4,
          "plate_width_m": 0.12,
          "target_superheat_k": 5.0,
          "emergent_pressure": true,
          "correlation": "Longo2004",
          "dp_correlation": "SimplifiedChannel",
          "ua": 2000.0,
          "z_ua": 1.0
        },
        {
          "type": "BrineSource",
          "name": "cond_water_in",
          "fluid": "Water",
          "p_set_bar": 2.0,
          "t_set_c": 30.0,
          "m_flow_kg_s": 0.4,
          "fix_pressure": false,
          "fix_temperature": true,
          "fix_mass_flow": true
        },
        {
          "type": "BrineSink",
          "name": "cond_water_out",
          "fluid": "Water",
          "p_back_bar": 2.0,
          "fix_pressure": true
        },
        {
          "type": "BrineSource",
          "name": "evap_water_in",
          "fluid": "Water",
          "p_set_bar": 3.0,
          "t_set_c": 12.0,
          "m_flow_kg_s": 0.5,
          "fix_pressure": false,
          "fix_temperature": true,
          "fix_mass_flow": true
        },
        {
          "type": "BrineSink",
          "name": "evap_water_out",
          "fluid": "Water",
          "p_back_bar": 3.0,
          "fix_pressure": true
        }
      ],
      "edges": [
        { "from": "comp:outlet",          "to": "cond:inlet" },
        { "from": "cond:outlet",          "to": "exv:inlet" },
        { "from": "exv:outlet",           "to": "evap:inlet" },
        { "from": "evap:outlet",          "to": "evap_sst_probe:inlet" },
        { "from": "evap_sst_probe:outlet","to": "comp:inlet" },
        { "from": "cond_water_in:outlet", "to": "cond:secondary_inlet" },
        { "from": "cond:secondary_outlet","to": "cond_water_out:inlet" },
        { "from": "evap_water_in:outlet", "to": "evap:secondary_inlet" },
        { "from": "evap:secondary_outlet","to": "evap_water_out:inlet" }
      ]
    }
  ],
  "solver": {
    "strategy": "fallback",
    "max_iterations": 300,
    "tolerance": 1e-06,
    "timeout_ms": 60000
  },
  "embeddings": [
    {
      "id": "emb_evap_z_ua",
      "unknown": {
        "component": "evap",
        "factor": "z_ua",
        "start": 0.3,
        "min": 0.05,
        "max": 2.0
      },
      "equation": {
        "component": "evap_sst_probe",
        "output": "saturationTemperature",
        "value": 277.55
      }
    }
  ]
}
"#;
    let result = run_config(json);
    assert!(
        matches!(result.status, SimulationStatus::Converged),
        "Probe-based SST calibration must converge: {:?} ({:?})",
        result.status,
        result.error
    );
    let solved = result
        .solved_variables
        .iter()
        .find(|v| v.variable == "z_ua" && v.component.as_deref() == Some("evap"))
        .expect("solved_variables must contain evap/z_ua");
    eprintln!("DIAG z_ua résolu = {}", solved.value);
    eprintln!("DIAG cible SST = 277.55 K (4.4°C)");

    let mut sst_c = None;
    if let Some(state) = result.state.as_ref() {
        for e in state.iter() {
            if e.source.as_deref() == Some("evap")
                || e.target.as_deref() == Some("evap_sst_probe")
                || e.source.as_deref() == Some("evap_sst_probe")
            {
                eprintln!(
                    "DIAG edge {}→{}  P={}bar  T_sat={}°C  T={}°C",
                    e.source.as_deref().unwrap_or("?"),
                    e.target.as_deref().unwrap_or("?"),
                    e.pressure_bar,
                    e.saturation_temperature_c.unwrap_or(f64::NAN),
                    e.temperature_c.unwrap_or(f64::NAN)
                );
                if e.source.as_deref() == Some("evap_sst_probe")
                    || e.target.as_deref() == Some("evap_sst_probe")
                {
                    if let Some(ts) = e.saturation_temperature_c {
                        sst_c = Some(ts);
                    }
                }
            }
        }
    }
    let sst_k = sst_c.expect("must read SST from suction probe edge") + 273.15;
    assert!(
        (sst_k - 277.55).abs() < 0.5,
        "SST must hit target 277.55 K within 0.5 K, got {sst_k}"
    );
    assert!(
        solved.value > 0.05 && solved.value < 2.0,
        "z_ua must solve within bounds, got {}",
        solved.value
    );
}
