"""
simple_components.py
--------------------
Source, Sink, Mixer, Splitter, Separator, Pipe, Expansion_valve
"""

import warnings
from .base_component import Component


# ================================================================== #
#   VALIDATION DECORATOR
# ================================================================== #
def validate_inputs(func):
    """Decorator to check component inputs before calculation"""
    def wrapper(self):
        # Check if component is part of a model
        if not hasattr(self, 'Model'):
            raise RuntimeError(f"{self.ID}: Not attached to a model")
        
        # Check state points exist
        for attr in dir(self):
            if attr.endswith('_state') or attr.endswith('_states'):
                states = getattr(self, attr)
                if isinstance(states, list):
                    for s in states:
                        if s not in self.Model.Point:
                            raise KeyError(f"{self.ID}: State '{s}' not found in model")
                elif states and states not in self.Model.Point:
                    raise KeyError(f"{self.ID}: State '{states}' not found in model")
        
        return func(self)
    return wrapper


# ================================================================== #
#   SOURCE
# ================================================================== #
class Source(Component):
    """Energy source component - adds fluid to the system"""

    def __init__(self, Model, ID, Out_state, Calculate=False):
        self.Out_state = Out_state
        self.energy_supply = None
        super().__init__(Model, ID, Calculate)

    @validate_inputs
    def Cal(self):
        self.Out = self.Model.Point[self.Out_state]
        
        # Validation
        if self.Out.Mass_flowrate is None:
            raise ValueError(f"{self.ID}: Outlet mass flow rate is missing")
        if self.Out.H is None:
            raise ValueError(f"{self.ID}: Outlet enthalpy is missing")
        if self.Out.Mass_flowrate <= 0:
            raise ValueError(f"{self.ID}: Mass flow rate must be positive")
        
        self.energy_supply = self.Out.H * self.Out.Mass_flowrate
        
        # Exergy destruction (negative for source)
        if self.Out.Ex is not None:
            self.Ex_D = self.Out.Ex
        else:
            self.Ex_D = None
            
        self.Solution_Status = True

    def __str__(self):
        return (
            f"{self.ID} (Source):\n"
            f"  Energy supply  : {self.energy_supply:.2f} W\n"
            f"  Mass flow      : {self.Out.Mass_flowrate:.4f} kg/s\n"
            f"  Exergy         : {self.Ex_D}\n"
            f"  Solved         : {self.Solution_Status}"
        )


# ================================================================== #
#   SINK
# ================================================================== #
class Sink(Component):
    """Energy sink component - removes fluid from the system"""

    def __init__(self, Model, ID, In_state, Calculate=False):
        self.In_state = In_state
        self.energy_supply = None
        super().__init__(Model, ID, Calculate)

    @validate_inputs
    def Cal(self):
        self.In = self.Model.Point[self.In_state]
        
        # Validation
        if self.In.Mass_flowrate is None:
            raise ValueError(f"{self.ID}: Inlet mass flow rate is missing")
        if self.In.H is None:
            raise ValueError(f"{self.ID}: Inlet enthalpy is missing")
        if self.In.Mass_flowrate <= 0:
            raise ValueError(f"{self.ID}: Mass flow rate must be positive")
        
        self.energy_supply = self.In.H * self.In.Mass_flowrate
        
        # Exergy destruction (negative for sink)
        if self.In.Ex is not None:
            self.Ex_D = -self.In.Ex
        else:
            self.Ex_D = None
            
        self.Solution_Status = True

    def __str__(self):
        return (
            f"{self.ID} (Sink):\n"
            f"  Energy supply  : {self.energy_supply:.2f} W\n"
            f"  Mass flow      : {self.In.Mass_flowrate:.4f} kg/s\n"
            f"  Exergy         : {self.Ex_D}\n"
            f"  Solved         : {self.Solution_Status}"
        )


