"""Phaxor — Fatigue Life Engine (Python port)"""
import math

def solve_fatigue_life(inputs: dict) -> dict | None:
    """Fatigue Life Calculator."""
    sa = float(inputs.get('sigmaA', 0))
    sm = float(inputs.get('sigmaM', 0))
    sf = float(inputs.get('sigmaF', 0))
    b = float(inputs.get('b', -0.1))
    su = float(inputs.get('sigmaUlt', 0))

    if sa <= 0 or sf <= 0 or su <= 0:
        return None

    sa_goodman = sa / (1 - sm / su) if (1 - sm / su) != 0 else float('inf')
    
    sm_ratio = sm / su
    sa_gerber = sa / (1 - sm_ratio * sm_ratio) if (1 - sm_ratio * sm_ratio) != 0 else float('inf')

    sy = su * 0.5
    sa_soderberg = sa / (1 - sm / sy) if (1 - sm / sy) != 0 else float('inf')

    def solve_nf(stress_amp):
        if stress_amp <= 0 or (stress_amp / sf) <= 0: return 0.0
        try:
            return (stress_amp / sf) ** (1.0 / b) / 2.0
        except (ValueError, ZeroDivisionError):
            return 0.0

    nf_nomean = solve_nf(sa)
    nf_goodman = solve_nf(sa_goodman)
    nf_gerber = solve_nf(sa_gerber)

    se_1e6 = sf * ((2 * 1e6) ** b)
    safety_factor = se_1e6 / sa_goodman if sa_goodman > 0 else 0.0

    return {
        'saGoodman': float(f"{sa_goodman:.2f}"),
        'saGerber': float(f"{sa_gerber:.2f}"),
        'saSoderberg': float(f"{sa_soderberg:.2f}"),
        'Nf_noMean': nf_nomean,
        'Nf_goodman': nf_goodman,
        'Nf_gerber': nf_gerber,
        'safetyFactor': float(f"{safety_factor:.2f}")
    }
