"""
File integrity monitoring.

Computes SHA-256 baseline of critical files and watches for unexpected changes.
Uses watchdog for real-time filesystem event monitoring when available.
"""

from __future__ import annotations

import hashlib
import json
import logging
from pathlib import Path

import soosef.paths as _paths

logger = logging.getLogger(__name__)


def _hash_file(path: Path) -> str:
    """SHA-256 hash of a file."""
    h = hashlib.sha256()
    with open(path, "rb") as f:
        for chunk in iter(lambda: f.read(8192), b""):
            h.update(chunk)
    return h.hexdigest()


def create_baseline(watch_paths: list[Path], baseline_file: Path | None = None) -> dict:
    """Create a SHA-256 baseline of watched files."""
    baseline_file = baseline_file or _paths.TAMPER_BASELINE
    baseline = {}

    for path in watch_paths:
        if path.is_file():
            baseline[str(path)] = _hash_file(path)
        elif path.is_dir():
            for child in path.rglob("*"):
                if child.is_file():
                    baseline[str(child)] = _hash_file(child)

    baseline_file.parent.mkdir(parents=True, exist_ok=True)
    with open(baseline_file, "w") as f:
        json.dump(baseline, f, indent=2)

    logger.info("Tamper baseline created: %d files", len(baseline))
    return baseline


def check_baseline(baseline_file: Path | None = None) -> list[dict]:
    """Check current files against baseline. Returns list of violations."""
    baseline_file = baseline_file or _paths.TAMPER_BASELINE
    if not baseline_file.exists():
        return [{"type": "error", "message": "No baseline exists"}]

    with open(baseline_file) as f:
        baseline = json.load(f)

    violations = []
    for path_str, expected_hash in baseline.items():
        path = Path(path_str)
        if not path.exists():
            violations.append({"type": "deleted", "path": path_str})
        else:
            current = _hash_file(path)
            if current != expected_hash:
                violations.append({"type": "modified", "path": path_str})

    return violations
