# Copyright (C) 2026 GoodData Corporation

"""Versioning and additive migration helpers for repo-owned AIDA configs."""

from __future__ import annotations

from dataclasses import dataclass
from pathlib import Path

import yaml

from aida_mcp.utils.aida_paths import get_repo_config_root

LATEST_REPO_CONFIG_VERSIONS: dict[str, int] = {
    "change_domains.yaml": 1,
    "validation_policy.yaml": 1,
    "validation_registry.yaml": 1,
    "git_policy.yaml": 1,
    "rules_selection.yaml": 1,
}


@dataclass(frozen=True, slots=True)
class RepoConfigVersionStatus:
    name: str
    path: Path
    exists: bool
    version: int | None
    latest_version: int

    @property
    def outdated(self) -> bool:
        if not self.exists:
            return False
        if self.version is None:
            return True
        return self.version < self.latest_version


def collect_repo_config_statuses(*, workspace_root: Path) -> tuple[RepoConfigVersionStatus, ...]:
    config_root = get_repo_config_root(workspace_root)
    statuses: list[RepoConfigVersionStatus] = []
    for name, latest in LATEST_REPO_CONFIG_VERSIONS.items():
        path = config_root / name
        statuses.append(
            RepoConfigVersionStatus(
                name=name,
                path=path,
                exists=path.exists(),
                version=_read_config_version(path) if path.exists() else None,
                latest_version=latest,
            )
        )
    return tuple(statuses)


def migrate_repo_config_versions(*, workspace_root: Path, dry_run: bool) -> list[str]:
    config_root = get_repo_config_root(workspace_root)
    changed: list[str] = []
    for status in collect_repo_config_statuses(workspace_root=workspace_root):
        if not status.outdated:
            continue
        rel = str(status.path.relative_to(workspace_root))
        changed.append(rel)
        if dry_run:
            continue
        _write_version_header(path=config_root / status.name, version=status.latest_version)
    return changed


def _read_config_version(path: Path) -> int | None:
    try:
        loaded = yaml.safe_load(path.read_text(encoding="utf-8"))
    except Exception:
        return None
    if not isinstance(loaded, dict):
        return None
    value = loaded.get("version")
    if isinstance(value, bool):
        return None
    if isinstance(value, int) and value >= 1:
        return value
    return None


def _write_version_header(*, path: Path, version: int) -> None:
    text = path.read_text(encoding="utf-8")
    stripped = text.lstrip()
    if stripped.startswith("version:"):
        return

    lines = text.splitlines()
    insert_at = 0
    while insert_at < len(lines):
        line = lines[insert_at]
        if not line.strip():
            insert_at += 1
            continue
        if line.lstrip().startswith("#"):
            insert_at += 1
            continue
        break

    prefix = lines[:insert_at]
    suffix = lines[insert_at:]
    out_lines = [*prefix, f"version: {version}"]
    if suffix:
        out_lines.extend(suffix)
    path.write_text("\n".join(out_lines).rstrip("\n") + "\n", encoding="utf-8")
