"""Pulp JSON → 화면용 표시 모델 변환 (순수 함수, httpx 의존 없음).

GPG 검증 배지 로직(✅/⚠️/⚪)은 화면 4 에서도 재사용하므로 여기 함수로 둔다(스펙 §6 화면4).
"""

from __future__ import annotations

from typing import Any


def gpg_status(repo: dict[str, Any]) -> dict[str, str]:
    """repo_config 의 gpgcheck / repo-gpgcheck 로 3단계 검증 배지 산출.

    - pass(✅): 패키지 서명 + repo 메타데이터 서명 모두 검증
    - warn(⚠️): 둘 중 하나만 검증
    - unset(⚪): 검증 미설정
    """
    cfg = repo.get("repo_config") or {}
    pkg = bool(cfg.get("gpgcheck", 0))
    meta = bool(cfg.get("repo-gpgcheck", 0))
    # level 은 색상 칩(badge-{level})으로 렌더 — 장식 이모지는 쓰지 않는다(design-ref §7).
    if pkg and meta:
        return {"level": "pass", "label": "검증됨"}
    if pkg or meta:
        return {"level": "warn", "label": "부분 검증"}
    return {"level": "unset", "label": "미설정"}


def version_number(version_href: str | None) -> int | None:
    """latest_version_href 끝의 정수(vN) 추출. 예: .../versions/3/ → 3"""
    if not version_href:
        return None
    parts = [p for p in version_href.split("/") if p]
    try:
        return int(parts[-1])
    except (ValueError, IndexError):
        return None


def _content_count(version: dict[str, Any], section: str) -> int:
    """content_summary[section] (present/added/removed) 의 카운트 합계."""
    data = (version.get("content_summary") or {}).get(section) or {}
    return sum((info or {}).get("count", 0) for info in data.values())


def package_count(version: dict[str, Any] | None) -> int | None:
    """RepositoryVersion 의 content_summary.present 카운트 합계."""
    if version is None:
        return None
    return _content_count(version, "present")


def _uuid_from_href(href: str) -> str:
    parts = [p for p in href.split("/") if p]
    return parts[-1] if parts else ""


def build_repo_view(
    repo: dict[str, Any], version: dict[str, Any] | None = None
) -> dict[str, Any]:
    """저장소 1건 + (선택) 최신 버전 상세 → 대시보드 행 모델."""
    return {
        "name": repo.get("name", ""),
        "uuid": _uuid_from_href(repo.get("pulp_href", "")),
        "href": repo.get("pulp_href", ""),
        "latest_version": version_number(repo.get("latest_version_href")),
        "package_count": package_count(version),
        # 최신 스냅샷 생성 시각 ≈ 마지막 동기화 시각
        "last_sync": (version or {}).get("pulp_created"),
        "gpg": gpg_status(repo),
        # TODO(단계3/4): 현재 운영 배포 버전은 Distribution→publication→version 역추적 필요.
        # 단계1에선 최신 버전만 표시한다.
        "deployed_version": None,
    }


def build_version_view(
    version: dict[str, Any],
    deployed_number: int | None = None,
    gpg: dict[str, str] | None = None,
) -> dict[str, Any]:
    """RepositoryVersion → 버전 목록 행 모델.

    gpg 검증은 저장소 단위 설정(repo_config)이라 모든 버전이 같은 값을 공유한다 —
    호출부에서 repo 의 gpg_status() 를 주입한다.
    """
    number = version_number(version.get("pulp_href"))
    is_deployed = number is not None and number == deployed_number
    # 배포 가능: 검증 통과(pass) + 현재 배포 중이 아님 (스펙 §5-2 게이트)
    deployable = (gpg or {}).get("level") == "pass" and not is_deployed
    return {
        "number": number,
        "href": version.get("pulp_href"),
        "created": version.get("pulp_created"),
        "package_count": _content_count(version, "present"),
        "added": _content_count(version, "added"),
        "removed": _content_count(version, "removed"),
        "gpg": gpg,
        "is_deployed": is_deployed,
        "deployable": deployable,
    }


