# -*- coding: utf-8 -*-
"""
煤矿配风计划 - 需风量计算工具模块

基于《煤矿安全规程》2025 版和 AQ 1056-2008《煤矿通风能力核定标准》，
实现各用风地点类型的需风量计算工具。

每个工具函数返回结构化 JSON，包含：
- formula: 计算公式（文字描述）
- expression: 计算表达式（含数值代入）
- steps: 计算步骤列表
- result: 计算结果
- unit: 单位

工具列表:
- 采煤工作面: calc_face_by_gas / calc_face_by_workers / calc_face_by_wind_speed / calc_face_air_volume_max
- 掘进工作面: calc_tunnel_by_gas / calc_tunnel_by_explosives / calc_tunnel_by_workers / calc_tunnel_by_wind_speed / calc_tunnel_by_vehicle / calc_tunnel_air_volume_max
- 硐室: calc_chamber_by_equipment / calc_chamber_by_wind_speed
- 其他巷道: calc_other_by_wind_speed
- 辅助: calc_effective_area / calc_total_air_volume
- 反算: calc_gas_emission_from_wind（从测风报表风量×浓度反算涌出量）
"""

import json


# ============================================================
# 辅助工具
# ============================================================

def calc_effective_area(max_control_distance: float,
                         min_control_distance: float,
                         avg_mining_height: float) -> str:
    """计算工作面有效断面积。

    公式: S = (L_max + L_min) / 2 × H
    其中 L_max 为最大控顶距，L_min 为最小控顶距，H 为平均采高。

    Args:
        max_control_distance: 最大控顶距，单位 m
        min_control_distance: 最小控顶距，单位 m
        avg_mining_height: 平均采高，单位 m

    Returns:
        JSON格式的计算过程与结果
    """
    avg_distance = (max_control_distance + min_control_distance) / 2
    area = avg_distance * avg_mining_height

    return json.dumps({
        "formula": "S = (L_max + L_min) / 2 × H",
        "expression": f"S = ({max_control_distance} + {min_control_distance}) / 2 × {avg_mining_height}",
        "steps": [
            f"平均控顶距 = ({max_control_distance} + {min_control_distance}) / 2 = {avg_distance:.2f} m",
            f"有效断面积 = {avg_distance:.2f} × {avg_mining_height} = {area:.2f} m²",
        ],
        "result": round(area, 2),
        "unit": "m²",
    }, ensure_ascii=False)


# ============================================================
# 采煤工作面需风量计算
# ============================================================

def calc_face_by_gas(q_gas: float, k_gas: float = 1.5) -> str:
    """按瓦斯涌出量计算采煤工作面需风量。

    公式: Q = 100 × q_gas × K_gas
    依据: 按瓦斯涌出量计算，K_gas 为瓦斯涌出不均衡系数（1.2~1.6）

    Args:
        q_gas: 平均绝对瓦斯涌出量，单位 m³/min
        k_gas: 瓦斯涌出不均衡系数，默认 1.5

    Returns:
        JSON格式的计算过程与结果
    """
    result = 100 * q_gas * k_gas

    return json.dumps({
        "formula": "Q_cf = 100 × q_gas × K_gas",
        "expression": f"Q_cf = 100 × {q_gas} × {k_gas}",
        "steps": [
            f"Q_cf = 100 × {q_gas} × {k_gas}",
            f"Q_cf = {100 * q_gas:.2f} × {k_gas}",
            f"Q_cf = {result:.2f} m³/min",
        ],
        "result": round(result, 2),
        "unit": "m³/min",
    }, ensure_ascii=False)


def calc_face_by_workers(n: int) -> str:
    """按同时工作最多人数计算采煤工作面需风量。

    公式: Q = 4 × N
    依据: 每人供风量不小于 4 m³/min

    Args:
        n: 同时工作最多人数

    Returns:
        JSON格式的计算过程与结果
    """
    result = 4 * n

    return json.dumps({
        "formula": "Q_cf = 4 × N",
        "expression": f"Q_cf = 4 × {n}",
        "steps": [
            f"Q_cf = 4 × {n}",
            f"Q_cf = {result:.2f} m³/min",
        ],
        "result": round(result, 2),
        "unit": "m³/min",
    }, ensure_ascii=False)


