#!/usr/bin/env python3
"""
FreeExile Unified Protobuf Compiler
Compiles proto/*.proto into:
  - Python stubs (*_pb2.py, *_pb2.pyi) in server/proto/
  - TypeScript definitions (bundle.js, bundle.d.ts) in client/src/proto/
"""

import sys
import subprocess
import shutil
from pathlib import Path

PROJECT_ROOT = Path(__file__).resolve().parent.parent
PROTO_DIR = PROJECT_ROOT / "proto"
SERVER_PROTO_DIR = PROJECT_ROOT / "server" / "proto"
CLIENT_PROTO_DIR = PROJECT_ROOT / "client" / "src" / "proto"
COCOS_PROTO_DIR = PROJECT_ROOT / "client" / "cocos" / "assets" / "scripts" / "proto"

def compile_python_protos():
    print("[1/2] Compiling Protobuf for Python Server...")
    proto_files = list(PROTO_DIR.glob("*.proto"))
    if not proto_files:
        print("  ! No .proto files found in", PROTO_DIR)
        return False

    SERVER_PROTO_DIR.mkdir(parents=True, exist_ok=True)
    init_file = SERVER_PROTO_DIR / "__init__.py"
    if not init_file.exists():
        init_file.write_text("# Auto-generated proto package\n", encoding="utf-8")

    cmd = [
        sys.executable,
        "-m", "grpc_tools.protoc",
        f"-I{PROTO_DIR}",
        f"--python_out={SERVER_PROTO_DIR}",
        f"--pyi_out={SERVER_PROTO_DIR}",
        *[str(f) for f in proto_files]
    ]

    res = subprocess.run(cmd, capture_output=True, text=True)
    if res.returncode != 0:
        print("  X Python protoc compilation failed:")
        print(res.stderr)
        return False

    print(f"  OK Generated {len(proto_files)} Python proto modules in {SERVER_PROTO_DIR}")
    return True

def compile_typescript_protos():
    print("[2/2] Compiling Protobuf for TypeScript Client...")
    proto_files = list(PROTO_DIR.glob("*.proto"))
    if not proto_files:
        return False

    CLIENT_PROTO_DIR.mkdir(parents=True, exist_ok=True)
    COCOS_PROTO_DIR.mkdir(parents=True, exist_ok=True)
    bundle_js = CLIENT_PROTO_DIR / "bundle.js"
    bundle_dts = CLIENT_PROTO_DIR / "bundle.d.ts"

    # Run pbjs
    cmd = [
        "npx.cmd" if sys.platform == "win32" else "npx",
        "pbjs",
        "-t", "static-module",
        "-w", "esm",
        "--es6",
        "-d",
        "-o", str(bundle_js),
        *[str(f) for f in proto_files]
    ]

    res = subprocess.run(cmd, cwd=str(PROJECT_ROOT / "client"), capture_output=True, text=True)
    if res.returncode != 0:
        print("  X TypeScript pbjs compilation failed:")
        print(res.stderr)
        return False

    # Run pbts for type definitions
    pbts_cmd = [
        "npx.cmd" if sys.platform == "win32" else "npx",
        "pbts",
        "-o", str(bundle_dts),
        str(bundle_js)
    ]
    res_pbts = subprocess.run(pbts_cmd, cwd=str(PROJECT_ROOT / "client"), capture_output=True, text=True)
    if res_pbts.returncode != 0:
        print("  ! pbts generation warning:")
        print(res_pbts.stderr)

    # Sync bundle.js and bundle.d.ts to Cocos Creator proto directory
    shutil.copyfile(bundle_js, COCOS_PROTO_DIR / "bundle.js")
    if bundle_dts.exists():
        shutil.copyfile(bundle_dts, COCOS_PROTO_DIR / "bundle.d.ts")

    print(f"  OK Generated TypeScript bundle & d.ts in {CLIENT_PROTO_DIR}")
    print(f"  OK Synced Cocos Creator bundle & d.ts in {COCOS_PROTO_DIR}")
    return True

def main():
    print("=" * 60)
    print(" FreeExile Protobuf Pipeline Auto-Compiler")
    print("=" * 60)
    py_ok = compile_python_protos()
    ts_ok = compile_typescript_protos()
    if py_ok and ts_ok:
        print("\nAll Protobuf bindings compiled successfully!")
        return 0
    else:
        print("\nSome Protobuf compilation steps failed.")
        return 1

if __name__ == "__main__":
    sys.exit(main())
