//! Exemple: Pompe et compresseur avec polynômes
//!
//! Démontre l'utilisation des polynômes pour modéliser:
//! - Pompe: courbes H(Q) et η(Q) avec Polynomial1D
//! - Compresseur: modèle SST/SDT avec Polynomial2D
//! - Lois d'affinité pour variation de vitesse
//!
//! Exécuter: cargo run -p entropyk-demo --bin pump_compressor_polynomials

use entropyk_components::compressor::SstSdtCoefficients;
use entropyk_components::polynomials::{AffinityLaws, Polynomial1D};
use entropyk_components::port::{FluidId, Port};
use entropyk_components::pump::{Pump, PumpCurves};
use entropyk_core::{Enthalpy, Pressure};

fn main() -> Result<(), Box<dyn std::error::Error>> {
    println!("╔══════════════════════════════════════════════════════════════╗");
    println!("║  Exemple: Pompe et Compresseur avec Polynômes                ║");
    println!("╚══════════════════════════════════════════════════════════════╝\n");

    // ═══════════════════════════════════════════════════════════════
    // 1. POLYNÔMES 1D - Courbes de pompe
    // ═══════════════════════════════════════════════════════════════
    println!("📐 1. Polynômes 1D (Pompe)\n");

    // H = 30 - 10*Q - 50*Q²  (hauteur en m, Q en m³/s)
    let head_poly = Polynomial1D::quadratic(30.0, -10.0, -50.0);
    // η = 0.5 + 0.3*Q - 0.5*Q²  (rendement 0-1)
    let eff_poly = Polynomial1D::quadratic(0.5, 0.3, -0.5);

    println!("  Courbe hauteur:  H = 30 - 10*Q - 50*Q²");
    println!("  Courbe rendement: η = 0.5 + 0.3*Q - 0.5*Q²\n");

    for q in [0.0, 0.05, 0.1, 0.15, 0.2] {
        let h = head_poly.evaluate(q);
        let eta = eff_poly.evaluate(q);
        println!(
            "  Q={:.2} m³/s  →  H={:.2} m,  η={:.1}%",
            q,
            h,
            eta.clamp(0.0, 1.0) * 100.0
        );
    }

    // ═══════════════════════════════════════════════════════════════
    // 2. POMPE avec courbes polynomiales
    // ═══════════════════════════════════════════════════════════════
    println!("\n🔧 2. Pompe (PumpCurves polynomiales)\n");

    let curves = PumpCurves::quadratic(
        30.0, -10.0, -50.0, // H = h0 + h1*Q + h2*Q²
        0.5, 0.3, -0.5, // η = e0 + e1*Q + e2*Q²
    )?;

    let inlet = Port::new(
        FluidId::new("Water"),
        Pressure::from_bar(1.0),
        Enthalpy::from_joules_per_kg(100_000.0),
    );
    let outlet = Port::new(
        FluidId::new("Water"),
        Pressure::from_bar(1.0),
        Enthalpy::from_joules_per_kg(100_000.0),
    );

    let pump = Pump::new(curves, inlet, outlet, 1000.0)?;

    println!("  Pompe créée (eau, ρ=1000 kg/m³)");
    println!(
        "  Point nominal Q=0.1 m³/s: H={:.2} m, η={:.1}%\n",
        pump.curves().head_at_flow(0.1),
        pump.curves().efficiency_at_flow(0.1) * 100.0
    );

    // ═══════════════════════════════════════════════════════════════
    // 3. POLYNÔMES 2D - Modèle compresseur SST/SDT
    // ═══════════════════════════════════════════════════════════════
    println!("📐 3. Polynômes 2D (Compresseur SST/SDT)\n");

    // Modèle bilinéaire: ṁ = a00 + a10*SST + a01*SDT + a11*SST*SDT
    //                   Ẇ = b00 + b10*SST + b01*SDT + b11*SST*SDT
    let sst_sdt = SstSdtCoefficients::bilinear(
        0.05, 0.001, 0.0005, 0.00001, // débit (kg/s)
        1000.0, 50.0, 30.0, 0.5, // puissance (W)
    );

    println!("  Modèle: ṁ = f(SST, SDT), Ẇ = g(SST, SDT)");
    println!("  SST = température saturation aspiration (K)");
    println!("  SDT = température saturation refoulement (K)\n");

    // Conditions typiques: évaporation -5°C (268K), condensation 40°C (313K)
    let sst_evap = 268.15; // -5°C
    let sdt_cond = 313.15; // 40°C

    let mass_flow = sst_sdt.mass_flow_at(sst_evap, sdt_cond);
    let power = sst_sdt.power_at(sst_evap, sdt_cond);

    println!(
        "  SST={:.1} K (-5°C), SDT={:.1} K (40°C):",
        sst_evap, sdt_cond
    );
    println!("    → ṁ = {:.4} kg/s", mass_flow);
    println!("    → Ẇ = {:.0} W\n", power);

    // Grille de conditions
    println!("  Grille de performance:");
    println!(
        "  {:>8} | {:>8} {:>8} {:>8} {:>8}",
        "SST\\SDT", "303K", "308K", "313K", "318K"
    );
    println!("  -------- | -------- -------- -------- --------");

    for sst in [263.15, 268.15, 273.15] {
        print!("  {:>6.0}K |", sst);
        for sdt in [303.15, 308.15, 313.15, 318.15] {
            let m = sst_sdt.mass_flow_at(sst, sdt);
            print!(" {:>7.3} ", m);
        }
        println!();
    }

    // ═══════════════════════════════════════════════════════════════
    // 4. Lois d'affinité (variation de vitesse)
    // ═══════════════════════════════════════════════════════════════
    println!("\n📐 4. Lois d'affinité (pompe/ventilateur à vitesse variable)\n");

    let speed_ratios = [1.0, 0.8, 0.6, 0.5];

    println!("  À 50% vitesse: Q₂=0.5*Q₁, H₂=0.25*H₁, P₂=0.125*P₁\n");
    println!(
        "  {:>10} | {:>10} {:>10} {:>10}",
        "Vitesse", "Q ratio", "H ratio", "P ratio"
    );
    println!("  ---------- | ---------- ---------- ----------");

    for &ratio in &speed_ratios {
        // AffinityLaws: Q₂=scale_flow(Q₁), H₂=scale_head(H₁), P₂=scale_power(P₁)
        let q_ratio = AffinityLaws::scale_flow(1.0, ratio);
        let h_ratio = AffinityLaws::scale_head(1.0, ratio);
        let p_ratio = AffinityLaws::scale_power(1.0, ratio);
        println!(
            "  {:>8.0}% | {:>10.2} {:>10.2} {:>10.2}",
            ratio * 100.0,
            q_ratio,
            h_ratio,
            p_ratio
        );
    }

    println!("\n✅ Exemple terminé !");
    Ok(())
}