def calc_face_by_wind_speed(v: float, s: float) -> str:
    """按风速验算采煤工作面需风量。

    公式: Q = 60 × S × v
    验算条件: 0.25 ≤ v ≤ 4.0 m/s（采煤工作面最低/最高风速）

    Args:
        v: 设计风速，单位 m/s
        s: 有效断面积，单位 m²（可使用 calc_effective_area 计算）

    Returns:
        JSON格式的计算过程与结果
    """
    result = 60 * s * v

    return json.dumps({
        "formula": "Q_cf = 60 × S × v",
        "expression": f"Q_cf = 60 × {s} × {v}",
        "steps": [
            f"Q_cf = 60 × {s} × {v}",
            f"Q_cf = {60 * s:.2f} × {v}",
            f"Q_cf = {result:.2f} m³/min",
        ],
        "result": round(result, 2),
        "unit": "m³/min",
        "wind_speed_check": {
            "v_min": 0.25,
            "v_max": 4.0,
            "passed": 0.25 <= v <= 4.0,
        },
    }, ensure_ascii=False)


def calc_face_air_volume_max(q_gas: float = 0,
                               q_co2: float = 0,
                               k_gas: float = 1.5,
                               n_workers: int = 0,
                               v_wind: float = 0,
                               s_area: float = 0) -> str:
    """采煤工作面需风量综合计算 —— 取各方法最大值。

    按瓦斯、二氧化碳、人数、风速分别计算，取最大值作为最终需风量。
    同时验算风速是否在 0.25~4.0 m/s 范围内。

    Args:
        q_gas: 平均绝对瓦斯涌出量，m³/min
        q_co2: 平均绝对二氧化碳涌出量，m³/min
        k_gas: 瓦斯涌出不均衡系数，默认 1.5
        n_workers: 同时工作最多人数
        v_wind: 设计风速，m/s
        s_area: 有效断面积，m²

    Returns:
        JSON格式的综合计算过程与结果
    """
    results = {}

    if q_gas > 0:
        results["按瓦斯涌出量"] = 100 * q_gas * k_gas

    if q_co2 > 0:
        # 二氧化碳涌出量：按 67 × q_co2 × K
        results["按二氧化碳涌出量"] = 67 * q_co2 * k_gas

    if n_workers > 0:
        results["按人数"] = 4 * n_workers

    if v_wind > 0 and s_area > 0:
        q_wind = 60 * s_area * v_wind
        results["按风速"] = q_wind
        v_check = 0.25 <= v_wind <= 4.0
    else:
        q_wind = 0
        v_check = None

    if not results:
        return json.dumps({
            "error": "请至少提供一种计算参数（q_gas、q_co2、n_workers、v_wind + s_area）",
        }, ensure_ascii=False)

    max_method = max(results, key=results.get)
    max_value = results[max_method]

    steps = []
    for method, val in results.items():
        steps.append(f"{method}: {val:.2f} m³/min")
    steps.append(f"取最大值: {max_method} = {max_value:.2f} m³/min")

    return json.dumps({
        "formula": "Q_cf = max(Q_gas, Q_co2, Q_workers, Q_wind)",
        "methods": {k: round(v, 2) for k, v in results.items()},
        "steps": steps,
        "result": round(max_value, 2),
        "max_method": max_method,
        "unit": "m³/min",
        "wind_speed_check": {
            "v_min": 0.25,
            "v_max": 4.0,
            "passed": v_check,
        } if v_check is not None else None,
    }, ensure_ascii=False)


# ============================================================
# 掘进工作面需风量计算
# ============================================================