# ================================================================== #
#   MIXER
# ================================================================== #
class Mixer(Component):
    """Mixes multiple inlet streams into one outlet stream"""
    
    TOLERANCE_ENTHALPY = 1.0      # J/kg
    PRESSURE_WARNING_THRESHOLD = 0.05  # 5% pressure difference triggers warning

    def __init__(self, Model, ID, In_states, Out_state, 
                 pressure_loss_fraction=0.0, Calculate=False):
        """
        Args:
            pressure_loss_fraction: Fractional pressure loss (e.g., 0.02 = 2% loss)
        """
        if not In_states or len(In_states) < 2:
            raise ValueError(f"Mixer {ID}: Requires at least 2 inlet states")
            
        self.In_states = In_states
        self.Out_state = Out_state
        self.pressure_loss_fraction = pressure_loss_fraction
        super().__init__(Model, ID, Calculate)

    @validate_inputs
    def Cal(self):
        self.Out = self.Model.Point[self.Out_state]

        # Collect and validate inlet data
        mass_in = 0.0
        energy_in = 0.0
        inlet_pressures = []
        
        for name in self.In_states:
            pt = self.Model.Point[name]
            
            if pt.Mass_flowrate is None or pt.H is None:
                raise ValueError(
                    f"Mixer {self.ID}: Mass flow or enthalpy for inlet '{name}' is missing"
                )
            if pt.Mass_flowrate < 0:
                raise ValueError(
                    f"Mixer {self.ID}: Negative mass flow for inlet '{name}'"
                )
            if pt.P is None:
                raise ValueError(
                    f"Mixer {self.ID}: Pressure for inlet '{name}' is missing"
                )
            
            mass_in += pt.Mass_flowrate
            energy_in += pt.Mass_flowrate * pt.H
            inlet_pressures.append(pt.P)

        if mass_in <= 0:
            raise ValueError(f"Mixer {self.ID}: Total inlet mass flow must be positive")

        # Calculate outlet enthalpy from energy balance
        h_out = energy_in / mass_in

        # Handle pressure - use minimum inlet pressure with optional loss
        P_min = min(inlet_pressures)
        P_max = max(inlet_pressures)
        
        # Warn if large pressure differences
        if (P_max - P_min) / P_max > self.PRESSURE_WARNING_THRESHOLD:
            warnings.warn(
                f"Mixer {self.ID}: Inlet pressures vary significantly "
                f"({P_min/1e5:.2f} - {P_max/1e5:.2f} bar). Using minimum."
            )
        
        # Apply pressure loss
        P_out = P_min * (1.0 - self.pressure_loss_fraction)
        
        # Use calculated pressure if outlet pressure not specified
        if self.Out.P is None:
            self.Out.P = P_out
        else:
            # If specified, check consistency
            if abs(self.Out.P - P_out) / P_out > 0.01:  # 1% tolerance
                warnings.warn(
                    f"Mixer {self.ID}: Specified outlet pressure ({self.Out.P/1e5:.2f} bar) "
                    f"differs from expected ({P_out/1e5:.2f} bar)"
                )

        # Validate outlet enthalpy if already set
        if self.Out.H is not None:
            if abs(self.Out.H - h_out) > self.TOLERANCE_ENTHALPY:
                raise ValueError(
                    f"Mixer {self.ID}: Outlet enthalpy mismatch. "
                    f"Given: {self.Out.H:.2f} J/kg, Calculated: {h_out:.2f} J/kg"
                )

        # Create/update outlet state
        self.Out = self.Model.Prop(
            self.Out.fluid,
            StatePointName=self.Out.StatePointName,
            P=self.Out.P, H=h_out,
            Mass_flowrate=mass_in
        )

        # Calculate exergy destruction
        try:
            ex_in = sum(self.Model.Point[s].Ex for s in self.In_states)
            ex_out = self.Out.Ex
            self.Ex_D = ex_in - ex_out
        except (AttributeError, TypeError):
            self.Ex_D = None

        self.Solution_Status = True
        self.Model.Point[self.Out_state] = self.Out

    def __str__(self):
        inlet_flows = ", ".join([
            f"{self.Model.Point[s].Mass_flowrate:.4f}" 
            for s in self.In_states
        ])
        return (
            f"{self.ID} (Mixer):\n"
            f"  Inlet flows    : [{inlet_flows}] kg/s\n"
            f"  Total outlet   : {self.Out.Mass_flowrate:.4f} kg/s\n"
            f"  Outlet H       : {self.Out.H:.2f} J/kg\n"
            f"  Outlet P       : {self.Out.P/1e5:.2f} bar\n"
            f"  Exergy destr.  : {self.Ex_D}\n"
            f"  Solved         : {self.Solution_Status}"
        )


