"""Phaxor — RCC Beam Design Engine (Python port)"""
import math

def solve_rcc_beam(inputs: dict) -> dict:
    b = float(inputs.get('b', 0))
    D = float(inputs.get('D', 0))
    cc = float(inputs.get('cc', 25))
    Mu = float(inputs.get('Mu', 0))
    fck = float(inputs.get('fck', 20))
    fy = float(inputs.get('fy', 415))
    bar_dia = float(inputs.get('barDia', 12))
    bar_dia_comp = float(inputs.get('barDiaComp', 16))
    d_eff = inputs.get('d_eff')
    
    Muv = Mu * 1e6 # N.mm
    stir_dia = 8
    
    if d_eff:
        d = float(d_eff)
    else:
        d = D - cc - stir_dia - bar_dia / 2
        
    if d <= 0:
        return {'error': "Effective depth is non-positive"}
        
    # IS 456
    if fy <= 250: xu_max_ratio = 0.53
    elif fy <= 415: xu_max_ratio = 0.48
    elif fy <= 500: xu_max_ratio = 0.46
    else: xu_max_ratio = 0.44
    
    xu_max = xu_max_ratio * d
    MuLim = 0.36 * fck * b * xu_max * (d - 0.42 * xu_max)
    
    Ast = 0
    Asc = 0
    xu = 0
    beam_type = 'singly'
    num_bars_comp = 0
    
    if Muv <= MuLim:
        beam_type = 'singly'
        discrim = d * d - (4.598 * Muv) / (fck * b)
        if discrim < 0:
            xu = xu_max # Fallback
        else:
            xu = (d - math.sqrt(discrim)) / 2
        Ast = Muv / (0.87 * fy * (d - 0.42 * xu)) if (d - 0.42 * xu) != 0 else 0
    else:
        beam_type = 'doubly'
        xu = xu_max
        Mu2 = Muv - MuLim
        dc = cc + stir_dia + bar_dia_comp / 2
        Ast1 = MuLim / (0.87 * fy * (d - 0.42 * xu_max)) if (d - 0.42 * xu_max) != 0 else 0
        fsc = 0.87 * fy
        Asc = Mu2 / (fsc * (d - dc)) if (d - dc) != 0 else 0
        Ast2 = Mu2 / (0.87 * fy * (d - dc)) if (d - dc) != 0 else 0
        Ast = Ast1 + Ast2
        
    # Min/Max steel
    AstMin = 0.85 * b * d / fy if fy != 0 else 0
    if Ast < AstMin: Ast = AstMin
    # AstMax check omitted in logic but calculated
    AstMax = 0.04 * b * D
    
    area_one_bar = math.pi * bar_dia * bar_dia / 4
    num_bars = math.ceil(Ast / area_one_bar) if area_one_bar > 0 else 0
    AstProvided = num_bars * area_one_bar
    
    if beam_type == 'doubly' and Asc > 0:
        area_one_bar_comp = math.pi * bar_dia_comp * bar_dia_comp / 4
        num_bars_comp = math.ceil(Asc / area_one_bar_comp) if area_one_bar_comp > 0 else 0
        
    pt = (AstProvided / (b * d)) * 100 if (b * d) > 0 else 0
    clear_spacing = 0
    if num_bars > 1:
        denom = num_bars - 1
        clear_spacing = (b - 2 * cc - 2 * stir_dia - num_bars * bar_dia) / denom
        
    tauC = 0.25 * math.sqrt(fck)
    Vu = tauC * b * d / 1000 # kN
    
    return {
        'result': {
            'beamType': beam_type,
            'd': d,
            'xu': xu,
            'xuMax': xu_max,
            'MuLim': MuLim / 1e6,
            'Ast': Ast,
            'AstProvided': AstProvided,
            'Asc': Asc,
            'numBars': num_bars,
            'numBarsComp': num_bars_comp,
            'pt': pt,
            'AstMin': AstMin,
            'AstMax': AstMax,
            'clearSpacing': clear_spacing,
            'Vu': Vu
        }
    }
