"""Phaxor — Unit Converter Engine (Python port)"""

import math

CONVERSION_DB = {
    'length': {
        'm': 1, 'km': 1000, 'cm': 0.01, 'mm': 0.001, 'um': 1e-6, 'nm': 1e-9,
        'in': 0.0254, 'ft': 0.3048, 'yd': 0.9144, 'mi': 1609.344,
        'nmi': 1852, 'mil': 0.0000254, 'angstrom': 1e-10,
    },
    'area': {
        'm²': 1, 'km²': 1e6, 'cm²': 1e-4, 'mm²': 1e-6,
        'in²': 0.00064516, 'ft²': 0.09290304, 'yd²': 0.83612736,
        'acre': 4046.8564224, 'hectare': 10000,
    },
    'volume': {
        'm³': 1, 'L': 0.001, 'mL': 1e-6, 'cm³': 1e-6, 'mm³': 1e-9,
        'in³': 1.6387064e-5, 'ft³': 0.028316846592,
        'gal_us': 0.003785411784, 'gal_uk': 0.00454609,
    },
    'mass': {
        'kg': 1, 'g': 0.001, 'mg': 1e-6, 'lb': 0.45359237, 'oz': 0.028349523125,
        'ton_metric': 1000, 'ton_short': 907.18474,
    },
    'speed': {
        'm/s': 1, 'km/h': 1/3.6, 'mi/h': 0.44704, 'ft/s': 0.3048, 'knot': 0.514444,
    },
    'force': {
        'N': 1, 'kN': 1000, 'MN': 1e6, 'lbf': 4.44822, 'kgf': 9.80665,
    },
    'pressure': {
        'Pa': 1, 'kPa': 1000, 'MPa': 1e6, 'GPa': 1e9,
        'bar': 1e5, 'atm': 101325, 'psi': 6894.757,
    },
    'energy': {
        'J': 1, 'kJ': 1000, 'MJ': 1e6, 'cal': 4.184, 'kcal': 4184,
        'Wh': 3600, 'kWh': 3.6e6, 'BTU': 1055.06,
    },
    'power': {
        'W': 1, 'kW': 1000, 'MW': 1e6, 'hp': 745.7, 'BTU/h': 0.29307107,
    },
    'torque': {
        'N·m': 1, 'kN·m': 1000, 'lbf·ft': 1.35582, 'lbf·in': 0.112985,
    },
    'angle': {
        'rad': 1, 'deg': math.pi / 180, 'grad': math.pi / 200,
        'rev': 2 * math.pi,
    },
}


def _convert_temperature(value: float, from_unit: str, to_unit: str):
    """Convert temperature between C, F, K, R."""
    if from_unit == 'C': K = value + 273.15
    elif from_unit == 'F': K = (value - 32) * 5/9 + 273.15
    elif from_unit == 'K': K = value
    elif from_unit == 'R': K = value * 5/9
    else: return None

    if to_unit == 'C': return K - 273.15
    elif to_unit == 'F': return (K - 273.15) * 9/5 + 32
    elif to_unit == 'K': return K
    elif to_unit == 'R': return K * 9/5
    return None


def convert_unit(inputs: dict) -> dict | None:
    """Convert a value between units within the same category."""
    category = inputs.get('category', '')
    value = inputs.get('value', 0)
    from_unit = inputs.get('fromUnit', '')
    to_unit = inputs.get('toUnit', '')

    if category == 'temperature':
        result = _convert_temperature(value, from_unit, to_unit)
        return {'value': result, 'fromUnit': from_unit, 'toUnit': to_unit, 'category': category} if result is not None else None

    cat = CONVERSION_DB.get(category)
    if not cat:
        return None

    f_from = cat.get(from_unit)
    f_to = cat.get(to_unit)
    if f_from is None or f_to is None:
        return None

    return {'value': (value * f_from) / f_to, 'fromUnit': from_unit, 'toUnit': to_unit, 'category': category}


def get_categories() -> list:
    return list(CONVERSION_DB.keys()) + ['temperature']


def get_units(category: str) -> list:
    if category == 'temperature':
        return ['C', 'F', 'K', 'R']
    return list(CONVERSION_DB.get(category, {}).keys())
