#!/usr/bin/env python3
"""Fail if git-indexed deploy-critical files contain CR (CRLF).

Checks blobs in the git index (what Ubuntu gets on git pull), not the working tree.

Usage:
  python scripts/check_text_eol.py
  python scripts/check_text_eol.py --fix-hint
"""

from __future__ import annotations

import argparse
import subprocess
import sys
from pathlib import Path

ROOT = Path(__file__).resolve().parents[1]

# Paths that must be LF-only in the repository (Ubuntu bash / Python shebang)
GLOB_PATTERNS = [
    "*.sh",
    "server/**/*.py",
    "deploy/**/*.py",
    "scripts/**/*.py",
    "web/agent/**/*.py",
    "web/agent/**/*.json",
    "tests/**/*.py",
    "mcp/**/*.py",
    "frontend/src/**/*.vue",
    "frontend/src/**/*.ts",
    "frontend/src/**/*.css",
    "frontend/e2e/**/*.mjs",
    ".cursor/rules/**/*.mdc",
    "web/agent/**/*.py",
    ".gitattributes",
    ".env.example",
    "ruff.toml",
    "requirements*.txt",
]


def git_ls_files(pattern: str) -> list[str]:
    r = subprocess.run(
        ["git", "ls-files", pattern],
        cwd=ROOT,
        capture_output=True,
        text=True,
        check=False,
    )
    if r.returncode != 0:
        return []
    return [line for line in r.stdout.splitlines() if line.strip()]


def blob_has_cr(path: str) -> bool:
    r = subprocess.run(
        ["git", "show", f":{path}"],
        cwd=ROOT,
        capture_output=True,
        check=False,
    )
    if r.returncode != 0:
        return False
    return b"\r" in r.stdout


def main() -> int:
    parser = argparse.ArgumentParser(description=__doc__)
    parser.add_argument(
        "--fix-hint",
        action="store_true",
        help="Print git renormalize commands on failure",
    )
    args = parser.parse_args()

    if subprocess.run(["git", "rev-parse", "--is-inside-work-tree"], cwd=ROOT, capture_output=True).returncode != 0:
        print("check_text_eol: not a git repository", file=sys.stderr)
        return 1

    seen: set[str] = set()
    bad: list[str] = []
    for pattern in GLOB_PATTERNS:
        for path in git_ls_files(pattern):
            if path in seen:
                continue
            seen.add(path)
            if blob_has_cr(path):
                bad.append(path)

    bad.sort()
    if bad:
        print(f"CR byte in git index ({len(bad)} file(s)):", file=sys.stderr)
        for p in bad:
            print(f"  {p}", file=sys.stderr)
        if args.fix_hint:
            print(
                "\nFix:\n"
                "  git config core.autocrlf false\n"
                "  git add --renormalize '*.sh' 'server/' 'deploy/' 'scripts/' 'web/agent/' 'frontend/src/'\n"
                "  git commit -m 'chore: normalize line endings to LF'",
                file=sys.stderr,
            )
        return 1

    print(f"check_text_eol: OK ({len(seen)} tracked paths, LF-only in git index)")
    return 0


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