#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
SGO App 错误符号化工具 —— 配合 LINGS「App 错误」页。

把混淆的 Flutter stack trace + 对应版本的 split-debug-info 符号 → 还原成
文件:行号。是设备解码工具(sgo_crash_decode.py)的 App 翻版,包装 `flutter symbolize`。

前提: 发版时用 `flutter build apk/ipa --obfuscate --split-debug-info=symbols/<版本>/`
      生成并【按版本归档】符号文件。崩溃报告带 app_version → 用对应版本的符号解。

用法:
  # 1) 栈来自文件 (从 App 错误详情页"复制栈"存成 crash.txt)
  python sgo_app_symbolize.py --stack crash.txt --symbols symbols/1.2.3/app.android-arm64.symbols

  # 2) 平台对应的符号文件(发版时 symbols/<版本>/ 目录下):
  #    Android arm64 : app.android-arm64.symbols
  #    Android arm   : app.android-arm.symbols
  #    iOS           : app.ios-arm64.symbols
  #    (按崩溃报告的 platform 选对应那个)

前提: PATH 里有 `flutter`(本机 Flutter SDK)。
"""
import argparse
import os
import shutil
import subprocess
import sys


def die(msg):
    print("✗ " + msg, file=sys.stderr)
    sys.exit(1)


def main():
    ap = argparse.ArgumentParser(
        description="SGO App 错误符号化 (flutter symbolize 包装)")
    ap.add_argument("--stack", required=True,
                    help="混淆栈文件 (从 App 错误详情页复制 stack_trace 存成 .txt)")
    ap.add_argument("--symbols", required=True,
                    help="对应版本的符号文件 (symbols/<版本>/app.<platform>.symbols)")
    ap.add_argument("--flutter", help="覆盖 flutter 可执行路径 (默认从 PATH 找)")
    args = ap.parse_args()

    if not os.path.exists(args.stack):
        die(f"找不到栈文件: {args.stack}")
    if not os.path.exists(args.symbols):
        die(f"找不到符号文件: {args.symbols}\n"
            f"  → 发版时须 flutter build --obfuscate --split-debug-info=symbols/<版本>/ 并按版本归档。")

    flutter = args.flutter or shutil.which("flutter")
    if not flutter:
        die("找不到 flutter。请确认 Flutter SDK 在 PATH,或用 --flutter 指定。")

    print(f"→ {flutter} symbolize\n→ 符号: {args.symbols}\n" + "-" * 60)
    res = subprocess.run(
        [flutter, "symbolize", "-i", args.stack, "-d", args.symbols],
        capture_output=True, text=True)
    if res.returncode != 0:
        die("flutter symbolize 失败:\n" + (res.stderr or res.stdout)
            + "\n  → 多半是符号文件跟该版本不匹配 (用崩溃报告里 app_version 对应的那份)。")
    sys.stdout.write(res.stdout)


if __name__ == "__main__":
    main()