def calc_tunnel_by_gas(q_gas: float, k_gas: float = 1.8) -> str:
    """按瓦斯涌出量计算掘进工作面需风量。

    公式: Q = 100 × q_gas × K_gas
    掘进工作面瓦斯不均衡系数通常取 1.8~2.0

    Args:
        q_gas: 平均绝对瓦斯涌出量，单位 m³/min
        k_gas: 瓦斯涌出不均衡系数，默认 1.8

    Returns:
        JSON格式的计算过程与结果
    """
    result = 100 * q_gas * k_gas

    return json.dumps({
        "formula": "Q_hf = 100 × q_gas × K_gas",
        "expression": f"Q_hf = 100 × {q_gas} × {k_gas}",
        "steps": [
            f"Q_hf = 100 × {q_gas} × {k_gas}",
            f"Q_hf = {100 * q_gas:.2f} × {k_gas}",
            f"Q_hf = {result:.2f} m³/min",
        ],
        "result": round(result, 2),
        "unit": "m³/min",
    }, ensure_ascii=False)


def calc_tunnel_by_explosives(a: float) -> str:
    """按炸药量计算掘进工作面需风量。

    公式: Q = 25 × A
    其中 A 为一次爆破最大炸药用量，kg

    Args:
        a: 一次爆破最大炸药用量，单位 kg

    Returns:
        JSON格式的计算过程与结果
    """
    result = 25 * a

    return json.dumps({
        "formula": "Q_hf = 25 × A",
        "expression": f"Q_hf = 25 × {a}",
        "steps": [
            f"Q_hf = 25 × {a}",
            f"Q_hf = {result:.2f} m³/min",
        ],
        "result": round(result, 2),
        "unit": "m³/min",
    }, ensure_ascii=False)


def calc_tunnel_by_workers(n: int) -> str:
    """按同时工作最多人数计算掘进工作面需风量。

    公式: Q = 4 × N

    Args:
        n: 同时工作最多人数

    Returns:
        JSON格式的计算过程与结果
    """
    result = 4 * n

    return json.dumps({
        "formula": "Q_hf = 4 × N",
        "expression": f"Q_hf = 4 × {n}",
        "steps": [
            f"Q_hf = 4 × {n}",
            f"Q_hf = {result:.2f} m³/min",
        ],
        "result": round(result, 2),
        "unit": "m³/min",
    }, ensure_ascii=False)


def calc_tunnel_by_wind_speed(v: float, s: float) -> str:
    """按风速验算掘进工作面需风量。

    公式: Q = 60 × S × v
    验算条件: 0.25 ≤ v ≤ 4.0 m/s（掘进工作面最低/最高风速）
    注意：岩巷最低风速为 0.15 m/s

    Args:
        v: 设计风速，单位 m/s
        s: 有效断面积，单位 m²

    Returns:
        JSON格式的计算过程与结果
    """
    result = 60 * s * v

    return json.dumps({
        "formula": "Q_hf = 60 × S × v",
        "expression": f"Q_hf = 60 × {s} × {v}",
        "steps": [
            f"Q_hf = 60 × {s} × {v}",
            f"Q_hf = {60 * s:.2f} × {v}",
            f"Q_hf = {result:.2f} m³/min",
        ],
        "result": round(result, 2),
        "unit": "m³/min",
        "wind_speed_check": {
            "v_min": 0.25,
            "v_max": 4.0,
            "note": "岩巷最低风速为 0.15 m/s",
            "passed": 0.25 <= v <= 4.0,
        },
    }, ensure_ascii=False)


