//! Demo Entropyk - Thermal Coupling Between Circuits
//!
//! This example demonstrates:
//! - Multi-circuit system creation (2 circuits)
//! - Component placement in circuits
//! - Thermal coupling between circuits (heat exchanger)
//! - Circular dependency detection
//! - Heat transfer computation

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

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

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

struct SimpleComponent {
    name: String,
    n_eqs: usize,
}

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

impl Component for SimpleComponent {
    fn compute_residuals(
        &self,
        _state: &StateSlice,
        residuals: &mut ResidualVector,
    ) -> Result<(), ComponentError> {
        for r in residuals.iter_mut().take(self.n_eqs) {
            *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 SimpleComponent {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        f.debug_struct("SimpleComponent")
            .field("name", &self.name)
            .finish()
    }
}

fn main() {
    println!(
        "{}",
        "\n╔══════════════════════════════════════════════════════════╗".green()
    );
    println!(
        "{}",
        "║       ENTROPYK - Thermal Coupling Demo (Story 3.4)      ║"
            .green()
            .bold()
    );
    println!(
        "{}",
        "╚══════════════════════════════════════════════════════════╝\n".green()
    );

    // ========================================
    // PART 1: Basic Thermal Coupling
    // ========================================
    print_header("Part 1: Basic Thermal Coupling");

    print_section("Creating ThermalCoupling struct");
    let coupling = ThermalCoupling::new(
        CircuitId(0),                                      // Hot circuit (refrigerant)
        CircuitId(1),                                      // Cold circuit (water/glycol)
        ThermalConductance::from_watts_per_kelvin(5000.0), // 5 kW/K UA value
    )
    .with_efficiency(0.95); // 95% heat exchanger efficiency

    println!("  {} {:?}", "Coupling:".white(), coupling);
    println!(
        "  {} {} W/K",
        "UA:".white(),
        coupling.ua.to_watts_per_kelvin()
    );
    println!(
        "  {} {:.0}%",
        "Efficiency:".white(),
        coupling.efficiency * 100.0
    );

    print_section("Computing heat transfer");
    let t_hot = Temperature::from_celsius(45.0); // Refrigerant condensing at 45°C
    let t_cold = Temperature::from_celsius(35.0); // Water entering at 35°C

    let q = compute_coupling_heat(&coupling, t_hot, t_cold);

    println!(
        "  {} {:.1}°C ({:.1} K)",
        "T_hot:".white(),
        t_hot.to_celsius(),
        t_hot.to_kelvin()
    );
    println!(
        "  {} {:.1}°C ({:.1} K)",
        "T_cold:".white(),
        t_cold.to_celsius(),
        t_cold.to_kelvin()
    );
    println!(
        "  {} {:.1} K",
        "ΔT:".white(),
        t_hot.to_kelvin() - t_cold.to_kelvin()
    );
    println!();
    println!(
        "  {} {:.1} W = {:.2} kW",
        "Heat transfer (Q):".green().bold(),
        q,
        q / 1000.0
    );
    println!(
        "  {} Q > 0 means heat flows INTO cold circuit",
        "Sign convention:".white()
    );

    // Energy conservation demonstration
    println!();
    println!("{}", "  Energy Conservation:".cyan());
    let q_into_cold = q;
    let q_out_of_hot = -q;
    println!(
        "    Q_cold = {:.2} kW (heat received)",
        q_into_cold / 1000.0
    );
    println!(
        "    Q_hot  = {:.2} kW (heat rejected)",
        q_out_of_hot / 1000.0
    );
    println!("    {} Q_cold + Q_hot = 0 ✓", "Check:".green());

    // ========================================
    // PART 2: Multi-Circuit System
    // ========================================
    print_header("Part 2: Multi-Circuit System");

    print_section("Creating 2-circuit heat pump system");
    let mut system = System::new();

    // Circuit 0: Refrigerant circuit
    let comp = system
        .add_component_to_circuit(SimpleComponent::new("Compressor"), CircuitId(0))
        .unwrap();
    let cond = system
        .add_component_to_circuit(SimpleComponent::new("Condenser"), CircuitId(0))
        .unwrap();
    let valve = system
        .add_component_to_circuit(SimpleComponent::new("ExpansionValve"), CircuitId(0))
        .unwrap();
    let evap = system
        .add_component_to_circuit(SimpleComponent::new("Evaporator"), CircuitId(0))
        .unwrap();

    // Circuit 1: Water/glycol circuit
    let pump = system
        .add_component_to_circuit(SimpleComponent::new("Pump"), CircuitId(1))
        .unwrap();
    let hx = system
        .add_component_to_circuit(SimpleComponent::new("HeatExchanger"), CircuitId(1))
        .unwrap();

    println!("  Circuit 0 (Refrigerant):");
    println!("    - Compressor, Condenser, ExpansionValve, Evaporator");
    println!("  Circuit 1 (Water/Glycol):");
    println!("    - Pump, HeatExchanger");

    // Connect refrigerant circuit (cycle)
    system.add_edge(comp, cond).unwrap();
    system.add_edge(cond, valve).unwrap();
    system.add_edge(valve, evap).unwrap();
    system.add_edge(evap, comp).unwrap();

    // Connect water circuit (simple loop)
    system.add_edge(pump, hx).unwrap();
    system.add_edge(hx, pump).unwrap();

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

    print_section("Adding thermal coupling between circuits");
    let thermal_coupling = ThermalCoupling::new(
        CircuitId(0), // Hot: refrigerant condenser
        CircuitId(1), // Cold: water circuit heat exchanger
        ThermalConductance::from_watts_per_kelvin(8000.0),
    );

    match system.add_thermal_coupling(thermal_coupling.clone()) {
        Ok(idx) => println!("  {} Coupling added at index {}", "✓".green(), idx),
        Err(e) => println!("  {} Error: {:?}", "✗".red(), e),
    }

    println!();
    println!(
        "  {} {}",
        "Couplings:".white(),
        system.thermal_coupling_count()
    );
    for (i, c) in system.thermal_couplings().iter().enumerate() {
        println!(
            "    [{}] Circuit {} → Circuit {} (UA = {} W/K)",
            i,
            c.hot_circuit.0,
            c.cold_circuit.0,
            c.ua.to_watts_per_kelvin()
        );
    }

    // Finalize system
    match system.finalize() {
        Ok(()) => println!("\n  {} System finalized successfully", "✓".green()),
        Err(e) => println!("\n  {} Finalize error: {:?}", "✗".red(), e),
    }

    // ========================================
    // PART 3: Circular Dependency Detection
    // ========================================
    print_header("Part 3: Circular Dependency Detection");

    print_section("Scenario A: Single coupling (no cycle)");
    let couplings_a = vec![ThermalCoupling::new(
        CircuitId(0),
        CircuitId(1),
        ThermalConductance::from_watts_per_kelvin(1000.0),
    )];
    let has_cycle_a = has_circular_dependencies(&couplings_a);
    println!("  Couplings: Circuit 0 → Circuit 1");
    println!(
        "  {} {}",
        "Circular dependency:".white(),
        if has_cycle_a {
            "YES (solve simultaneously)".red()
        } else {
            "NO (solve sequentially)".green()
        }
    );

    let groups_a = coupling_groups(&couplings_a);
    println!("  {} {:?}", "Coupling groups:".white(), groups_a);

    print_section("Scenario B: Mutual coupling (cycle!)");
    let couplings_b = vec![
        ThermalCoupling::new(
            CircuitId(0),
            CircuitId(1),
            ThermalConductance::from_watts_per_kelvin(1000.0),
        ),
        ThermalCoupling::new(
            CircuitId(1),
            CircuitId(0), // Back-coupling!
            ThermalConductance::from_watts_per_kelvin(500.0),
        ),
    ];
    let has_cycle_b = has_circular_dependencies(&couplings_b);
    println!("  Couplings:");
    println!("    Circuit 0 → Circuit 1");
    println!("    Circuit 1 → Circuit 0 (back-coupling!)");
    println!();
    println!(
        "  {} {}",
        "Circular dependency:".white(),
        if has_cycle_b {
            "YES (solve simultaneously)".red()
        } else {
            "NO (solve sequentially)".green()
        }
    );

    let groups_b = coupling_groups(&couplings_b);
    println!("  {} {:?}", "Coupling groups:".white(), groups_b);
    if groups_b.iter().any(|g| g.len() > 1) {
        println!(
            "  {} Circuits in same group must be solved together",
            "→".yellow()
        );
    }

    print_section("Scenario C: Chain + mutual (complex)");
    let couplings_c = vec![
        ThermalCoupling::new(
            CircuitId(0),
            CircuitId(1),
            ThermalConductance::from_watts_per_kelvin(1000.0),
        ),
        ThermalCoupling::new(
            CircuitId(1),
            CircuitId(0),
            ThermalConductance::from_watts_per_kelvin(500.0),
        ), // 0↔1 cycle
        ThermalCoupling::new(
            CircuitId(2),
            CircuitId(3),
            ThermalConductance::from_watts_per_kelvin(800.0),
        ), // independent
    ];
    let has_cycle_c = has_circular_dependencies(&couplings_c);
    println!("  Couplings:");
    println!("    Circuit 0 ↔ Circuit 1 (mutual)");
    println!("    Circuit 2 → Circuit 3 (independent)");
    println!();
    println!(
        "  {} {}",
        "Circular dependency:".white(),
        if has_cycle_c {
            "YES".red()
        } else {
            "NO".green()
        }
    );

    let groups_c = coupling_groups(&couplings_c);
    println!("  {} {:?}", "Coupling groups:".white(), groups_c);
    println!(
        "  {} [0,1] together, [2] independent, [3] independent",
        "→".yellow()
    );

    // ========================================
    // PART 4: Error Handling
    // ========================================
    print_header("Part 4: Error Handling");

    print_section("Invalid circuit validation");
    let mut sys_test = System::new();
    sys_test
        .add_component_to_circuit(SimpleComponent::new("A"), CircuitId(0))
        .unwrap();
    // Circuit 1 has NO components!

    let invalid_coupling = ThermalCoupling::new(
        CircuitId(0),
        CircuitId(1), // This circuit doesn't exist!
        ThermalConductance::from_watts_per_kelvin(1000.0),
    );

    match sys_test.add_thermal_coupling(invalid_coupling) {
        Ok(_) => println!("  {} Unexpected success!", "✗".red()),
        Err(e) => {
            println!("  {} Correctly rejected invalid coupling", "✓".green());
            println!("  {} {}", "Error:".white(), e);
        }
    }

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

    println!();
    println!(
        "  {} ThermalCoupling struct with hot/cold circuits + UA + efficiency",
        "✓".green()
    );
    println!(
        "  {} compute_coupling_heat() with sign convention (Q > 0 = heat into cold)",
        "✓".green()
    );
    println!(
        "  {} has_circular_dependencies() via petgraph cycle detection",
        "✓".green()
    );
    println!(
        "  {} coupling_groups() via Kosaraju SCC for solver strategy",
        "✓".green()
    );
    println!(
        "  {} System.add_thermal_coupling() with circuit validation",
        "✓".green()
    );
    println!("  {} InvalidCircuitForCoupling error handling", "✓".green());

    println!();
    println!("{}", "═".repeat(60).cyan());
    println!(
        "{}",
        "  Demo complete! Run 'cargo run --bin thermal-coupling' again.".cyan()
    );
    println!("{}", "═".repeat(60).cyan());
}
