"""Models for diff mode."""

from dataclasses import dataclass, field
from enum import Enum

from apiposture.core.models.finding import Finding


class ChangeType(str, Enum):
    """Type of change detected in diff."""

    NEW = "new"
    RESOLVED = "resolved"
    CHANGED = "changed"
    UNCHANGED = "unchanged"


@dataclass
class FindingChange:
    """Represents a change in a finding between two scans."""

    change_type: ChangeType
    finding: Finding
    previous_finding: Finding | None = None


@dataclass
class SeverityChange:
    """Represents a severity level change for a finding between scans."""

    finding: Finding
    previous_severity: object  # Severity enum
    current_severity: object  # Severity enum
    is_escalation: bool = False
    is_deescalation: bool = False


@dataclass
class EndpointChange:
    """Represents a change in endpoints between two scans."""

    change_type: ChangeType
    endpoint_path: str
    endpoint_method: str


@dataclass
class DiffResult:
    """Result of comparing two scan results."""

    baseline_scan_count: int
    current_scan_count: int

    # Finding changes
    new_findings: list[Finding] = field(default_factory=list)
    resolved_findings: list[Finding] = field(default_factory=list)
    changed_findings: list[tuple[Finding, Finding]] = field(default_factory=list)
    unchanged_findings: list[Finding] = field(default_factory=list)

    # Severity changes
    severity_changes: list[SeverityChange] = field(default_factory=list)

    # Endpoint changes
    new_endpoints: list[str] = field(default_factory=list)
    removed_endpoints: list[str] = field(default_factory=list)

    # Regression detection
    has_regressions: bool = False
    regression_count: int = 0

    @property
    def total_changes(self) -> int:
        """Total number of changes detected."""
        return (
            len(self.new_findings)
            + len(self.resolved_findings)
            + len(self.changed_findings)
            + len(self.severity_changes)
        )

    @property
    def summary(self) -> str:
        """Human-readable summary of changes."""
        lines = [
            f"Baseline: {self.baseline_scan_count} findings",
            f"Current: {self.current_scan_count} findings",
            "",
            f"New findings: {len(self.new_findings)}",
            f"Resolved findings: {len(self.resolved_findings)}",
            f"Changed findings: {len(self.changed_findings)}",
            f"Unchanged findings: {len(self.unchanged_findings)}",
        ]

        if self.severity_changes:
            escalations = sum(1 for sc in self.severity_changes if sc.is_escalation)
            deescalations = sum(1 for sc in self.severity_changes if sc.is_deescalation)
            lines.append(f"Severity changes: {len(self.severity_changes)} ({escalations} escalations, {deescalations} de-escalations)")

        lines.extend([
            "",
            f"New endpoints: {len(self.new_endpoints)}",
            f"Removed endpoints: {len(self.removed_endpoints)}",
        ])

        if self.has_regressions:
            lines.append("")
            lines.append(f"Regressions detected: {self.regression_count}")

        return "\n".join(lines)
