"""
Responsibility Heatmap — who owns what and how critical is it.

For each file in the index:
  owner          = top_authors[0] from git data (or "unknown")
  dependents_count = len(dependents)
  commit_count   = from git data
  criticality    = normalised 0-100 score based on dependents * commits

risk_level thresholds:
  CRITICAL  criticality > 80
  HIGH      criticality > 50
  MEDIUM    criticality > 20
  LOW       everything else
"""

from __future__ import annotations

from dataclasses import dataclass
from pathlib import Path

from ..memory.store import KodaraIndex


@dataclass
class HeatmapEntry:
    file: str
    module_name: str
    owner: str
    dependents_count: int
    commit_count: int
    criticality: float    # 0–100
    risk_level: str       # LOW / MEDIUM / HIGH / CRITICAL


def build_heatmap(index: KodaraIndex) -> list[HeatmapEntry]:
    """
    Build a responsibility heatmap from an indexed project.

    Returns a list of HeatmapEntry sorted by criticality descending.
    Files with no git data degrade gracefully (owner="unknown", commit_count=0).
    """
    if not index.modules:
        return []

    # First pass: collect raw scores to normalise
    raw: list[tuple[str, dict, int, int, str]] = []  # path, mod, dependents, commits, owner

    for path, mod in index.modules.items():
        dependents_count = len(mod.get("dependents", []))
        git = mod.get("git", {}) or {}
        commit_count = git.get("commit_count", 0) or 0
        top_authors = git.get("top_authors", []) or []
        owner = top_authors[0]["name"] if top_authors else "unknown"
        raw.append((path, mod, dependents_count, commit_count, owner))

    # Normalise: raw_score = dependents * commits → scale to 0-100
    max_raw = max((r[2] * r[3] for r in raw), default=0)

    entries: list[HeatmapEntry] = []
    for path, mod, dep_count, com_count, owner in raw:
        raw_score = dep_count * com_count
        if max_raw > 0:
            criticality = (raw_score / max_raw) * 100.0
        else:
            # No git data available — use dependents fraction only
            max_deps = max((r[2] for r in raw), default=0)
            criticality = (dep_count / max_deps * 100.0) if max_deps > 0 else 0.0

        risk_level = _risk_from_criticality(criticality)
        module_name = mod.get("module_name", Path(path).stem)

        entries.append(HeatmapEntry(
            file=path,
            module_name=module_name,
            owner=owner,
            dependents_count=dep_count,
            commit_count=com_count,
            criticality=round(criticality, 1),
            risk_level=risk_level,
        ))

    entries.sort(key=lambda e: e.criticality, reverse=True)
    return entries


def _risk_from_criticality(criticality: float) -> str:
    if criticality > 80:
        return "CRITICAL"
    if criticality > 50:
        return "HIGH"
    if criticality > 20:
        return "MEDIUM"
    return "LOW"
