"""Phaxor — Shaft Design Engine (Python port)"""
import math

def solve_shaft_design(inputs: dict) -> dict | None:
    """ASME Code for Transmission Shaft Design."""
    power = float(inputs.get('power', 0))
    rpm = float(inputs.get('rpm', 0))
    bending_moment = float(inputs.get('bendingMoment', 0))
    shaft_length = float(inputs.get('shaftLength', 0))
    sy = float(inputs.get('Sy', 0))
    sut = float(inputs.get('Sut', 0))
    e = float(inputs.get('E', 0))
    g = float(inputs.get('G', 0))
    kb = float(inputs.get('Kb', 1.5))
    kt = float(inputs.get('Kt', 1.0))
    fos_des = float(inputs.get('fos', 2.0))

    if rpm > 0:
        torque = (power * 1000 * 60) / (2 * math.pi * rpm)
    else:
        torque = 0
    
    m = bending_moment

    # ASME
    combined_asme = math.sqrt((kb * m) ** 2 + (kt * torque) ** 2)
    try:
        d_asme_m = ((16 * fos_des * combined_asme) / (math.pi * sy * 1e6)) ** (1/3)
    except ZeroDivisionError:
        d_asme_m = 0
    d_asme = d_asme_m * 1000

    # DE
    combined_de = math.sqrt((kb * m) ** 2 + 0.75 * (kt * torque) ** 2)
    try:
        d_de_m = ((32 * fos_des * combined_de) / (math.pi * sy * 1e6)) ** (1/3)
    except ZeroDivisionError:
        d_de_m = 0
    d_de = d_de_m * 1000

    # Tresca
    combined_tresca = math.sqrt((kb * m) ** 2 + (kt * torque) ** 2)
    try:
        d_tresca_m = ((32 * fos_des * combined_tresca) / (math.pi * sy * 1e6)) ** (1/3)
    except ZeroDivisionError:
        d_tresca_m = 0
    d_tresca = d_tresca_m * 1000

    d = d_asme / 1000
    
    sigma_bending = 0
    tau_torsion = 0
    von_mises = 0
    tresca = 0
    fos = 0
    critical_speed = 0
    angle_of_twist = 0

    if d > 0:
        i_val = (math.pi * d ** 4) / 64
        j_val = (math.pi * d ** 4) / 32
        c = d / 2

        sigma_bending = (m * c) / i_val / 1e6
        tau_torsion = (torque * c) / j_val / 1e6
        von_mises = math.sqrt(sigma_bending ** 2 + 3 * tau_torsion ** 2)
        tresca = 2 * math.sqrt((sigma_bending / 2) ** 2 + tau_torsion ** 2)

        if von_mises > 0:
            fos = sy / von_mises
        else:
            fos = 999

        rho = 7850
        area = (math.pi * d ** 2) / 4
        # Nc = (π/2L²) × √(E·I·g / (ρ·A)) * (60/2π)
        # Here term2 usually includes g if weight force is considered in deflection 
        # But standard formula for uniform shaft often simplifies ρA as mass per unit length.
        # Let's match TS exactly:
        if shaft_length > 0:
            term1 = math.pi / (2 * shaft_length ** 2)
            term2 = math.sqrt((e * 1e9 * i_val) / (rho * area))
            critical_speed = (term1 * term2) * (60 / (2 * math.pi))

        if g > 0:
            angle_of_twist = (torque * shaft_length) / (g * 1e9 * j_val) * (180 / math.pi)

    power_check = (2 * math.pi * rpm * torque) / (60 * 1000)

    return {
        'torque': float(f"{torque:.2f}"),
        'bendingMoment': m,
        'tauTorsion': float(f"{tau_torsion:.2f}"),
        'sigmaBending': float(f"{sigma_bending:.2f}"),
        'vonMises': float(f"{von_mises:.2f}"),
        'tresca': float(f"{tresca:.2f}"),
        'dASME': float(f"{d_asme:.2f}"),
        'dDE': float(f"{d_de:.2f}"),
        'dTresca': float(f"{d_tresca:.2f}"),
        'fos': float(f"{fos:.2f}"),
        'criticalSpeed': float(f"{critical_speed:.0f}"),
        'angleOfTwist': float(f"{angle_of_twist:.3f}"),
        'powerCheck': float(f"{power_check:.2f}")
    }