# ================================================================== #
#   SPLITTER
# ================================================================== #
class Splitter(Component):
    """Splits one inlet stream into multiple outlet streams"""
    
    TOLERANCE_FRACTION_SUM = 1e-5

    def __init__(self, Model, ID, In_state, Out_states,
                 split_fractions, Calculate=False):
        """
        Args:
            split_fractions: List of fractions for each outlet (must sum to ~1.0)
        """
        if not Out_states or len(Out_states) < 2:
            raise ValueError(f"Splitter {ID}: Requires at least 2 outlet states")
            
        if len(Out_states) != len(split_fractions):
            raise ValueError(
                f"Splitter {ID}: Number of outlets ({len(Out_states)}) must match "
                f"number of split fractions ({len(split_fractions)})"
            )
        
        self.In_state = In_state
        self.Out_states = Out_states
        self.split_fractions = list(split_fractions)
        super().__init__(Model, ID, Calculate)

    @validate_inputs
    def Cal(self):
        self.In = self.Model.Point[self.In_state]

        # Validation
        if self.In.Mass_flowrate is None or self.In.H is None:
            raise ValueError(f"Splitter {self.ID}: Inlet data is incomplete")
        if self.In.Mass_flowrate <= 0:
            raise ValueError(f"Splitter {self.ID}: Inlet mass flow must be positive")
        if self.In.P is None:
            raise ValueError(f"Splitter {self.ID}: Inlet pressure is missing")

        # Normalize fractions if they don't sum to 1
        total = sum(self.split_fractions)
        if abs(total - 1.0) > self.TOLERANCE_FRACTION_SUM:
            warnings.warn(
                f"Splitter {self.ID}: Split fractions sum to {total:.6f}, "
                f"normalizing to 1.0"
            )
            self.split_fractions = [f / total for f in self.split_fractions]

        # Validate individual fractions
        for i, frac in enumerate(self.split_fractions):
            if frac < 0:
                raise ValueError(
                    f"Splitter {self.ID}: Negative split fraction at outlet {i}"
                )
            if frac > 1:
                raise ValueError(
                    f"Splitter {self.ID}: Split fraction > 1 at outlet {i}"
                )

        # Create outlet states (isenthalpic, isobaric split)
        for i, name in enumerate(self.Out_states):
            m_out = self.In.Mass_flowrate * self.split_fractions[i]
            pt = self.Model.Prop(
                self.In.fluid,
                StatePointName=name,
                P=self.In.P,
                H=self.In.H,
                Mass_flowrate=m_out
            )
            self.Model.Point[name] = pt

        # No exergy destruction in ideal splitter
        self.Ex_D = 0
        self.Solution_Status = True

    def __str__(self):
        outlet_flows = ", ".join([
            f"{self.Model.Point[s].Mass_flowrate:.4f}" 
            for s in self.Out_states
        ])
        return (
            f"{self.ID} (Splitter):\n"
            f"  Inlet mass flow  : {self.In.Mass_flowrate:.4f} kg/s\n"
            f"  Split fractions  : {[f'{x:.4f}' for x in self.split_fractions]}\n"
            f"  Outlet flows     : [{outlet_flows}] kg/s\n"
            f"  Exergy destr.    : {self.Ex_D}\n"
            f"  Solved           : {self.Solution_Status}"
        )


