#!/usr/bin/env python3
"""
手动发布版本脚本
================

用法：
    python scripts/publish_release.py \
        --version 1.6.0 \
        --notes "修复视频导出崩溃\n优化启动速度" \
        --bundle-dir ../tauri-app/src-tauri/target/release/bundle

流程：
    1. 扫描 bundle 目录，找到 .app.tar.gz / .exe / .AppImage 和对应的 .sig 文件
    2. 上传安装包到七牛云
    3. 读取 .sig 文件内容
    4. 调用后端 API 创建版本发布记录

依赖：
    pip install qiniu httpx
"""

import argparse
import sys
from pathlib import Path

import httpx
from dotenv import load_dotenv

load_dotenv()


def find_packages(bundle_dir: Path) -> list[dict]:
    """扫描构建产物目录，找到安装包和对应的签名文件"""
    packages = []

    # macOS: .app.tar.gz + .app.tar.gz.sig
    for sig_file in bundle_dir.rglob("*.app.tar.gz.sig"):
        pkg_file = sig_file.with_suffix("")  # 去掉 .sig
        if not pkg_file.exists():
            print(f"警告: 签名文件存在但安装包缺失: {pkg_file}")
            continue

        signature = sig_file.read_text().strip()
        file_size = pkg_file.stat().st_size
        filename = pkg_file.name

        # 判断文件名是否包含架构标识
        has_arch_marker = any(marker in filename for marker in ["aarch64", "arm64", "x86_64"])

        if has_arch_marker:
            # 文件名含架构标识，按标识解析
            arch = "aarch64" if "aarch64" in filename or "arm64" in filename else "x86_64"
            archs = [arch]
        else:
            # Universal Binary：同时支持 x86_64 和 aarch64
            archs = ["x86_64", "aarch64"]

        for arch in archs:
            packages.append({
                "platform": "darwin",
                "architecture": arch,
                "filename": filename,
                "local_path": str(pkg_file),
                "signature": signature,
                "file_size": file_size,
            })

    # Windows: .exe + .exe.sig
    for sig_file in bundle_dir.rglob("*.exe.sig"):
        pkg_file = sig_file.with_suffix("")
        if not pkg_file.exists():
            print(f"警告: 签名文件存在但安装包缺失: {pkg_file}")
            continue

        arch = "x86_64"  # Windows 目前只打 x86_64

        signature = sig_file.read_text().strip()

        packages.append({
            "platform": "windows",
            "architecture": arch,
            "filename": pkg_file.name,
            "local_path": str(pkg_file),
            "signature": signature,
            "file_size": pkg_file.stat().st_size,
        })

    # Linux: .AppImage + .AppImage.sig
    for sig_file in bundle_dir.rglob("*.AppImage.sig"):
        pkg_file = sig_file.with_suffix("")
        if not pkg_file.exists():
            print(f"警告: 签名文件存在但安装包缺失: {pkg_file}")
            continue

        arch = "x86_64"  # Linux 目前只打 x86_64

        signature = sig_file.read_text().strip()

        packages.append({
            "platform": "linux",
            "architecture": arch,
            "filename": pkg_file.name,
            "local_path": str(pkg_file),
            "signature": signature,
            "file_size": pkg_file.stat().st_size,
        })

    # macOS DMG: 给新用户首次安装用（无签名文件）
    for dmg_file in bundle_dir.rglob("*.dmg"):
        filename = dmg_file.name

        # 判断文件名是否包含架构标识
        has_arch_marker = any(marker in filename for marker in ["aarch64", "arm64", "x86_64"])
        if has_arch_marker:
            arch = "aarch64" if "aarch64" in filename or "arm64" in filename else "x86_64"
            archs = [arch]
        else:
            # Universal DMG：同时支持 x86_64 和 aarch64
            archs = ["x86_64", "aarch64"]

        for arch in archs:
            packages.append({
                "platform": "darwin",
                "architecture": arch,
                "filename": filename,
                "local_path": str(dmg_file),
                "signature": "",  # DMG 无签名（非 updater 包）
                "file_size": dmg_file.stat().st_size,
            })

    return packages


