"""
run_detection.py
定时检测脚本：查询最近 N 分钟内上报的模拟数据，逐条调用存储过程 sp_battery_anomaly_detect。
通过 HTTP API 访问数据库，无需安装第三方依赖。

Usage: python run_detection.py [--minutes <n>]
"""

import sys
import json
import argparse
import urllib.request
from datetime import datetime

DB_API_URL = "http://47.97.121.32:8080/VOLERTECH/app/api/oauth/getmysql"
DB_JDBC    = "snowy_cloud_mysql_copy"


def execute_sql(sql: str):
    data = {"sql": sql, "basejdbc": DB_JDBC}
    json_data = json.dumps(data).encode("utf-8")
    req = urllib.request.Request(
        DB_API_URL,
        data=json_data,
        headers={"Content-Type": "application/json"}
    )
    response = urllib.request.urlopen(req)
    result = json.loads(response.read().decode("utf-8"))
    if isinstance(result, list):
        return result
    if isinstance(result, dict):
        for key in ("data", "rows", "result", "records"):
            if key in result and isinstance(result[key], list):
                return result[key]
    return []


def parse_args():
    parser = argparse.ArgumentParser()
    parser.add_argument("--minutes", type=int, default=5,
                        help="检测时间窗口（分钟），默认 5")
    return parser.parse_args()


def main():
    args = parse_args()

    # 1. 查询最近 N 分钟内的模拟数据
    rows = execute_sql(f"""
        SELECT id, battery_monitor_id, report_time
        FROM tb_battery_monitor_data
        WHERE report_time >= DATE_SUB(NOW(), INTERVAL {args.minutes} MINUTE)
        ORDER BY report_time ASC
    """)

    if not rows:
        print(json.dumps({
            "status":  "success",
            "checked": 0,
            "message": f"最近 {args.minutes} 分钟内无新数据。"
        }, ensure_ascii=False, indent=2))
        return

    # 2. 记录执行前的最大 id
    max_id_before = 0
    id_rows = execute_sql("SELECT COALESCE(MAX(id), 0) AS max_id FROM tb_battery_fault_record")
    if id_rows:
        max_id_before = id_rows[0].get("max_id", 0) or 0

    # 3. 逐条调用存储过程
    checked = 0
    errors  = []
    for row in rows:
        data_id     = row.get("id")
        cell_id     = row.get("battery_monitor_id")
        report_time = row.get("report_time")

        if not data_id or not cell_id or not report_time:
            continue

        # report_time 可能是毫秒时间戳，转为 datetime 字符串
        if isinstance(report_time, (int, float)):
            report_time = datetime.fromtimestamp(report_time / 1000).strftime("%Y-%m-%d %H:%M:%S")

        try:
            execute_sql(
                f"CALL sp_battery_anomaly_detect({data_id}, {cell_id}, '{report_time}')"
            )
            checked += 1
        except Exception as e:
            errors.append({"data_id": data_id, "error": str(e)})

    # 4. 查询本次新增的告警记录
    new_faults = []
    if max_id_before is not None:
        new_faults = execute_sql(f"""
            SELECT id, battery_id, battery_monitor_id, fault_code, fault_name,
                   fault_level, actual_value, threshold_value, report_time, create_time
            FROM tb_battery_fault_record
            WHERE id > {max_id_before}
            ORDER BY id ASC
        """)
        # report_time 可能是毫秒时间戳，转换一下
        for r in new_faults:
            for k in ("report_time", "create_time"):
                v = r.get(k)
                if isinstance(v, (int, float)):
                    r[k] = datetime.fromtimestamp(v / 1000).strftime("%Y-%m-%d %H:%M:%S")

    print(json.dumps({
        "status":     "success" if not errors else "partial",
        "minutes":    args.minutes,
        "checked":    checked,
        "new_faults": len(new_faults),
        "faults":     new_faults,
        "errors":     errors,
        "message":    f"检测完成，共处理 {checked} 条数据，新增 {len(new_faults)} 条告警。"
                      + (f" {len(errors)} 条失败。" if errors else "")
    }, ensure_ascii=False, indent=2))


if __name__ == "__main__":
    main()