# ================================================================== #
#   SEPARATOR  (Flash Drum)
# ================================================================== #
class Separator(Component):
    """Separates two-phase mixture into vapor and liquid streams"""

    def __init__(self, Model, ID, In_state,
                 Out_vap_state, Out_liq_state, Calculate=False):
        self.In_state = In_state
        self.Out_vap_state = Out_vap_state
        self.Out_liq_state = Out_liq_state
        super().__init__(Model, ID, Calculate)

    @validate_inputs
    def Cal(self):
        self.In = self.Model.Point[self.In_state]
        self.Out_vap = self.Model.Point[self.Out_vap_state]
        self.Out_liq = self.Model.Point[self.Out_liq_state]

        # Validation
        if self.In.Mass_flowrate is None or self.In.H is None:
            raise ValueError(f"Separator {self.ID}: Inlet data is incomplete")
        if self.In.Mass_flowrate <= 0:
            raise ValueError(f"Separator {self.ID}: Inlet mass flow must be positive")
        if self.In.P is None:
            raise ValueError(f"Separator {self.ID}: Inlet pressure is missing")

        # Check inlet quality (must be two-phase)
        quality = self.In.Q
        if quality is None:
            raise ValueError(
                f"Separator {self.ID}: Inlet quality is None. "
                f"Inlet must be in two-phase region."
            )
        if not (0 < quality < 1):
            raise ValueError(
                f"Separator {self.ID}: Inlet quality = {quality:.4f}. "
                f"Must be between 0 and 1 (two-phase)."
            )

        P = self.In.P
        m_total = self.In.Mass_flowrate
        m_vap = m_total * quality
        m_liq = m_total * (1.0 - quality)

        # Create saturated vapor outlet (Q=1)
        self.Out_vap = self.Model.Prop(
            self.In.fluid,
            StatePointName=self.Out_vap_state,
            P=P, Q=1.0,
            Mass_flowrate=m_vap
        )
        
        # Create saturated liquid outlet (Q=0)
        self.Out_liq = self.Model.Prop(
            self.In.fluid,
            StatePointName=self.Out_liq_state,
            P=P, Q=0.0,
            Mass_flowrate=m_liq
        )

        # Energy balance check
        h_in = self.In.H
        h_out_mixed = (m_vap * self.Out_vap.H + m_liq * self.Out_liq.H) / m_total
        if abs(h_in - h_out_mixed) > 1.0:  # 1 J/kg tolerance
            warnings.warn(
                f"Separator {self.ID}: Energy balance error. "
                f"ΔH = {abs(h_in - h_out_mixed):.2f} J/kg"
            )

        # Calculate exergy destruction
        try:
            self.Ex_D = self.In.Ex - (self.Out_vap.Ex + self.Out_liq.Ex)
        except (AttributeError, TypeError):
            self.Ex_D = None

        self.Solution_Status = True
        self.Model.Point[self.Out_vap_state] = self.Out_vap
        self.Model.Point[self.Out_liq_state] = self.Out_liq

    def __str__(self):
        return (
            f"{self.ID} (Separator):\n"
            f"  Inlet flow       : {self.In.Mass_flowrate:.4f} kg/s (Q={self.In.Q:.4f})\n"
            f"  Vapor outlet     : {self.Out_vap.Mass_flowrate:.4f} kg/s\n"
            f"  Liquid outlet    : {self.Out_liq.Mass_flowrate:.4f} kg/s\n"
            f"  Pressure         : {self.In.P/1e5:.2f} bar\n"
            f"  Exergy destr.    : {self.Ex_D}\n"
            f"  Solved           : {self.Solution_Status}"
        )


