"""AutoPOE2 - CLI Zero-Day Memory Calibrator & Offset Registry Generator.
==========================================================================
Công cụ dòng lệnh hiệu chuẩn bộ nhớ tự động Zero-Day (< 180s):
- Quét vi sai chữ ký AOB và fingerprint PE của PathOfExile.exe mới cập nhật.
- Tự động loại trừ neo tĩnh 0x290/0x540 (INV-MEM-DYNAMIC-XYZ), ép PlayerFinder 16MB.
- Thẩm định cấu trúc Vitals (CI HP 1/1, kháng UI Marker 778/779).
- Tự động sinh và cập nhật bin/Release/offsets.toml và bin/offsets.toml (INV-BUILD-01).
- Chạy kiểm toán Gate 2 Memory Drift.

Cách dùng:
  python tools/zero_day_mem_calibrator.py
  python tools/zero_day_mem_calibrator.py --exe "D:\\Games\\Path of Exile 2\\PathOfExile.exe"
  python tools/zero_day_mem_calibrator.py --dry-run
"""

from __future__ import annotations

import argparse
import json
import os
import sys
from datetime import datetime
from pathlib import Path

ROOT = Path(__file__).resolve().parent.parent
sys.path.insert(0, str(ROOT))

if sys.stdout and hasattr(sys.stdout, "reconfigure"):
    try:
        sys.stdout.reconfigure(encoding="utf-8", errors="replace")
        sys.stderr.reconfigure(encoding="utf-8", errors="replace")
    except Exception:
        pass

from src.assistant_tool.zero_day_mem_calibrator import ZeroDayMemoryCalibrator


def main() -> int:
    parser = argparse.ArgumentParser(description="AutoPOE2 Zero-Day Memory Calibrator (INV-BUILD-01)")
    parser.add_argument("--exe", type=str, default=None, help="Đường dẫn PathOfExile.exe (mặc định: tự định vị)")
    parser.add_argument("--dry-run", action="store_true", help="Chạy kiểm toán không ghi đè file cấu hình")
    parser.add_argument("--json", type=str, default=None, help="Xuất báo cáo chi tiết ra file JSON")
    args = parser.parse_args()

    calibrator = ZeroDayMemoryCalibrator(repo_root=ROOT)

    print("=" * 75)
    print("AutoPOE2 - ZERO-DAY MEMORY CALIBRATION PIPELINE (INV-BUILD-01 / INV-MEM-DYNAMIC-XYZ)")
    print(f"Thời gian kích hoạt: {datetime.now().strftime('%Y-%m-%d %H:%M:%S')}")
    print("=" * 75)

    res = calibrator.run_calibration(exe_path=args.exe, dry_run=args.dry_run)

    print(f"\n[FINGERPRINT]")
    print(f"  BuildId               : {res.build_id}")
    print(f"  TimeDateStamp         : 0x{res.time_date_stamp:08X}")
    print(f"  SectionLayoutHash     : 0x{res.section_layout_hash:016X}")
    if res.file_sha256:
        print(f"  File SHA-256          : {res.file_sha256}")

    print(f"\n[CALIBRATION & STATIC ROOTS]")
    print(f"  Số lượng static roots : {len(res.static_roots)}")
    for idx, rva in enumerate(res.static_roots[:8], start=1):
        print(f"    static_root_{idx:<2}      : 0x{rva:X}")

    print(f"\n[OFFSETS & DYNAMIC XYZ]")
    for k, v in sorted(res.offsets.items()):
        print(f"    {k:<20}: 0x{v:X}")
    print(f"  Neo tĩnh stripped     : {'CÓ (INV-MEM-DYNAMIC-XYZ ĐƯỢC BẢO TOÀN)' if res.static_anchor_stripped else 'KHÔNG'}")

    print(f"\n[GATE 2 AUDIT & TIME]")
    print(f"  Gate 2 Memory Drift   : {'PASSED [OK]' if res.gate2_passed else 'BLOCKED [FAIL]'}")
    print(f"  Thời gian thực thi    : {res.elapsed_sec:.3f} giây (Ngân sách: 180 giây)")

    if res.written_files:
        print(f"\n[REGISTRY WRITTEN]")
        for f in res.written_files:
            print(f"  -> {f}")

    if res.diagnostics:
        print(f"\n[DIAGNOSTICS]")
        for d in res.diagnostics:
            print(f"  * {d}")

    if res.errors:
        print(f"\n[ERRORS]")
        for e in res.errors:
            print(f"  ! {e}")

    report_payload = {
        "schema": "autopoe2.zero_day_mem_calibration/v1",
        "timestamp": datetime.now().isoformat(),
        "build_id": res.build_id,
        "time_date_stamp": f"0x{res.time_date_stamp:08X}",
        "section_layout_hash": f"0x{res.section_layout_hash:016X}",
        "file_sha256": res.file_sha256,
        "static_roots": [f"0x{r:X}" for r in res.static_roots],
        "offsets": {k: f"0x{v:X}" for k, v in res.offsets.items()},
        "static_anchor_stripped": res.static_anchor_stripped,
        "gate2_passed": res.gate2_passed,
        "elapsed_sec": res.elapsed_sec,
        "written_files": res.written_files,
        "diagnostics": res.diagnostics,
        "errors": res.errors,
        "success": res.success,
    }

    out_json = args.json
    if not out_json:
        out_json = str(ROOT / "data" / "builds" / f"{res.build_id}_calibration.json")

    try:
        Path(out_json).parent.mkdir(parents=True, exist_ok=True)
        Path(out_json).write_text(json.dumps(report_payload, indent=2, ensure_ascii=False), encoding="utf-8")
        print(f"\n[BÁO CÁO] Đã lưu báo cáo hiệu chuẩn: {out_json}")
    except Exception as exc:
        print(f"[WARN] Không ghi được báo cáo JSON: {exc}")

    print("\n" + "=" * 75)
    print(f"KẾT QUẢ CUỐI CÙNG: {'THÀNH CÔNG (READY FOR ZERO-DAY RUN)' if res.success else 'THẤT BẠI'}")
    print("=" * 75)

    return 0 if res.success else 1


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