# Use the existing connected PyFluent variable solver.
import math

task_directory = r"C:\Users\13977\AppData\Local\FluentAGI\data\runs\20261018-142547-90d0a4"
s = solver.settings

def checked(label, result):
    print(label, result)
    if isinstance(result, dict):
        if result.get("status") in ("error", "failed", "needs_review"):
            raise RuntimeError(str(result))
        if result.get("error") or result.get("errors"):
            raise RuntimeError(str(result))
    return result

def numbers(value):
    if isinstance(value, bool):
        return []
    if isinstance(value, (int, float)):
        return [float(value)]
    if isinstance(value, dict):
        return [number for child in value.values() for number in numbers(child)]
    if isinstance(value, (list, tuple)):
        return [number for child in value for number in numbers(child)]
    return []

def value_of(result, name):
    if isinstance(result, dict):
        if name in result:
            values = numbers(result[name])
            if values and math.isfinite(values[0]):
                return values[0]
        children = result.values()
    elif isinstance(result, (list, tuple)):
        children = result
    else:
        children = []
    for child in children:
        try:
            return value_of(child, name)
        except ValueError:
            pass
    raise ValueError("无法提取报告：" + name + "；返回：" + str(result))

if not s.setup.models.is_active():
    raise RuntimeError("当前网格未激活。")

reports = s.solution.report_definitions
if not reports.compute.is_active():
    raise RuntimeError("当前解报告不可用，停止并保留结果。")

print("CURRENT_SOLVER", s.setup.general.solver.get_state())
run = s.solution.run_calculation
if run.transient_controls.is_active():
    print("TRANSIENT_CONTROLS", run.transient_controls.get_state())

force_names = ["front_wing_drag_interface", "front_wing_lift_interface"]
for name in force_names:
    if name not in reports.force.get_object_names():
        raise RuntimeError("缺少已配置受力报告：" + name)

wing_zones = reports.force[force_names[0]].zones.get_state()
lift_zones = reports.force[force_names[1]].zones.get_state()
if not wing_zones or set(wing_zones) != set(lift_zones):
    raise RuntimeError("升阻力统计区域为空或不一致。")

force_result = reports.compute(report_defs=force_names)
drag, lift = [value_of(force_result, name) for name in force_names]
denominator = 0.5 * 1.225 * 30.0**2 * 0.552
print("AERODYNAMIC_READBACK", {
    "drag": drag,
    "lift": lift,
    "downforce": -lift,
    "CD": drag / denominator,
    "CL": lift / denominator,
    "reference_area": 0.552,
})

mass_names = ["fw_inlet_mass", "fw_outlet_mass"]
if all(name in reports.surface.get_object_names() for name in mass_names):
    result = reports.compute(report_defs=mass_names)
    mass_values = [value_of(result, name) for name in mass_names]
    scale = max(max(abs(value) for value in mass_values), 1e-20)
    print("MASS_BALANCE_READBACK", {
        "inlet": mass_values[0],
        "outlet": mass_values[1],
        "relative_imbalance": abs(sum(mass_values)) / scale,
    })

paths = s.results.graphics.pathline
if not paths.is_active():
    raise RuntimeError("当前原生流线对象不可用。")
path_name = "front_wing_streamlines"
if path_name not in paths.get_object_names():
    paths[path_name] = {}
path = paths[path_name]

try:
    if not path.field.is_active():
        raise RuntimeError("流线着色字段未激活。")
    if "velocity-magnitude" not in path.field.allowed_values():
        raise RuntimeError("流线速度着色字段不可用。")
    path.field = "velocity-magnitude"
    path.release_from_surfaces = ["inlet"]
    print("STREAMLINE_READBACK", {
        "field": path.field.get_state(),
        "release_from_surfaces": path.release_from_surfaces.get_state(),
    })
    for name in ["step", "skip", "options", "accuracy_control"]:
        child = getattr(path, name)
        if child.is_active():
            print("STREAMLINE_CONTROL", name, child.get_state())

    views = s.results.graphics.views
    views.restore_view(view_name="isometric")
    paths.display(object_name=path_name)
    views.auto_scale()

    picture = s.results.graphics.picture
    if "save_picture" not in getattr(picture, "command_names", []):
        raise RuntimeError("原生图片保存命令不可用。")
    command = picture.save_picture
    if "file_name" not in getattr(command, "argument_names", []):
        raise RuntimeError("图片保存命令参数不匹配。")
    file_name = task_directory + r"\front_wing_streamlines.png"
    print("STREAMLINE_SAVE_RESULT", command(file_name=file_name))
    print("STREAMLINE_SAVE_PATH", file_name)

    checked(
        "WING_SURFACE_EXPORT",
        fluentagi.export_results(
            directory=task_directory,
            fields=["pressure", "velocity-magnitude"],
            surfaces=wing_zones,
        ),
    )
finally:
    s.file.write_case_data(
        file_name=task_directory + r"\front_wing_postprocessing_repair.cas.h5"
    )

print("POSTPROCESSING_SCOPE", {
    "initialized": False,
    "advanced_time_steps": 0,
    "streamlines": "instantaneous_velocity_field",
    "all_step_convergence_verified": False,
    "force_stability_verified": False,
    "mesh_independence_verified": False,
})