//! Calibration redesign (HARD RULE — Probe for ALL measurements) — integration
//! test: a `Probe` measuring SDT + free `cond/z_ua` via model `embeddings[]`
//! (Modelica unknown + equation — not SaturatedController / controls[]).

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_sdt_calib.json");
    std::fs::write(&path, json).unwrap();
    run_simulation(&path, None, false).unwrap()
}

#[test]
fn probe_based_sdt_calibration_converges_and_solves_z_ua() {
    let json = r#"
{
  "name": "Probe-based SDT calibration (R134a BPHX chiller)",
  "description": "Same vapor-compression cycle as calibration_sdt.rs, but the SDT measurement lives on a Probe node spliced into the condenser refrigerant inlet edge. control.measure.component = the Probe name.",
  "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": "cond_sdt_probe",
          "measure": "SDT",
          "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
        },
        {
          "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_sdt_probe:inlet" },
        { "from": "cond_sdt_probe:outlet","to": "cond:inlet" },
        { "from": "cond:outlet",          "to": "exv:inlet" },
        { "from": "exv:outlet",           "to": "evap:inlet" },
        { "from": "evap: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_cond_z_ua",
      "unknown": {
        "component": "cond",
        "factor": "z_ua",
        "start": 0.3,
        "min": 0.05,
        "max": 2.0
      },
      "equation": {
        "component": "cond_sdt_probe",
        "output": "saturationTemperature",
        "value": 315.0
      }
    }
  ]
}
"#;
    let result = run_config(json);
    assert!(
        matches!(result.status, SimulationStatus::Converged),
        "Probe-based SDT calibration must converge: {:?} ({:?})",
        result.status,
        result.error
    );
    let solved = result
        .solved_variables
        .iter()
        .find(|v| v.variable == "z_ua" && v.component.as_deref() == Some("cond"))
        .expect("solved_variables must contain cond/z_ua");
    eprintln!("DIAG z_ua résolu = {}", solved.value);
    eprintln!("DIAG cible SDT = 315.0 K (41.85°C)");
    if let Some(state) = result.state.as_ref() {
        for e in state.iter() {
            if e.target.as_deref() == Some("cond") || e.source.as_deref() == Some("cond") {
                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));
            }
        }
    }
    let mut sdt_c = None;
    if let Some(state) = result.state.as_ref() {
        for e in state.iter() {
            if e.target.as_deref() == Some("cond") || e.source.as_deref() == Some("cond_sdt_probe")
            {
                if let Some(ts) = e.saturation_temperature_c {
                    sdt_c = Some(ts);
                }
            }
        }
    }
    let sdt_k = sdt_c.expect("must read SDT near condenser inlet probe") + 273.15;
    assert!(
        (sdt_k - 315.0).abs() < 0.5,
        "SDT must hit target 315.0 K within 0.5 K, got {sdt_k}"
    );
    assert!(
        solved.value > 0.05 && solved.value < 2.0,
        "z_ua must solve within bounds, got {}",
        solved.value
    );
}
