"""Phaxor — CSTR Engine (Python port)"""
import math

def solve_cstr(inputs: dict) -> dict | None:
    """CSTR Design Calculator."""
    ca0 = float(inputs.get('cA0', 0))
    k = float(inputs.get('k', 0))
    order = str(inputs.get('order', '1'))
    flow = float(inputs.get('flowRate', 0))
    x_target = float(inputs.get('targetX', 0))

    if ca0 <= 0 or k <= 0 or flow <= 0 or x_target <= 0 or x_target >= 1:
        return None

    def rate_at(x):
        ca = ca0 * (1.0 - x)
        if order == '0': return k
        if order == '1': return k * ca
        if order == '2': return k * ca * ca
        return k * ca

    ra_exit = rate_at(x_target)
    if ra_exit == 0: return None

    # tau = cA0 * X / (-rA)
    tau = ca0 * x_target / ra_exit
    vol = flow * tau
    ca_exit = ca0 * (1.0 - x_target)

    levenspiel_data = []
    xx = 0.0
    while xx <= 0.99:
        r = rate_at(xx)
        if r > 1e-12:
            levenspiel_data.append({
                'X': float(f"{xx:.2f}"), 
                'invR': float(f"{ca0/r:.4f}")
            })
        xx += 0.02

    vol_data = []
    max_v = vol * 2.0
    step_v = max_v / 50.0
    vv = 0.0
    while vv <= max_v + 1e-9:
        tau_v = vv / flow
        xv = 0.0
        
        if order == '0':
            xv = min(k * tau_v / ca0, 1.0)
        elif order == '1':
            xv = k * tau_v / (1.0 + k * tau_v)
        elif order == '2':
            # Kt * X^2 - (2Kt + 1)X + Kt = 0
            Kt = k * ca0 * tau_v
            if Kt > 0:
                b = -(2 * Kt + 1)
                disc = b*b - 4*Kt*Kt
                if disc >= 0:
                    xv = (-b - math.sqrt(disc)) / (2 * Kt)
            else:
                xv = 0
        
        vol_data.append({'V': float(f"{vv:.2f}"), 'X': float(f"{max(0, min(xv, 0.999)):.4f}")})
        vv += step_v

    return {
        'V': float(f"{vol:.2f}"),
        'tau': float(f"{tau:.2f}"),
        'cA_exit': float(f"{ca_exit:.4f}"),
        'rA_exit': ra_exit,
        'levenspielData': levenspiel_data,
        'volData': vol_data
    }