def calc_tunnel_by_vehicle(total_power: float,
                            k_vehicle: float = 0.8,
                            vehicle_count: int = 1) -> str:
    """按防爆柴油机车（胶轮车）功率计算掘进工作面需风量。

    公式: Q = 4 × ΣP × K
    依据: 《煤矿安全规程》—— 使用防爆柴油机车（无轨胶轮车）的掘进工作面，
    需风量按同时运行车辆总功率计算，每 kW 供风量不小于 4 m³/min。
    K 为车辆同时运行系数。

    Args:
        total_power: 防爆柴油机车总功率（同时运行），单位 kW
        k_vehicle: 车辆同时运行系数，默认 0.8（0.5~1.0）
        vehicle_count: 同时运行车辆数，默认 1

    Returns:
        JSON格式的计算过程与结果
    """
    result = 4 * total_power * k_vehicle

    return json.dumps({
        "formula": "Q_hf = 4 × ΣP × K",
        "expression": f"Q_hf = 4 × {total_power} × {k_vehicle}",
        "steps": [
            f"车辆总功率 ΣP = {total_power} kW",
            f"同时运行系数 K = {k_vehicle}（{vehicle_count} 辆车）",
            f"Q_hf = 4 × {total_power} × {k_vehicle}",
            f"Q_hf = {4 * total_power:.2f} × {k_vehicle}",
            f"Q_hf = {result:.2f} m³/min",
        ],
        "result": round(result, 2),
        "unit": "m³/min",
        "params": {
            "total_power_kw": total_power,
            "k_vehicle": k_vehicle,
            "vehicle_count": vehicle_count,
        },
        "note": "每 kW 柴油机功率供风量 ≥ 4 m³/min（《煤矿安全规程》）",
    }, ensure_ascii=False)


def calc_tunnel_air_volume_max(q_gas: float = 0,
                                q_co2: float = 0,
                                k_gas: float = 1.8,
                                a_explosives: float = 0,
                                n_workers: int = 0,
                                v_wind: float = 0,
                                s_area: float = 0,
                                p_vehicle: float = 0,
                                k_vehicle: float = 0.8) -> str:
    """掘进工作面需风量综合计算 —— 取各方法最大值。

    按瓦斯、二氧化碳、炸药量、人数、风速、胶轮车分别计算，取最大值。
    同时验算风速是否在 0.25~4.0 m/s 范围内。

    Args:
        q_gas: 平均绝对瓦斯涌出量，m³/min
        q_co2: 平均绝对二氧化碳涌出量，m³/min
        k_gas: 瓦斯涌出不均衡系数，默认 1.8
        a_explosives: 一次爆破最大炸药用量，kg
        n_workers: 同时工作最多人数
        v_wind: 设计风速，m/s
        s_area: 有效断面积，m²
        p_vehicle: 防爆柴油机车（胶轮车）总功率，kW
        k_vehicle: 车辆同时运行系数，默认 0.8

    Returns:
        JSON格式的综合计算过程与结果
    """
    results = {}

    if q_gas > 0:
        results["按瓦斯涌出量"] = 100 * q_gas * k_gas

    if q_co2 > 0:
        results["按二氧化碳涌出量"] = 67 * q_co2 * k_gas

    if a_explosives > 0:
        results["按炸药量"] = 25 * a_explosives

    if n_workers > 0:
        results["按人数"] = 4 * n_workers

    if v_wind > 0 and s_area > 0:
        results["按风速"] = 60 * s_area * v_wind
        v_check = 0.25 <= v_wind <= 4.0
    else:
        v_check = None

    if p_vehicle > 0:
        results["按胶轮车"] = 4 * p_vehicle * k_vehicle

    if not results:
        return json.dumps({
            "error": "请至少提供一种计算参数",
        }, ensure_ascii=False)

    max_method = max(results, key=results.get)
    max_value = results[max_method]

    steps = []
    for method, val in results.items():
        steps.append(f"{method}: {val:.2f} m³/min")
    steps.append(f"取最大值: {max_method} = {max_value:.2f} m³/min")

    return json.dumps({
        "formula": "Q_hf = max(Q_gas, Q_co2, Q_explosives, Q_workers, Q_wind, Q_vehicle)",
        "methods": {k: round(v, 2) for k, v in results.items()},
        "steps": steps,
        "result": round(max_value, 2),
        "max_method": max_method,
        "unit": "m³/min",
        "wind_speed_check": {
            "v_min": 0.25,
            "v_max": 4.0,
            "passed": v_check,
        } if v_check is not None else None,
    }, ensure_ascii=False)


