# Copyright 2026 Nikolay Petrov
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#     http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

"""Canonical summary metric computation for all report formats."""

from __future__ import annotations

from collections.abc import Sequence
from dataclasses import dataclass

from .checker import _BREAKING_KINDS, DiffResult
from .checker_policy import HasKind


@dataclass(frozen=True)
class ReportSummary:
    breaking: int
    source_breaks: int
    risk_count: int
    compatible_additions: int
    total_changes: int
    binary_compatibility_pct: float
    affected_pct: float


@dataclass(frozen=True)
class CompatibilityMetrics:
    breaking_count: int
    binary_compatibility_pct: float
    affected_pct: float


def compatibility_metrics(
    changes: Sequence[HasKind], old_symbol_count: int | None = None
) -> CompatibilityMetrics:
    """Compute canonical ABICC-style binary compatibility counters/percentages."""
    breaking_count = sum(1 for c in changes if c.kind in _BREAKING_KINDS)

    if breaking_count == 0:
        bc_pct = 100.0
    elif old_symbol_count and old_symbol_count > 0:
        bc_pct = max(0.0, (old_symbol_count - breaking_count) / old_symbol_count * 100)
    else:
        total = len(changes)
        bc_pct = max(0.0, (total - breaking_count) / total * 100) if total > 0 else 0.0

    if old_symbol_count and old_symbol_count > 0:
        affected_pct = min(100.0, breaking_count / old_symbol_count * 100)
    else:
        affected_pct = 0.0

    return CompatibilityMetrics(
        breaking_count=breaking_count,
        binary_compatibility_pct=bc_pct,
        affected_pct=affected_pct,
    )


def build_summary(result: DiffResult) -> ReportSummary:
    metrics = compatibility_metrics(result.changes, result.old_symbol_count)
    return ReportSummary(
        breaking=len(result.breaking),
        source_breaks=len(result.source_breaks),
        risk_count=len(result.risk),
        compatible_additions=len(result.compatible),
        total_changes=len(result.changes),
        binary_compatibility_pct=metrics.binary_compatibility_pct,
        affected_pct=metrics.affected_pct,
    )