def deploy_preview(
    version_views: list[dict[str, Any]],
    target_number: int | None,
    deployed_number: int | None,
) -> dict[str, Any]:
    """배포 확인 모달용 미리보기: 현재 운영 버전 → 대상 버전, 순 패키지 변화."""

    def find(n: int | None) -> dict[str, Any] | None:
        return next((v for v in version_views if v["number"] == n), None)

    current = find(deployed_number)
    target = find(target_number)
    current_count = current["package_count"] if current else 0
    target_count = target["package_count"] if target else 0
    net = target_count - current_count
    return {
        "current_version": deployed_number,
        "current_count": current_count,
        "target_version": target_number,
        "target_count": target_count,
        "net": abs(net),
        "net_sign": "+" if net >= 0 else "−",
    }


def verification_detail(repo: dict[str, Any]) -> dict[str, Any]:
    """검증 상태 상세 (화면 4): GPG/checksum 설정값 + 종합 배지."""
    cfg = repo.get("repo_config") or {}
    return {
        "status": gpg_status(repo),
        "gpgcheck": int(bool(cfg.get("gpgcheck", 0))),
        "repo_gpgcheck": int(bool(cfg.get("repo-gpgcheck", 0))),
        "checksum_type": repo.get("metadata_checksum_type")
        or cfg.get("checksum_type")
        or "—",
    }


_REPO_SORT_KEYS = {
    "name": lambda r: (r["name"] or "").lower(),
    "verified": lambda r: {"pass": 0, "warn": 1, "unset": 2}.get(
        (r["gpg"] or {}).get("level"), 3
    ),
    "version": lambda r: r["latest_version"] if r["latest_version"] is not None else -1,
    "packages": lambda r: r["package_count"] if r["package_count"] is not None else -1,
    "last_sync": lambda r: r["last_sync"] or "",
}


def sort_repos(
    repo_views: list[dict[str, Any]], key: str, direction: str = "asc"
) -> list[dict[str, Any]]:
    """대시보드 헤더 정렬. 알 수 없는 key 는 이름순으로 폴백."""
    fn = _REPO_SORT_KEYS.get(key) or _REPO_SORT_KEYS["name"]
    return sorted(repo_views, key=fn, reverse=(direction == "desc"))


def summarize(repo_views: list[dict[str, Any]], syncing: int = 0) -> dict[str, int]:
    """상단 요약 카드 수치. syncing 은 task_store.active_count() 에서 주입."""
    return {
        "total": len(repo_views),
        "syncing": syncing,
        "gpg_pass": sum(1 for r in repo_views if r["gpg"]["level"] == "pass"),
        "total_packages": sum(r["package_count"] or 0 for r in repo_views),
    }


def task_progress(task: dict[str, Any]) -> dict[str, Any]:
    """Pulp task → 진행률 표시 모델.

    progress_reports[] 의 done/total 을 합산해 퍼센트를 낸다. 완료 시
    created_resources 에서 새 RepositoryVersion 번호(vN)를 추출한다.
    """
    state = task.get("state", "waiting")
    reports = task.get("progress_reports") or []
    done = sum((r or {}).get("done") or 0 for r in reports)
    total = sum((r or {}).get("total") or 0 for r in reports)
    percent = int(done / total * 100) if total else 0

    new_version = None
    for href in task.get("created_resources") or []:
        if "/versions/" in href:
            new_version = version_number(href)
            break

    error = None
    if state == "failed":
        err = task.get("error") or {}
        error = err.get("description") or "동기화 작업이 실패했습니다."

    return {
        "state": state,
        "done": done,
        "total": total,
        "percent": percent,
        "new_version": new_version,
        "error": error,
        "completed": state == "completed",
        "failed": state == "failed",
        "running": state in ("waiting", "running"),
    }