# ============================================================
# 硐室需风量计算
# ============================================================

def calc_chamber_by_equipment(total_power: float,
                               efficiency: float = 0.85,
                               temp_rise: float = 10.0) -> str:
    """按机电设备发热量计算硐室需风量。

    公式: Q = 3600 × θ × ΣN / (ρ × C_p × Δt)
    简化: Q ≈ 0.1 × ΣN  (常规硐室估算)
    或精确: Q = ΣN × (1 - η) / (C_p × ρ × Δt) × 60

    此处使用机电设备功率简化计算。

    Args:
        total_power: 硐室内机电设备总功率，kW
        efficiency: 设备平均效率，默认 0.85
        temp_rise: 允许温升，℃，默认 10

    Returns:
        JSON格式的计算过程与结果
    """
    # 发热量: θ = (1 - η) × ΣN
    heat = (1 - efficiency) * total_power  # kW 发热量
    # Q = 3600 × θ / (ρ × C_p × Δt)  → 空气密度 1.2 kg/m³, 比热 1.005 kJ/(kg·℃)
    result = 3600 * heat / (1.2 * 1.005 * temp_rise)

    return json.dumps({
        "formula": "Q = 3600 × (1 - η) × ΣN / (ρ × C_p × Δt)",
        "expression": f"Q = 3600 × (1 - {efficiency}) × {total_power} / (1.2 × 1.005 × {temp_rise})",
        "steps": [
            f"发热量 θ = (1 - {efficiency}) × {total_power} = {heat:.2f} kW",
            f"Q = 3600 × {heat:.2f} / (1.2 × 1.005 × {temp_rise})",
            f"Q = {3600 * heat:.2f} / {1.2 * 1.005 * temp_rise:.2f}",
            f"Q = {result:.2f} m³/min",
        ],
        "result": round(result, 2),
        "unit": "m³/min",
    }, ensure_ascii=False)


def calc_chamber_by_wind_speed(v: float, s: float) -> str:
    """按风速验算硐室需风量。

    依据: 机电硐室最低风速 0.15 m/s，最高 6.0 m/s（无瓦斯涌出）

    Args:
        v: 设计风速，m/s
        s: 有效断面积，m²

    Returns:
        JSON格式的计算过程与结果
    """
    result = 60 * s * v

    return json.dumps({
        "formula": "Q = 60 × S × v",
        "expression": f"Q = 60 × {s} × {v}",
        "steps": [
            f"Q = 60 × {s} × {v}",
            f"Q = {60 * s:.2f} × {v}",
            f"Q = {result:.2f} m³/min",
        ],
        "result": round(result, 2),
        "unit": "m³/min",
        "wind_speed_check": {
            "v_min": 0.15,
            "v_max": 6.0,
            "passed": 0.15 <= v <= 6.0,
        },
    }, ensure_ascii=False)


# ============================================================
# 其他巷道需风量计算
# ============================================================

