"""Phaxor — Battery & UPS Engine (Python port)"""
import math

def solve_battery_ups(inputs: dict) -> dict | None:
    """Battery & UPS Sizing Calculator."""
    loads = inputs.get('loads', [])
    backup_hours = float(inputs.get('backupHours', 2))
    inverter_eff = float(inputs.get('inverterEfficiency', 85))
    dod = float(inputs.get('depthOfDischarge', 50))
    bat_v = float(inputs.get('batteryVoltage', 12))
    bat_ah = float(inputs.get('batteryAh', 150))

    total_watt = 0
    for l in loads:
        total_watt += float(l.get('watt', 0)) * float(l.get('qty', 0))

    if total_watt <= 0:
        return None

    eff = inverter_eff / 100.0
    dod_val = dod / 100.0
    hrs = max(0.1, backup_hours)

    total_va = total_watt / 0.8
    ups_rating_va = math.ceil(total_va / 500.0) * 500.0
    ups_rating_kva = ups_rating_va / 1000.0

    wh_needed = total_watt * hrs
    wh_actual = wh_needed / (eff * dod_val)
    ah_needed = wh_actual / bat_v

    # UI Logic: forced 230V DC bus assumption?
    batteries_in_series = math.ceil(230.0 / bat_v)
    parallel_strings = math.ceil(ah_needed / bat_ah)

    total_batteries = batteries_in_series * parallel_strings
    total_ah = parallel_strings * bat_ah

    # Replicating UI logic for actual backup
    actual_backup = (total_ah * bat_v * eff * dod_val) / total_watt

    return {
        'totalWatt': float(f"{total_watt:.2f}"),
        'totalVA': float(f"{total_va:.2f}"),
        'upsRatingVA': float(f"{ups_rating_va:.2f}"),
        'upsRatingKVA': float(f"{ups_rating_kva:.2f}"),
        'ahNeeded': float(f"{ah_needed:.2f}"),
        'totalBatteries': int(total_batteries),
        'batteriesInSeries': int(batteries_in_series),
        'parallelStrings': int(parallel_strings),
        'totalAh': float(f"{total_ah:.2f}"),
        'actualBackup': float(f"{actual_backup:.2f}"),
        'whNeeded': float(f"{wh_needed:.2f}")
    }
