"""Skill refresh types and result models.

Provides ``SkillRefreshResult`` — a lightweight, immutable summary of a
refresh operation — used by ``SkillRegistry.refresh()`` / ``refresh_all()``
and propagated to CLI output and MCP notification hooks.
"""

from __future__ import annotations

from dataclasses import dataclass, field


@dataclass(frozen=True)
class SkillRefreshResult:
    """Immutable summary of a skill registry refresh operation.

    Attributes:
        refreshed: Names of skills whose tool sets were successfully recomputed.
        failed: Mapping of skill name to error message for each failure.
        skipped: Names of skills skipped because the tool registry was
            unavailable (validation cannot proceed without it).
    """

    refreshed: list[str] = field(default_factory=list)
    failed: dict[str, str] = field(default_factory=dict)
    skipped: list[str] = field(default_factory=list)

    @property
    def total_refreshed(self) -> int:
        """Number of successfully refreshed skills."""
        return len(self.refreshed)

    @property
    def total_failed(self) -> int:
        """Number of skills that failed to refresh."""
        return len(self.failed)

    @property
    def total_skipped(self) -> int:
        """Number of skills skipped due to missing tool registry."""
        return len(self.skipped)

    def to_summary(self) -> str:
        """Return a human-readable one-line summary for CLI/log output.

        Example::

            "refreshed: 3, failed: 1, skipped: 0"
        """
        return (
            f"refreshed: {self.total_refreshed}, "
            f"failed: {self.total_failed}, "
            f"skipped: {self.total_skipped}"
        )

    def merge(self, other: SkillRefreshResult) -> SkillRefreshResult:
        """Combine two results into one (used by ``refresh_all``)."""
        merged_failed = {**self.failed, **other.failed}
        return SkillRefreshResult(
            refreshed=self.refreshed + other.refreshed,
            failed=merged_failed,
            skipped=self.skipped + other.skipped,
        )