def calc_other_by_wind_speed(v: float, s: float, tunnel_type: str = "other") -> str:
    """按风速计算其他巷道需风量。

    公式: Q = 60 × S × v
    风速限值因巷道类型不同：
    - 主要进回风巷: v ≤ 8 m/s
    - 其他通风人行巷道: v ≥ 0.15 m/s
    - 运输机巷、采区进回风巷: 0.25 ≤ v ≤ 6 m/s

    Args:
        v: 设计风速，m/s
        s: 有效断面积，m²
        tunnel_type: 巷道类型 (main_in: 主要进风, main_out: 主要回风, mining: 采区, other: 其他)

    Returns:
        JSON格式的计算过程与结果
    """
    result = 60 * s * v

    # 各类型风速限值
    limits = {
        "main_in": {"v_min": None, "v_max": 8.0, "desc": "主要进风巷"},
        "main_out": {"v_min": None, "v_max": 8.0, "desc": "主要回风巷"},
        "mining": {"v_min": 0.25, "v_max": 6.0, "desc": "采区进回风巷"},
        "other": {"v_min": 0.15, "v_max": None, "desc": "其他通风人行巷道"},
    }
    limit = limits.get(tunnel_type, limits["other"])

    return json.dumps({
        "formula": "Q = 60 × S × v",
        "expression": f"Q = 60 × {s} × {v}",
        "steps": [
            f"Q = 60 × {s} × {v}",
            f"Q = {60 * s:.2f} × {v}",
            f"Q = {result:.2f} m³/min",
        ],
        "result": round(result, 2),
        "unit": "m³/min",
        "tunnel_type": limit["desc"],
        "wind_speed_limits": {
            "v_min": limit["v_min"],
            "v_max": limit["v_max"],
        },
    }, ensure_ascii=False)


# ============================================================
# 瓦斯/CO2 涌出量反算（从测风报表数据推算）
# ============================================================

def calc_gas_emission_from_wind(wind_volume: float,
                                 concentration: float,
                                 gas_type: str = "CH4") -> str:
    """根据回风顺槽实测风量和浓度反算绝对瓦斯/CO2涌出量。

    公式: q = Q × C / 100
    其中 Q 为回风顺槽实测风量（m³/min），C 为瓦斯或CO2浓度（%）。

    用于数据一致性审查：将测风报表中反算的涌出量与配风计划中的数值对比。

    Args:
        wind_volume: 回风顺槽实测风量，单位 m³/min
        concentration: 瓦斯或CO2浓度，单位 %（如 0.3 表示 0.3%）
        gas_type: 气体类型，"CH4"（瓦斯）或 "CO2"（二氧化碳）

    Returns:
        JSON格式的计算过程与结果
    """
    result = wind_volume * concentration / 100.0

    gas_label = "绝对瓦斯涌出量" if gas_type.upper() == "CH4" else "绝对二氧化碳涌出量"
    gas_symbol = "q_gas" if gas_type.upper() == "CH4" else "q_co2"

    return json.dumps({
        "formula": f"{gas_symbol} = Q × C / 100",
        "expression": f"{gas_symbol} = {wind_volume} × {concentration} / 100",
        "steps": [
            f"回风顺槽实测风量 Q = {wind_volume} m³/min",
            f"{'瓦斯' if gas_type.upper() == 'CH4' else 'CO₂'}浓度 C = {concentration}%",
            f"{gas_label} = {wind_volume} × {concentration} / 100",
            f"{gas_label} = {wind_volume * concentration:.2f} / 100",
            f"{gas_label} = {result:.4f} m³/min",
        ],
        "result": round(result, 4),
        "unit": "m³/min",
        "gas_type": gas_type.upper(),
        "gas_label": gas_label,
        "source": "测风报表反算",
    }, ensure_ascii=False)


# ============================================================
# 汇总工具
# ============================================================

def calc_total_air_volume(air_volumes: list[dict]) -> str:
    """汇总各用风地点需风量，计算矿井总需风量。

    将各用风地点的需风量求和，得到矿井总需风量。

    Args:
        air_volumes: 各用风地点需风量列表，格式 [{name: str, q: float}, ...]

    Returns:
        JSON格式的汇总结果
    """
    if not air_volumes:
        return json.dumps({"error": "请提供各用风地点需风量数据"}, ensure_ascii=False)

    total = sum(item.get("q", 0) for item in air_volumes)
    details = [f"{item.get('name', '未知')}: {item.get('q', 0):.2f} m³/min" for item in air_volumes]

    return json.dumps({
        "formula": "Q_total = ΣQ_i",
        "steps": details + [f"总需风量 = {total:.2f} m³/min"],
        "result": round(total, 2),
        "location_count": len(air_volumes),
        "unit": "m³/min",
    }, ensure_ascii=False)