def upload_to_qiniu(local_path: str, key: str) -> str:
    """上传文件到七牛云，返回访问 URL"""
    # 这里使用七牛云 SDK，需要配置环境变量
    # 复用现有七牛云密钥和 media bucket
    import os
    from qiniu import Auth, put_file

    access_key = os.environ["QINIU_ACCESS_KEY"]
    secret_key = os.environ["QINIU_SECRET_KEY"]
    bucket_name = os.environ["QINIU_VIDEO_BUCKET"]
    domain = os.environ["QINIU_VIDEO_DOMAIN"]

    auth = Auth(access_key, secret_key)
    token = auth.upload_token(bucket_name, key, 3600)

    ret, info = put_file(token, key, local_path, version="v2")
    if ret is None:
        raise RuntimeError(f"上传失败: {info}")

    return f"https://{domain}/{key}"


def create_release(api_base_url: str, version: str, notes: str, mandatory: bool, packages: list[dict]):
    """调用后端 API 创建版本发布记录"""
    url = f"{api_base_url}/api/v1/update/releases"

    payload = {
        "version": version,
        "notes": notes,
        "mandatory": mandatory,
        "packages": packages,
    }

    response = httpx.post(url, json=payload, timeout=30)
    response.raise_for_status()
    return response.json()


def main():
    parser = argparse.ArgumentParser(description="手动发布应用版本")
    parser.add_argument("--version", required=True, help="版本号，如 1.6.0")
    parser.add_argument("--notes", default="", help="更新说明（支持 \\n 换行）")
    parser.add_argument("--mandatory", action="store_true", help="强制更新")
    parser.add_argument("--bundle-dir", required=True, help="Tauri 构建产物目录")
    parser.add_argument("--api-url", default="https://dev.tapi.meijiaka.cn", help="后端 API 地址")
    parser.add_argument("--skip-upload", action="store_true", help="跳过七牛云上传（包已上传）")
    parser.add_argument("--base-url", default="", help="安装包基础 URL（跳过上传时使用）")

    args = parser.parse_args()

    bundle_dir = Path(args.bundle_dir)
    if not bundle_dir.exists():
        print(f"错误: 构建目录不存在: {bundle_dir}")
        sys.exit(1)

    # 1. 扫描构建产物
    print(f"扫描构建目录: {bundle_dir}")
    packages = find_packages(bundle_dir)

    if not packages:
        print("错误: 未找到任何安装包或签名文件")
        print("请确认已运行: export TAURI_SIGNING_PRIVATE_KEY=... && npm run tauri build")
        sys.exit(1)

    print(f"发现 {len(packages)} 个平台包:")
    for p in packages:
        print(f"  - {p['platform']}-{p['architecture']}: {p['filename']} ({p['file_size'] / 1024 / 1024:.1f} MB)")

    # 2. 上传到七牛云（或构造 URL）
    # 按 local_path 去重，同一个文件只上传一次
    uploaded = {}  # local_path -> file_url
    for p in packages:
        if args.skip_upload:
            if not args.base_url:
                print("错误: --skip-upload 时必须提供 --base-url")
                sys.exit(1)
            p["file_url"] = f"{args.base_url.rstrip('/')}/{p['platform']}/{p['filename']}"
        else:
            local_path = p["local_path"]
            if local_path not in uploaded:
                key = f"meijiaka-zy/releases/{args.version}/{p['platform']}/{p['filename']}"
                print(f"上传 {p['filename']} ({p['platform']}) 到七牛云...")
                uploaded[local_path] = upload_to_qiniu(local_path, key)
            p["file_url"] = uploaded[local_path]

        # 删除临时字段
        del p["local_path"]

    # 3. 创建版本发布记录
    print(f"创建版本发布记录: {args.version}")
    try:
        result = create_release(
            api_base_url=args.api_url,
            version=args.version,
            notes=args.notes.replace("\\n", "\n"),
            mandatory=args.mandatory,
            packages=packages,
        )
        print(f"发布成功！ID: {result['id']}")
        print(f"更新接口: {args.api_url}/api/v1/update/check?version={{current_version}}&target={{target}}&arch={{arch}}")
    except httpx.HTTPStatusError as e:
        print(f"发布失败: {e.response.status_code} - {e.response.text}")
        sys.exit(1)


if __name__ == "__main__":
    main()