# ================================================================== #
#   PIPE
# ================================================================== #
class Pipe(Component):
    """Pipe with pressure and temperature drops"""
    
    TOLERANCE_PRESSURE = 1e3      # Pa
    TOLERANCE_TEMPERATURE = 0.1   # K

    def __init__(self, Model, ID, In_state, Out_state,
                 Pressure_drop=0, Temperature_drop=0, Calculate=False):
        """
        Args:
            Pressure_drop: Pressure drop in Pa (positive = pressure decreases)
            Temperature_drop: Temperature drop in K (positive = temperature decreases)
        """
        self.In_state = In_state
        self.Out_state = Out_state
        self.Pressure_drop = Pressure_drop
        self.Temperature_drop = Temperature_drop
        super().__init__(Model, ID, Calculate)

    @validate_inputs
    def Cal(self):
        self.In = self.Model.Point[self.In_state]
        self.Out = self.Model.Point[self.Out_state]
        
        # Resolve mass flow rate
        mass, deffult = self._resolve_mass_flowrate(self.In, self.Out)
        self.In.Mass_flowrate = self.Model.Point[self.In_state].Mass_flowrate = mass
        self.Out.Mass_flowrate = self.Model.Point[self.Out_state].Mass_flowrate = mass

        # ===== PRESSURE SOLVER =====
        # Need at least 2 of: P_in, P_out, ΔP
        known_P_count = sum([
            self.In.P is not None,
            self.Out.P is not None,
            self.Pressure_drop != 0
        ])
        
        if known_P_count < 2:
            raise ValueError(
                f"Pipe {self.ID}: Need at least 2 of (P_in, P_out, Pressure_drop)"
            )
        
        if self.In.P is None:
            self.In.P = self.Out.P + self.Pressure_drop
        elif self.Out.P is None:
            self.Out.P = self.In.P - self.Pressure_drop
        else:  # Both pressures known
            calculated_drop = self.In.P - self.Out.P
            if self.Pressure_drop == 0:
                self.Pressure_drop = calculated_drop
            elif abs(calculated_drop - self.Pressure_drop) > self.TOLERANCE_PRESSURE:
                raise ValueError(
                    f"Pipe {self.ID}: Pressure inconsistency. "
                    f"Specified drop: {self.Pressure_drop/1e5:.3f} bar, "
                    f"Calculated: {calculated_drop/1e5:.3f} bar"
                )
        
        # Validate positive pressures
        if self.In.P < 0 or self.Out.P < 0:
            raise ValueError(
                f"Pipe {self.ID}: Negative pressure encountered "
                f"(P_in={self.In.P/1e5:.2f}, P_out={self.Out.P/1e5:.2f} bar)"
            )

        # ===== TEMPERATURE SOLVER =====
        # Need at least 2 of: T_in, T_out, ΔT
        known_T_count = sum([
            self.In.T is not None,
            self.Out.T is not None,
            self.Temperature_drop != 0
        ])
        
        if known_T_count < 2:
            raise ValueError(
                f"Pipe {self.ID}: Need at least 2 of (T_in, T_out, Temperature_drop)"
            )
        
        if self.In.T is None:
            self.In.T = self.Out.T + self.Temperature_drop
        elif self.Out.T is None:
            self.Out.T = self.In.T - self.Temperature_drop
        else:  # Both temperatures known
            calculated_drop = self.In.T - self.Out.T
            if self.Temperature_drop == 0:
                self.Temperature_drop = calculated_drop
            elif abs(calculated_drop - self.Temperature_drop) > self.TOLERANCE_TEMPERATURE:
                raise ValueError(
                    f"Pipe {self.ID}: Temperature inconsistency. "
                    f"Specified drop: {self.Temperature_drop:.2f} K, "
                    f"Calculated: {calculated_drop:.2f} K"
                )

        # Calculate exergy destruction
        try:
            self.Ex_D = self.In.Ex - self.Out.Ex
            if self.Ex_D < 0:
                warnings.warn(
                    f"Pipe {self.ID}: Negative exergy destruction ({self.Ex_D:.2f} W). "
                    f"Check dead state definition."
                )
        except (AttributeError, TypeError):
            self.Ex_D = None

        self.Solution_Status = True
        self._update_model_points(In_state=self.In, Out_state=self.Out)

    def __str__(self):
        return (
            f"{self.ID} (Pipe):\n"
            f"  P_in  → P_out  : {self.In.P/1e5:.2f} → {self.Out.P/1e5:.2f} bar "
            f"(ΔP = {self.Pressure_drop/1e5:.3f} bar)\n"
            f"  T_in  → T_out  : {self.In.T:.2f} → {self.Out.T:.2f} K "
            f"(ΔT = {self.Temperature_drop:.2f} K)\n"
            f"  Mass flow      : {self.In.Mass_flowrate:.4f} kg/s\n"
            f"  Exergy destr.  : {self.Ex_D}\n"
            f"  Solved         : {self.Solution_Status}"
        )


