"""
DNA Evolution — история изменения архитектурного DNA через snapshots.

Загружает все snapshots проекта, строит fingerprint для каждого и
показывает, как менялась архитектура со временем.
"""

from __future__ import annotations

from dataclasses import dataclass, field
from pathlib import Path

from ..memory.store import KodaraIndex


@dataclass
class DNADiff:
    snapshot_name: str
    timestamp: float
    added_patterns: list[str]    # паттерны, которые появились
    removed_patterns: list[str]  # паттерны, которые исчезли
    complexity_delta: float      # изменение complexity_score
    file_count_delta: int        # изменение количества файлов


def _all_patterns(detected: dict[str, list[str]]) -> set[str]:
    """Плоское множество всех обнаруженных паттернов из всех категорий."""
    result: set[str] = set()
    for names in detected.values():
        result.update(names)
    return result


def _index_from_snapshot(data: dict) -> KodaraIndex:
    """Воссоздаёт KodaraIndex из словаря snapshot."""
    return KodaraIndex(
        repo_id=data.get("repo_id", ""),
        display_name=data.get("display_name", ""),
        source_root=data.get("source_root", ""),
        indexed_at=float(data.get("indexed_at", 0)),
        index_version=int(data.get("index_version", 2)),
        file_count=int(data.get("file_count", 0)),
        language_counts=data.get("language_counts", {}),
        modules=data.get("modules", {}),
        graph_edges=data.get("graph_edges", []),
        file_hashes=data.get("file_hashes", {}),
    )


def get_evolution(root: Path) -> list[DNADiff]:
    """
    Загружает все snapshots и возвращает историю изменений DNA.

    Сравнивает каждый snapshot с предыдущим (от старого к новому).
    Если snapshots < 2 — возвращает пустой список.
    Если SnapshotStore недоступен или нет snapshots — graceful, возвращает [].
    """
    try:
        from ..snapshots.store import SnapshotStore
        from .fingerprint import build_fingerprint
    except ImportError:
        return []

    try:
        kodara_dir = root / ".kodara"
        snap_store = SnapshotStore(kodara_dir)
        metas = snap_store.list()
    except Exception:
        return []

    if len(metas) < 2:
        return []

    # Загружаем snapshots от старого к новому (list() возвращает newest first)
    ordered = list(reversed(metas))

    diffs: list[DNADiff] = []
    prev_dna = None
    prev_file_count = 0

    for meta in ordered:
        try:
            data = snap_store.load(meta.filename)
            if data is None:
                continue
            snap_index = _index_from_snapshot(data)
            dna = build_fingerprint(snap_index)
        except Exception:
            continue

        if prev_dna is not None:
            prev_patterns = _all_patterns(prev_dna.detected_patterns)
            curr_patterns = _all_patterns(dna.detected_patterns)

            added = sorted(curr_patterns - prev_patterns)
            removed = sorted(prev_patterns - curr_patterns)
            complexity_delta = round(dna.complexity_score - prev_dna.complexity_score, 2)
            file_count_delta = snap_index.file_count - prev_file_count

            diffs.append(DNADiff(
                snapshot_name=meta.filename,
                timestamp=snap_index.indexed_at,
                added_patterns=added,
                removed_patterns=removed,
                complexity_delta=complexity_delta,
                file_count_delta=file_count_delta,
            ))

        prev_dna = dna
        prev_file_count = snap_index.file_count

    return diffs
