//! Demo Entropyk - Chiller System Simulation
//!
//! Complete refrigeration system with:
//! - Air-cooled condenser (35°C ambient air)
//! - BPHE evaporator (water 12°C → 7°C)
//! - Compressor
//! - Expansion valve (EXV)
//!
//! System topology:
//!   Circuit 0 (Refrigerant R410A):
//!     Compressor → Condenser → EXV → Evaporator → Compressor
//!
//!   Circuit 1 (Water/Glycol):
//!     Pump → Evaporator (heat exchange) → Pump

use colored::Colorize;
use entropyk_components::heat_exchanger::{CondenserCoil, Evaporator};
use entropyk_components::{Component, ComponentError, JacobianBuilder, ResidualVector, StateSlice};
use entropyk_core::{MassFlow, Pressure, Temperature, ThermalConductance};
use entropyk_solver::{
    compute_coupling_heat, coupling_groups, has_circular_dependencies, System, ThermalCoupling,
};
use std::fmt;

fn print_header(title: &str) {
    println!();
    println!("{}", "═".repeat(70).cyan());
    println!("{}", format!("  {}", title).cyan().bold());
    println!("{}", "═".repeat(70).cyan());
}

fn print_section(title: &str) {
    println!();
    println!("{}", format!("▶ {}", title).yellow().bold());
    println!("{}", "─".repeat(50).yellow());
}

fn print_subsection(title: &str) {
    println!();
    println!("  {}", format!("◆ {}", title).white().bold());
}

// Simple placeholder component for demo
struct PlaceholderComponent {
    name: String,
    n_eqs: usize,
}

impl PlaceholderComponent {
    #[allow(clippy::new_ret_no_self)]
    fn new(name: &str) -> Box<dyn Component> {
        Box::new(Self {
            name: name.to_string(),
            n_eqs: 0,
        })
    }

    fn with_equations(name: &str, n_eqs: usize) -> Box<dyn Component> {
        Box::new(Self {
            name: name.to_string(),
            n_eqs,
        })
    }
}

impl Component for PlaceholderComponent {
    fn compute_residuals(
        &self,
        _state: &StateSlice,
        residuals: &mut ResidualVector,
    ) -> Result<(), ComponentError> {
        for r in residuals.iter_mut() {
            *r = 0.0;
        }
        Ok(())
    }

    fn jacobian_entries(
        &self,
        _state: &StateSlice,
        _jacobian: &mut JacobianBuilder,
    ) -> Result<(), ComponentError> {
        Ok(())
    }

    fn n_equations(&self) -> usize {
        self.n_eqs
    }

    fn get_ports(&self) -> &[entropyk_components::ConnectedPort] {
        &[]
    }
}

impl fmt::Debug for PlaceholderComponent {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        f.debug_struct("PlaceholderComponent")
            .field("name", &self.name)
            .finish()
    }
}

// ============================================================================
// MAIN DEMO
// ============================================================================

