"""
Safety Factor Constraint Hook - Manual Implementation

This hook enforces a minimum safety factor constraint on stress.
If safety_factor < minimum required, the objective is heavily penalized.

Safety Factor = Yield Strength / Max Stress

For Aluminum 6061-T6:
- Yield Strength: 276 MPa
- Required Safety Factor: 4.0
- Allowable Stress: 69 MPa

Author: Atomizer Development Team
Version: 1.0
"""

from optimization_engine.plugins.hooks import Hook, HookPoint


def safety_factor_constraint_hook(context: dict) -> dict:
    """
    Enforce safety factor constraint on optimization.

    This hook checks if the calculated safety factor meets the minimum requirement.
    If violated, it adds a large penalty to the objective to guide optimization
    away from unsafe designs.

    Args:
        context: Dict containing:
            - calculations: Dict with 'safety_factor' value
            - results: Dict with stress results

    Returns:
        Dict with:
            - safety_factor_satisfied: bool
            - safety_factor_violation: float (0 if satisfied, penalty otherwise)
            - constrained_objective: float (original or penalized objective)
    """
    calculations = context.get('calculations', {})

    # Get safety factor from calculations
    safety_factor = calculations.get('safety_factor', 0.0)

    # Get objective (negative displacement to maximize)
    neg_displacement = calculations.get('neg_displacement', 0.0)

    # Required minimum safety factor
    min_safety_factor = 4.0

    # Check constraint
    satisfied = safety_factor >= min_safety_factor

    # Calculate violation (how much we're under the limit)
    violation = max(0.0, min_safety_factor - safety_factor)

    # Apply penalty if constraint violated
    if not satisfied:
        # Heavy penalty: add large value to objective (we're minimizing)
        # Penalty scales with violation severity
        penalty = 1000.0 * violation
        constrained_objective = neg_displacement + penalty

        print(f"  [CONSTRAINT VIOLATED] Safety factor {safety_factor:.2f} < {min_safety_factor}")
        print(f"  [PENALTY APPLIED] Adding {penalty:.2f} to objective")
    else:
        constrained_objective = neg_displacement
        print(f"  [CONSTRAINT SATISFIED] Safety factor {safety_factor:.2f} >= {min_safety_factor}")

    return {
        'safety_factor_satisfied': satisfied,
        'safety_factor_violation': violation,
        'constrained_objective': constrained_objective,
        'objective': constrained_objective  # This becomes the final objective
    }


# Register hook with plugin system
hook = Hook(
    name="safety_factor_constraint",
    hook_point=HookPoint.POST_CALCULATION,
    function=safety_factor_constraint_hook,
    enabled=True,
    description="Enforce minimum safety factor constraint with penalty"
)


def register_hooks(hook_manager):
    """Register hooks with the plugin system."""
    return [hook]
