"""Phaxor — Cable Sizing Engine (Python port)"""
import math

# Cable data (Size, A-Conduit, B-Tray, C-Air, D-Buried, R-Ohm/km)
CABLE_TABLE = [
    {'size': 1.5, 'cu_a': 17.5, 'cu_b': 19.5, 'cu_c': 23, 'cu_d': 22, 'r': 12.1},
    {'size': 2.5, 'cu_a': 24, 'cu_b': 27, 'cu_c': 31, 'cu_d': 30, 'r': 7.41},
    {'size': 4, 'cu_a': 32, 'cu_b': 36, 'cu_c': 42, 'cu_d': 40, 'r': 4.61},
    {'size': 6, 'cu_a': 41, 'cu_b': 46, 'cu_c': 54, 'cu_d': 51, 'r': 3.08},
    {'size': 10, 'cu_a': 57, 'cu_b': 63, 'cu_c': 75, 'cu_d': 70, 'r': 1.83},
    {'size': 16, 'cu_a': 76, 'cu_b': 85, 'cu_c': 100, 'cu_d': 94, 'r': 1.15},
    {'size': 25, 'cu_a': 101, 'cu_b': 112, 'cu_c': 133, 'cu_d': 119, 'r': 0.727},
    {'size': 35, 'cu_a': 125, 'cu_b': 138, 'cu_c': 164, 'cu_d': 148, 'r': 0.524},
    {'size': 50, 'cu_a': 151, 'cu_b': 168, 'cu_c': 198, 'cu_d': 180, 'r': 0.387},
    {'size': 70, 'cu_a': 192, 'cu_b': 213, 'cu_c': 253, 'cu_d': 232, 'r': 0.268},
    {'size': 95, 'cu_a': 232, 'cu_b': 258, 'cu_c': 306, 'cu_d': 282, 'r': 0.193},
    {'size': 120, 'cu_a': 269, 'cu_b': 299, 'cu_c': 354, 'cu_d': 328, 'r': 0.153},
    {'size': 150, 'cu_a': 300, 'cu_b': 344, 'cu_c': 407, 'cu_d': 379, 'r': 0.124},
    {'size': 185, 'cu_a': 341, 'cu_b': 392, 'cu_c': 464, 'cu_d': 434, 'r': 0.0991},
    {'size': 240, 'cu_a': 400, 'cu_b': 461, 'cu_c': 546, 'cu_d': 514, 'r': 0.0754},
    {'size': 300, 'cu_a': 458, 'cu_b': 530, 'cu_c': 628, 'cu_d': 593, 'r': 0.0601},
]

def solve_cable_sizing(inputs: dict) -> dict | None:
    """Cable Sizing Calculator."""
    current = float(inputs.get('current', 0))
    length = float(inputs.get('length', 0))
    voltage = float(inputs.get('voltage', 0))
    phase = int(inputs.get('phase', 1))
    method = inputs.get('installMethod', 'tray')
    df = float(inputs.get('deratingFactor', 1))
    max_drop = float(inputs.get('maxDropPercent', 3))

    if current <= 0 or length <= 0 or voltage <= 0:
        return None

    df = max(0.01, df)
    iderated = current / df
    
    method_key = 'cu_b' # default tray
    if method == 'conduit': method_key = 'cu_a'
    elif method == 'buried': method_key = 'cu_d'
    elif method == 'air': method_key = 'cu_c'

    # Filter by ampacity
    suitable_by_amps = [c for c in CABLE_TABLE if c[method_key] >= iderated]
    
    phase_mult = math.sqrt(3) if phase == 3 else 2.0

    # Filter by voltage drop
    suitable_by_drop = []
    for c in CABLE_TABLE:
        v_drop = phase_mult * current * c['r'] * length / 1000.0
        drop_pct = (v_drop / voltage) * 100.0
        if drop_pct <= max_drop:
            suitable_by_drop.append(c)

    # Fallback to largest if empty
    by_amps = suitable_by_amps[0] if suitable_by_amps else CABLE_TABLE[-1]
    by_drop = suitable_by_drop[0] if suitable_by_drop else CABLE_TABLE[-1]

    if by_amps['size'] >= by_drop['size']:
        selected = by_amps
        reason = 'Current Rating'
    else:
        selected = by_drop
        reason = 'Voltage Drop'

    v_drop = phase_mult * current * selected['r'] * length / 1000.0
    drop_pct = (v_drop / voltage) * 100.0
    v_recv = voltage - v_drop

    if phase == 3:
        power_loss = 3 * current * current * selected['r'] * length / 1000.0
    else:
        power_loss = 2 * current * current * selected['r'] * length / 1000.0

    return {
        'selectedSize': float(selected['size']),
        'voltageDrop': float(f"{v_drop:.2f}"),
        'dropPercent': float(f"{drop_pct:.2f}"),
        'receivingVoltage': float(f"{v_recv:.2f}"),
        'powerLoss': float(f"{power_loss:.2f}"),
        'governingFactor': reason,
        'deratedCurrent': float(f"{iderated:.2f}"),
        'cableCapacity': float(selected[method_key])
    }