# ================================================================== #
#   EXPANSION VALVE
# ================================================================== #
class Expansion_valve(Component):
    """Isenthalpic expansion device (throttling valve)"""
    
    TOLERANCE_ENTHALPY = 1.0  # J/kg

    def __init__(self, Model, ID, In_state, Out_state, Calculate=False):
        self.In_state = In_state
        self.Out_state = Out_state
        super().__init__(Model, ID, Calculate)

    @validate_inputs
    def Cal(self):
        self.In = self.Model.Point[self.In_state]
        self.Out = self.Model.Point[self.Out_state]
        
        # Resolve mass flow rate
        mass, default = self._resolve_mass_flowrate(self.In, self.Out)
        self.In.Mass_flowrate = self.Model.Point[self.In_state].Mass_flowrate = mass
        self.Out.Mass_flowrate = self.Model.Point[self.Out_state].Mass_flowrate = mass
        # Validate pressures exist
        if self.In.P is None and self.Out.P is None:
            raise ValueError(
                f"Expansion_valve {self.ID}: At least one pressure must be specified"
            )
        
        if self.In.P is not None and self.Out.P is not None:
            if self.In.P <= self.Out.P:
                warnings.warn(
                    f"Expansion_valve {self.ID}: Outlet pressure ({self.Out.P/1e5:.2f} bar) "
                    f"is not less than inlet pressure ({self.In.P/1e5:.2f} bar)"
                )

        # ===== ISENTHALPIC PROCESS (H_in = H_out) =====
        if self.In.H is None and self.Out.H is None:
            raise ValueError(
                f"Expansion_valve {self.ID}: At least one enthalpy must be known"
            )
        
        if self.In.H is None:
            # Calculate inlet from outlet
            if self.In.P is None:
                raise ValueError(
                    f"Expansion_valve {self.ID}: Cannot determine inlet state. "
                    f"Need P_in when H_in is unknown"
                )
            self.In = self.Model.Prop(
                self.In.fluid,
                StatePointName=self.In.StatePointName,
                P=self.In.P, H=self.Out.H,
                Mass_flowrate=mass
            )
            
        elif self.Out.H is None:
            # Calculate outlet from inlet
            if self.Out.P is None:
                raise ValueError(
                    f"Expansion_valve {self.ID}: Cannot determine outlet state. "
                    f"Need P_out when H_out is unknown"
                )
            self.Out = self.Model.Prop(
                self.Out.fluid,
                StatePointName=self.Out.StatePointName,
                P=self.Out.P, H=self.In.H,
                Mass_flowrate=mass
            )
            
        else:
            # Both enthalpies specified - check consistency
            if abs(self.In.H - self.Out.H) > self.TOLERANCE_ENTHALPY:
                raise ValueError(
                    f"Expansion_valve {self.ID}: Enthalpy mismatch in isenthalpic process. "
                    f"H_in = {self.In.H:.2f} J/kg, H_out = {self.Out.H:.2f} J/kg, "
                    f"ΔH = {abs(self.In.H - self.Out.H):.2f} J/kg"
                )

        # Calculate exergy destruction (should be positive for irreversible throttling)
        try:
            self.Ex_D = self.In.Ex - self.Out.Ex
            if self.Ex_D < 0:
                warnings.warn(
                    f"Expansion_valve {self.ID}: Negative exergy destruction ({self.Ex_D:.2f} W)"
                )
        except (AttributeError, TypeError):
            self.Ex_D = None

        self.Solution_Status = True
        self._update_model_points(In_state=self.In, Out_state=self.Out)

    def __str__(self):
        h_avg = (self.In.H + self.Out.H) / 2 if self.In.H and self.Out.H else None
        return (
            f"{self.ID} (Expansion Valve):\n"
            f"  P_in  → P_out  : {self.In.P/1e5:.2f} → {self.Out.P/1e5:.2f} bar "
            f"(ΔP = {(self.In.P - self.Out.P)/1e5:.3f} bar)\n"
            f"  Enthalpy       : {h_avg:.2f} J/kg (isenthalpic)\n"
            f"  Mass flow      : {self.In.Mass_flowrate:.4f} kg/s\n"
            f"  Exergy destr.  : {self.Ex_D}\n"
            f"  Solved         : {self.Solution_Status}"
        )


# ================================================================== #
#   COMPONENT TOLERANCE CONFIGURATION
# ================================================================== #
class ComponentConfig:
    """Global configuration for component tolerances"""
    
    @staticmethod
    def set_tolerances(**kwargs):
        """
        Set tolerances for all components.
        
        Example:
            ComponentConfig.set_tolerances(
                pressure=1e4,           # 10 kPa
                temperature=0.5,        # 0.5 K
                enthalpy=10.0           # 10 J/kg
            )
        """
        mapping = {
            'pressure': ['Pipe'],
            'temperature': ['Pipe'],
            'enthalpy': ['Mixer', 'Expansion_valve'],
            'fraction_sum': ['Splitter']
        }
        
        for param, value in kwargs.items():
            if param in mapping:
                for component_name in mapping[param]:
                    component_class = globals()[component_name]
                    attr_name = f'TOLERANCE_{param.upper()}'
                    if hasattr(component_class, attr_name):
                        setattr(component_class, attr_name, value)
                        print(f"Set {component_name}.{attr_name} = {value}")
            else:
                warnings.warn(f"Unknown tolerance parameter: {param}")