"""Git regression guard — install/uninstall a post-commit hook."""
from __future__ import annotations

import os
import stat
from pathlib import Path

_HOOK_MARKER = "# DEATHBED_GUARD"

_HOOK_TEMPLATE = '''\
#!/usr/bin/env python3
# deathbed regression guard — post-commit hook
# Generated by: deathbed --install-hook
# Uninstall with: deathbed --uninstall-hook
#
# DEATHBED_GUARD
import json
import subprocess
import sys
from pathlib import Path

REPO_ROOT  = Path(__file__).resolve().parent.parent.parent
WARN_DROP  = WARN_DROP_VALUE
BLOCK_DROP = BLOCK_DROP_VALUE


def main() -> None:
    try:
        proc = subprocess.run(
            [sys.executable, "-m", "deathbed", "--since", "HEAD~1", "--format", "json"],
            capture_output=True, text=True, cwd=str(REPO_ROOT),
        )
        if proc.returncode != 0:
            proc = subprocess.run(
                ["deathbed", "--since", "HEAD~1", "--format", "json"],
                capture_output=True, text=True, cwd=str(REPO_ROOT),
            )
        if proc.returncode != 0:
            sys.exit(0)
        data = json.loads(proc.stdout)
    except Exception:
        sys.exit(0)

    history_file = Path.home() / ".deathbed" / "history.json"
    try:
        all_history = json.loads(history_file.read_text(encoding="utf-8"))
        repo_key = str(REPO_ROOT)
        scans = all_history.get(repo_key, [])
    except Exception:
        sys.exit(0)

    if len(scans) < 2:
        sys.exit(0)

    prev_files = scans[-2].get("files", {})
    warn_files = []
    block_files = []

    for f in data.get("files", []):
        path = f["file"]
        curr = f["health_score"]
        prev = prev_files.get(path)
        if prev is None:
            continue
        drop = prev - curr
        if drop >= BLOCK_DROP:
            block_files.append((path, drop, prev, curr))
        elif drop >= WARN_DROP:
            warn_files.append((path, drop, prev, curr))

    if warn_files or block_files:
        print()
        for path, drop, prev, curr in warn_files:
            print(f"\u26a0\ufe0f  Health regression: {path} dropped {drop} points ({prev} \u2192 {curr})")
        for path, drop, prev, curr in block_files:
            print(f"\U0001f6a8 REGRESSION DETECTED: {path} dropped {drop} points ({prev} \u2192 {curr})")

    if block_files:
        print(f"\\nBlocking commit \\u2014 score drop exceeded {BLOCK_DROP} points threshold.")
        print("Fix the regression or raise the threshold in .deathbed.toml ([guard] block_drop).")
        sys.exit(1)


if __name__ == "__main__":
    main()
'''


def install_hook(repo_root: Path, warn_drop: int = 10, block_drop: int = 20) -> None:
    """
    Install a post-commit hook. Idempotent — safe to call multiple times.
    Raises FileNotFoundError if .git/hooks does not exist.
    Raises FileExistsError if hook exists and was NOT created by deathbed.
    """
    hook_dir  = repo_root / ".git" / "hooks"
    hook_file = hook_dir / "post-commit"

    if not hook_dir.is_dir():
        raise FileNotFoundError(f".git/hooks not found in {repo_root}")

    if hook_file.exists():
        existing = hook_file.read_text(encoding="utf-8", errors="replace")
        if _HOOK_MARKER not in existing:
            raise FileExistsError(
                f"{hook_file} already exists and was not created by deathbed.\n"
                "Remove it manually or append the deathbed guard to it."
            )

    script = (
        _HOOK_TEMPLATE
        .replace("WARN_DROP_VALUE", str(warn_drop))
        .replace("BLOCK_DROP_VALUE", str(block_drop))
    )
    hook_file.write_text(script, encoding="utf-8")

    if os.name != "nt":
        current = stat.S_IMODE(hook_file.stat().st_mode)
        hook_file.chmod(current | stat.S_IXUSR | stat.S_IXGRP | stat.S_IXOTH)


def uninstall_hook(repo_root: Path) -> bool:
    """Remove the deathbed post-commit hook. Returns True if removed."""
    hook_file = repo_root / ".git" / "hooks" / "post-commit"
    if not hook_file.exists():
        return False
    existing = hook_file.read_text(encoding="utf-8", errors="replace")
    if _HOOK_MARKER not in existing:
        return False
    hook_file.unlink()
    return True