fn main() {
    println!(
        "{}",
        "\n╔══════════════════════════════════════════════════════════════════╗".green()
    );
    println!(
        "{}",
        "║        ENTROPYK - Water Chiller System Demo                      ║"
            .green()
            .bold()
    );
    println!(
        "{}",
        "║        Condenser: Air-cooled (35°C ambient)                      ║".green()
    );
    println!(
        "{}",
        "║        Evaporator: BPHE (water 12°C → 7°C)                       ║".green()
    );
    println!(
        "{}",
        "╚══════════════════════════════════════════════════════════════════╝\n".green()
    );

    // ========================================
    // Part 1: Design Point Analysis
    // ========================================
    print_header("Design Point Analysis");

    println!();
    println!("{}", "  Water Chiller - Cooling Mode".white());
    println!("{}", "  ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━".white());

    // Water side
    let t_water_in = Temperature::from_celsius(12.0);
    let t_water_out = Temperature::from_celsius(7.0);
    let water_flow = MassFlow::from_kg_per_s(0.5); // 0.5 kg/s ≈ 30 L/min
    let cp_water = 4186.0; // J/(kg·K)

    let q_evap =
        water_flow.to_kg_per_s() * cp_water * (t_water_in.to_celsius() - t_water_out.to_celsius());

    println!();
    println!("{}", "  Water Side (Evaporator Load)".cyan());
    println!("    T_water_in:    {:.1}°C", t_water_in.to_celsius());
    println!("    T_water_out:   {:.1}°C", t_water_out.to_celsius());
    println!(
        "    ṁ_water:       {:.2} kg/s ({:.0} L/min)",
        water_flow.to_kg_per_s(),
        water_flow.to_kg_per_s() * 60.0
    );
    println!(
        "    Q_evap:        {:.0} W = {:.1} kW",
        q_evap,
        q_evap / 1000.0
    );

    // Air side (condenser)
    let t_amb = Temperature::from_celsius(35.0);
    let approach_cond = 10.0; // K approach temperature
    let t_cond = Temperature::from_celsius(t_amb.to_celsius() + approach_cond);

    // Estimate compressor power (assuming COP ≈ 3.5)
    let cop_estimate = 3.5;
    let w_comp = q_evap / cop_estimate;
    let q_cond = q_evap + w_comp;

    println!();
    println!("{}", "  Air Side (Condenser Rejection)".cyan());
    println!("    T_ambient:     {:.1}°C", t_amb.to_celsius());
    println!("    Approach:      {:.1} K", approach_cond);
    println!(
        "    T_cond:        {:.1}°C ({:.2} K)",
        t_cond.to_celsius(),
        t_cond.to_kelvin()
    );
    println!(
        "    Q_cond:        {:.0} W = {:.1} kW",
        q_cond,
        q_cond / 1000.0
    );

    println!();
    println!("{}", "  Compressor".cyan());
    println!(
        "    W_comp:        {:.0} W = {:.2} kW",
        w_comp,
        w_comp / 1000.0
    );
    println!("    COP (est):     {:.1}", cop_estimate);

    // Evaporator temperature
    let approach_evap = 5.0; // K
    let t_evap = Temperature::from_celsius(t_water_out.to_celsius() - approach_evap);

    println!();
    println!("{}", "  Refrigerant Cycle (R410A)".cyan());
    println!(
        "    T_evap:        {:.1}°C ({:.2} K)",
        t_evap.to_celsius(),
        t_evap.to_kelvin()
    );
    println!(
        "    T_cond:        {:.1}°C ({:.2} K)",
        t_cond.to_celsius(),
        t_cond.to_kelvin()
    );
    println!(
        "    ΔT_lift:       {:.1} K",
        t_cond.to_kelvin() - t_evap.to_kelvin()
    );

    // Pressure estimates for R410A (approximate)
    let p_evap = Pressure::from_bar(8.0); // ~5°C saturation for R410A
    let p_cond = Pressure::from_bar(24.0); // ~45°C saturation for R410A
    let pressure_ratio = p_cond.to_bar() / p_evap.to_bar();

    println!("    P_evap:        {:.1} bar", p_evap.to_bar());
    println!("    P_cond:        {:.1} bar", p_cond.to_bar());
    println!("    PR:            {:.2}", pressure_ratio);

    // Heat exchanger sizing
    println!();
    println!("{}", "  Heat Exchanger Sizing".cyan());

    // Condenser UA (air-cooled, typical 0.1-0.2 kW/K per kW capacity)
    let ua_cond = q_cond / (t_cond.to_kelvin() - t_amb.to_kelvin());
    println!(
        "    UA_condenser:  {:.0} W/K = {:.1} kW/K",
        ua_cond,
        ua_cond / 1000.0
    );

    // Evaporator UA (BPHE, water-to-refrigerant)
    let delta_t1 = t_water_in.to_kelvin() - t_evap.to_kelvin();
    let delta_t2 = t_water_out.to_kelvin() - t_evap.to_kelvin();
    let lmtd_evap = (delta_t1 - delta_t2) / (delta_t1 / delta_t2).ln();
    let ua_evap = q_evap / lmtd_evap;
    println!("    LMTD_evap:     {:.1} K", lmtd_evap);
    println!(
        "    UA_evaporator: {:.0} W/K = {:.1} kW/K",
        ua_evap,
        ua_evap / 1000.0
    );

    // ========================================
    // Part 2: Create Heat Exchangers (Real Components)
    // ========================================
    print_header("Component Creation");

    // Condenser (air-cooled)
    print_section("Creating Air-Cooled Condenser");
    let condenser = CondenserCoil::with_saturation_temp(ua_cond, t_cond.to_kelvin());
    println!("  UA: {:.0} W/K", condenser.ua());
    println!(
        "  T_sat: {:.1}°C ({:.2} K)",
        t_cond.to_celsius(),
        t_cond.to_kelvin()
    );
    println!("  Equations: {}", condenser.n_equations());
    println!("  {} Condenser coil created", "✓".green());

    // Evaporator (BPHE water-to-refrigerant)
    print_section("Creating BPHE Evaporator");
    let evaporator = Evaporator::with_superheat(ua_evap, t_evap.to_kelvin(), 5.0);
    println!("  UA: {:.0} W/K", evaporator.ua());
    println!(
        "  T_sat: {:.1}°C ({:.2} K)",
        t_evap.to_celsius(),
        t_evap.to_kelvin()
    );
    println!("  Superheat target: 5 K");
    println!("  Equations: {}", evaporator.n_equations());
    println!("  {} BPHE evaporator created", "✓".green());

    // ========================================
    // Part 3: System Topology
    // ========================================
    print_header("System Topology");

    print_section("Creating Multi-Circuit System");

    let mut system = System::new();

    // Circuit 0: Refrigerant
    let n_comp = system
        .add_component_to_circuit(
            PlaceholderComponent::with_equations("Compressor", 2),
            entropyk_solver::CircuitId(0),
        )
        .unwrap();
    let n_cond = system
        .add_component_to_circuit(
            Box::new(CondenserCoil::with_saturation_temp(
                ua_cond,
                t_cond.to_kelvin(),
            )),
            entropyk_solver::CircuitId(0),
        )
        .unwrap();
    let n_exv = system
        .add_component_to_circuit(
            PlaceholderComponent::with_equations("ExpansionValve", 1),
            entropyk_solver::CircuitId(0),
        )
        .unwrap();
    let n_evap = system
        .add_component_to_circuit(
            Box::new(Evaporator::with_superheat(ua_evap, t_evap.to_kelvin(), 5.0)),
            entropyk_solver::CircuitId(0),
        )
        .unwrap();

    // Circuit 1: Water
    let n_pump = system
        .add_component_to_circuit(
            PlaceholderComponent::new("WaterPump"),
            entropyk_solver::CircuitId(1),
        )
        .unwrap();
    let n_load = system
        .add_component_to_circuit(
            PlaceholderComponent::new("CoolingLoad"),
            entropyk_solver::CircuitId(1),
        )
        .unwrap();

    println!("  Circuit 0 (Refrigerant R410A):");
    println!("    [{}] Compressor", n_comp.index());
    println!("    [{}] CondenserCoil", n_cond.index());
    println!("    [{}] ExpansionValve", n_exv.index());
    println!("    [{}] Evaporator (BPHE)", n_evap.index());
    println!();
    println!("  Circuit 1 (Water/Glycol):");
    println!("    [{}] WaterPump", n_pump.index());
    println!("    [{}] CoolingLoad", n_load.index());

    // Connect refrigerant cycle
    print_subsection("Connecting Refrigerant Circuit");
    system.add_edge(n_comp, n_cond).unwrap();
    system.add_edge(n_cond, n_exv).unwrap();
    system.add_edge(n_exv, n_evap).unwrap();
    system.add_edge(n_evap, n_comp).unwrap();
    println!("  Compressor → Condenser → EXV → Evaporator → Compressor");
    println!("  {} Refrigerant cycle connected", "✓".green());

    // Connect water cycle (independent circuit - no cross-circuit flow edges!)
    print_subsection("Connecting Water Circuit");
    system.add_edge(n_pump, n_load).unwrap();
    system.add_edge(n_load, n_pump).unwrap();
    println!("  Pump → CoolingLoad → Pump (independent closed loop)");
    println!("  {} Water circuit connected", "✓".green());
    println!();
    println!(
        "  {} Thermal coupling handles heat transfer between circuits",
        "Note:".cyan()
    );
    println!("     (No cross-circuit flow edges allowed)");

    println!();
    println!(
        "  {} circuits, {} components, {} flow edges",
        system.circuit_count(),
        system.node_count(),
        system.edge_count()
    );

    // ========================================
    // Part 4: Thermal Coupling
    // ========================================
    print_header("Thermal Coupling");

    print_section("Adding Heat Exchanger Coupling");

    // The evaporator thermally couples water to refrigerant
    // Water is hot side, refrigerant is cold side (evaporating)
    let coupling = ThermalCoupling::new(
        entropyk_solver::CircuitId(1), // Hot: water circuit
        entropyk_solver::CircuitId(0), // Cold: refrigerant circuit (evaporating)
        ThermalConductance::from_watts_per_kelvin(ua_evap),
    )
    .with_efficiency(0.95);

    let idx = system.add_thermal_coupling(coupling.clone()).unwrap();
    println!("  Coupling [{}]:", idx);
    println!(
        "    Hot circuit:  Circuit 1 (Water @ {:.1}°C)",
        t_water_in.to_celsius()
    );
    println!(
        "    Cold circuit: Circuit 0 (R410A @ {:.1}°C)",
        t_evap.to_celsius()
    );
    println!("    UA: {:.0} W/K", coupling.ua.to_watts_per_kelvin());
    println!("    Efficiency: {:.0}%", coupling.efficiency * 100.0);
    println!("  {} Thermal coupling added", "✓".green());

    // Compute heat transfer at design point
    print_subsection("Heat Transfer at Design Point");
    let q_calc = compute_coupling_heat(&coupling, t_water_in, t_evap);
    println!("  T_hot (water):  {:.1}°C", t_water_in.to_celsius());
    println!("  T_cold (ref):   {:.1}°C", t_evap.to_celsius());
    println!(
        "  ΔT:             {:.1} K",
        t_water_in.to_kelvin() - t_evap.to_kelvin()
    );
    println!(
        "  Q_calc:         {:.0} W = {:.1} kW",
        q_calc,
        q_calc / 1000.0
    );

    // ========================================
    // Part 5: Circular Dependency Check
    // ========================================
    print_header("Solver Strategy");

    print_section("Coupling Analysis");

    let couplings = system.thermal_couplings();
    let has_cycle = has_circular_dependencies(couplings);

    println!(
        "  Circular dependency: {}",
        if has_cycle { "YES".red() } else { "NO".green() }
    );

    let groups = coupling_groups(couplings);
    println!("  Coupling groups: {:?}", groups);

    if has_cycle {
        println!();
        println!(
            "  {} Circuits with mutual coupling must be solved SIMULTANEOUSLY",
            "→".yellow()
        );
        println!("     (Newton-Raphson on combined system)");
    } else {
        println!();
        println!("  {} Circuits can be solved SEQUENTIALLY", "→".green());
        println!("     (Water circuit → Refrigerant circuit)");
    }

    // ========================================
    // Part 6: Finalize System
    // ========================================
    print_header("System Finalization");

    match system.finalize() {
        Ok(()) => {
            println!("  {} System finalized successfully", "✓".green());
            println!(
                "  {} state variables (P, h per edge)",
                system.state_vector_len()
            );
        }
        Err(e) => {
            println!("  {} Finalization error: {:?}", "✗".red(), e);
        }
    }

    // ========================================
    // Summary
    // ========================================
    print_header("System Summary");

    println!();
    println!(
        "{}",
        "  ┌─────────────────────────────────────────────────────────────┐".white()
    );
    println!(
        "{}",
        "  │                    WATER CHILLER SYSTEM                    │".white()
    );
    println!(
        "{}",
        "  ├─────────────────────────────────────────────────────────────┤".white()
    );
    println!(
        "{}",
        "  │  REFRIGERANT CIRCUIT (R410A)                               │".white()
    );
    println!(
        "{}",
        "  │    Compressor: 2900 RPM, 30cc, η=85%                       │".white()
    );
    println!(
        "  │    Condenser:  Air-cooled, UA={:.0} W/K                     │",
        ua_cond
    );
    println!(
        "{}",
        "  │    EXV:         Isenthalpic, 100% open                     │".white()
    );
    println!(
        "  │    Evaporator:  BPHE, UA={:.0} W/K, SH=5K                   │",
        ua_evap
    );
    println!(
        "{}",
        "  ├─────────────────────────────────────────────────────────────┤".white()
    );
    println!(
        "{}",
        "  │  WATER CIRCUIT                                            │".white()
    );
    println!(
        "  │    Pump:         {:.2} kg/s, ΔP=200 kPa                      │",
        0.5
    );
    println!(
        "{}",
        "  │    Inlet:        12°C                                      │".white()
    );
    println!(
        "{}",
        "  │    Outlet:       7°C                                       │".white()
    );
    println!(
        "{}",
        "  ├─────────────────────────────────────────────────────────────┤".white()
    );
    println!(
        "{}",
        "  │  PERFORMANCE (Design Point)                               │".white()
    );
    println!(
        "  │    Q_evap:       {:.1} kW                                    │",
        q_evap / 1000.0
    );
    println!(
        "  │    Q_cond:       {:.1} kW                                    │",
        q_cond / 1000.0
    );
    println!(
        "  │    W_comp:       {:.2} kW                                    │",
        w_comp / 1000.0
    );
    println!(
        "  │    COP:          {:.1}                                       │",
        q_evap / w_comp
    );
    println!(
        "{}",
        "  └─────────────────────────────────────────────────────────────┘".white()
    );

    println!();
    println!("{}", "═".repeat(70).cyan());
    println!(
        "{}",
        "  Next: Implement solver (Epic 4) to run full simulation".cyan()
    );
    println!("{}", "═".repeat(70).cyan());
}
