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

def solve_distillation(inputs: dict) -> dict | None:
    """McCabe-Thiele Distillation Calculator."""
    alpha = float(inputs.get('alpha', 0))
    x_d = float(inputs.get('xD', 0))
    x_b = float(inputs.get('xB', 0))
    x_f = float(inputs.get('xF', 0))
    q = float(inputs.get('q', 1))
    r_reflux = float(inputs.get('R', 0))

    if alpha <= 1 or x_d <= x_b or r_reflux <= 0:
        return None

    def y_eq(x):
        return (alpha * x) / (1.0 + (alpha - 1.0) * x)

    y_f_eq = y_eq(x_f)
    # Using the same simplified Rmin formula as TS/UI
    r_min = (x_d / y_f_eq - 1.0) / (1.0 - x_f / y_f_eq) if y_f_eq != x_f else 0 # Avoid div/0 if xf=yf (impossible for alpha>1)
    
    # Operating Lines
    slope_rect = r_reflux / (r_reflux + 1.0)
    int_rect = x_d / (r_reflux + 1.0)

    # Feed point intersection
    if abs(q - 1.0) < 0.001:
        x_feed = x_f
        y_feed = slope_rect * x_f + int_rect
    else:
        slope_q = q / (q - 1.0)
        int_q = -x_f / (q - 1.0)
        x_feed = (int_q - int_rect) / (slope_rect - slope_q)
        y_feed = slope_rect * x_feed + int_rect

    slope_strip = (y_feed - x_b) / (x_feed - x_b) if x_feed != x_b else 1.0

    # Stepping
    stages = []
    x = x_d
    n = 0
    feed_stage = 0

    while x > x_b and n < 100:
        y_curr = x
        x_new = y_curr / (alpha - (alpha - 1.0) * y_curr)
        n += 1

        y_rect = slope_rect * x_new + int_rect
        y_strip = slope_strip * (x_new - x_b) + x_b

        if x_new > x_feed:
            y_op = y_rect
        else:
            y_op = y_strip
            if feed_stage == 0:
                feed_stage = n
        
        stages.append({'x': float(f"{x_new:.4f}"), 'y': float(f"{y_op:.4f}"), 'n': n})
        x = max(x_b, y_op)

    # xy data generation
    xy_data = []
    xx = 0.0
    while xx <= 1.005:
        yy = y_eq(xx)
        op_r = slope_rect * xx + int_rect
        op_s = slope_strip * (xx - x_b) + x_b
        
        point = {
            'x': float(f"{xx:.3f}"),
            'eq': float(f"{yy:.4f}"),
            'diag': float(f"{xx:.3f}")
        }
        if xx > x_feed + 0.01:
            point['rect'] = float(f"{max(0, min(1, op_r)):.4f}")
        if xx < x_feed - 0.01:
            point['strip'] = float(f"{max(0, min(1, op_s)):.4f}")
            
        xy_data.append(point)
        xx += 0.01

    n_min = math.log((x_d / (1.0 - x_d)) * ((1.0 - x_b) / x_b)) / math.log(alpha)

    return {
        'totalStages': n,
        'feedStage': feed_stage or math.ceil(n / 2),
        'Rmin': float(f"{max(r_min, 0):.3f}"),
        'Nmin': float(f"{n_min:.2f}"),
        'xyData': xy_data,
        'xFeed': float(f"{x_feed:.3f}"),
        'yFeed': float(f"{y_feed:.3f}"),
        'slope_rect': float(f"{slope_rect:.4f}"),
        'intercept_rect': float(f"{int_rect:.4f}"),
        'stages': stages
    }
