"""Drift detection — hash-based staleness check for code-anchored knowledge records."""

from __future__ import annotations

import hashlib
from pathlib import Path

from fliiq.runtime.knowledge.models import KnowledgeRecord


def compute_anchor_hash(file_path: str, line_start: int, line_end: int) -> str:
    """SHA-256 of the content between line_start and line_end (1-indexed, inclusive)."""
    path = Path(file_path)
    if not path.is_file():
        raise FileNotFoundError(f"Anchor file not found: {file_path}")
    lines = path.read_text(encoding="utf-8").splitlines(keepends=True)
    content = "".join(lines[line_start - 1 : line_end])
    return hashlib.sha256(content.encode()).hexdigest()


def check_drift(record: KnowledgeRecord) -> dict:
    """Check if a code-anchored record's content has changed.

    Returns {"status": "current"|"drifted"|"missing"|"unanchored", "current_hash": str|None}
    """
    if not record.anchor or not record.anchor.content_hash:
        return {"status": "unanchored", "current_hash": None}

    path = Path(record.anchor.file)
    if not path.is_file():
        return {"status": "missing", "current_hash": None}

    try:
        current = compute_anchor_hash(
            record.anchor.file,
            record.anchor.line_start or 1,
            record.anchor.line_end or _count_lines(path),
        )
    except Exception:
        return {"status": "missing", "current_hash": None}

    if current != record.anchor.content_hash:
        return {"status": "drifted", "current_hash": current}

    return {"status": "current", "current_hash": current}


def check_drift_batch(records: list[KnowledgeRecord]) -> list[dict]:
    """Check drift for multiple records. Returns list of {record_id, ...drift_info}."""
    results = []
    for record in records:
        info = check_drift(record)
        info["record_id"] = record.id
        results.append(info)
    return results


def _count_lines(path: Path) -> int:
    return len(path.read_text(encoding="utf-8").splitlines())
