"""Phaxor — Stress & Strain Engine (Python port)"""

import math

MATERIALS = {
    'steel-a36':        {'name': 'ASTM A36 Steel',     'E': 200,  'sigmaY': 250,  'sigmaUlt': 400,  'nu': 0.26, 'density': 7850, 'elongation': 20},
    'steel-a572':       {'name': 'ASTM A572 Gr.50',    'E': 200,  'sigmaY': 345,  'sigmaUlt': 450,  'nu': 0.27, 'density': 7850, 'elongation': 18},
    'stainless-304':    {'name': 'Stainless Steel 304', 'E': 193,  'sigmaY': 215,  'sigmaUlt': 505,  'nu': 0.29, 'density': 7900, 'elongation': 40},
    'aluminum-6061':    {'name': 'Aluminum 6061-T6',    'E': 68.9, 'sigmaY': 276,  'sigmaUlt': 310,  'nu': 0.33, 'density': 2700, 'elongation': 12},
    'copper':           {'name': 'Copper (C11000)',     'E': 117,  'sigmaY': 69,   'sigmaUlt': 220,  'nu': 0.34, 'density': 8960, 'elongation': 42},
    'titanium-ti6al4v': {'name': 'Ti-6Al-4V',          'E': 114,  'sigmaY': 880,  'sigmaUlt': 950,  'nu': 0.34, 'density': 4430, 'elongation': 14},
    'cast-iron':        {'name': 'Gray Cast Iron',     'E': 100,  'sigmaY': 130,  'sigmaUlt': 200,  'nu': 0.26, 'density': 7200, 'elongation': 0.5},
}


def calc_area(section_type: str, dims: dict) -> float:
    """Calculate cross-section area from geometry type."""
    if section_type == 'circular':
        return math.pi * dims.get('d', 0)**2 / 4
    elif section_type == 'rectangular':
        return dims.get('b', 0) * dims.get('h', 0)
    elif section_type == 'hollow-circular':
        D = dims.get('D', 0)
        di = dims.get('di', 0)
        return math.pi * (D**2 - di**2) / 4
    elif section_type == 'i-beam':
        return 2 * dims.get('bf', 0) * dims.get('tf', 0) + dims.get('hw', 0) * dims.get('tw', 0)
    return 0


def solve_stress_strain(inputs: dict) -> dict | None:
    """Uniaxial stress-strain analysis."""
    force = inputs.get('force', 0)
    area = inputs.get('area', 0)
    L0 = inputs.get('originalLength', 0)
    dL = inputs.get('changeInLength', 0)
    mat = inputs.get('material', MATERIALS['steel-a36'])

    if not force or not L0 or not area:
        return None

    stress = force / area
    strain = dL / L0
    E_calc = (stress / strain / 1000) if strain != 0 else 0
    shear = stress / 2
    lat_strain = -mat['nu'] * strain
    true_stress = stress * (1 + strain)
    true_strain = math.log(1 + strain) if strain != 0 else 0
    fos = mat['sigmaY'] / stress
    fos_ult = mat['sigmaUlt'] / stress
    strain_energy = 0.5 * stress * strain * area * L0 / 1000

    if stress < mat['sigmaY']:
        status = 'safe'
        status_text = f"ELASTIC — FoS: {fos:.2f}"
    elif stress < mat['sigmaUlt']:
        status = 'yield'
        status_text = f"YIELDING — exceeds σy ({mat['sigmaY']} MPa)"
    else:
        status = 'failure'
        status_text = f"FAILURE — exceeds σu ({mat['sigmaUlt']} MPa)"

    return {
        'stress': stress, 'strain': strain, 'youngsModCalc': E_calc,
        'shearStress': shear, 'lateralStrain': lat_strain,
        'trueStress': true_stress, 'trueStrain': true_strain,
        'fos': fos, 'fosUlt': fos_ult, 'strainEnergy': strain_energy,
        'status': status, 'statusText': status_text,
    }
