"""
Local Blast Radius Calculator for VideoDetection.
Hỗ trợ kiểm tra mức độ ảnh hưởng và cơ chế mở khóa tạm thời (--ack) trong 30 phút.
"""
from __future__ import annotations

import argparse
import json
import os
import sys
import time
from pathlib import Path
from typing import Dict, List, Set

ACK_FILE = Path(__file__).resolve().parent / ".blast_radius_ack.json"


def load_acks() -> Dict[str, float]:
    if not ACK_FILE.exists():
        return {}
    try:
        with open(ACK_FILE, "r", encoding="utf-8") as f:
            return json.load(f)
    except Exception:
        return {}


def save_ack(target_path: str) -> None:
    acks = load_acks()
    # 30 phút = 1800 giây
    acks[os.path.abspath(target_path)] = time.time() + 1800
    try:
        with open(ACK_FILE, "w", encoding="utf-8") as f:
            json.dump(acks, f, indent=2, ensure_ascii=True)
    except Exception:
        pass


def is_acked(target_path: str) -> bool:
    acks = load_acks()
    exp = acks.get(os.path.abspath(target_path), 0.0)
    return time.time() < exp


def analyze_target(target_path: str, workspace_root: Path) -> Dict[str, object]:
    norm_target = os.path.abspath(target_path)
    base_name = os.path.basename(norm_target)
    stem = os.path.splitext(base_name)[0]

    if is_acked(norm_target):
        return {
            "blocked": False,
            "target": target_path,
            "reason": f"Target '{base_name}' is acknowledged and unlocked.",
            "dependents": [],
            "count": 0,
        }

    # Nếu không phải file Python hoặc là __init__.py thì không chặn
    if not norm_target.endswith(".py") or base_name == "__init__.py":
        return {
            "blocked": False,
            "target": target_path,
            "reason": "Non-code or package init file permitted.",
            "dependents": [],
            "count": 0,
        }


    dependents: List[str] = []
    for root, dirs, files in os.walk(workspace_root):
        dirs[:] = [d for d in dirs if d not in [".git", ".gemini", "node_modules", "venv", ".venv", "__pycache__", "dist", "build", "Temp", "Data", "Target"]]
        for f in files:
            if not f.endswith(".py"):
                continue
            full_p = os.path.join(root, f)
            if os.path.abspath(full_p) == norm_target:
                continue
            try:
                with open(full_p, "r", encoding="utf-8", errors="ignore") as src:
                    if stem in src.read():
                        dependents.append(os.path.relpath(full_p, workspace_root))
            except Exception:
                pass

    is_blocked = len(dependents) >= 6
    return {
        "blocked": is_blocked,
        "target": target_path,
        "reason": f"Target has {len(dependents)} dependents." if is_blocked else "Safe to modify.",
        "dependents": dependents,
        "count": len(dependents),
    }


def main() -> int:
    parser = argparse.ArgumentParser(description="Blast Radius Calculator")
    parser.add_argument("--target", required=True, help="Target file path")
    parser.add_argument("--format", default="json", choices=["json", "text"])
    parser.add_argument("--ack", action="store_true", help="Acknowledge and unlock target for 30 minutes")
    args = parser.parse_args()

    workspace_root = Path(__file__).resolve().parents[2]

    if args.ack:
        save_ack(args.target)
        result = {
            "blocked": False,
            "target": args.target,
            "reason": f"Target '{args.target}' acknowledged for 30 minutes.",
            "acknowledged": True,
        }
    else:
        result = analyze_target(args.target, workspace_root)

    print(json.dumps(result, ensure_ascii=True))
    return 0


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