"""Policy analysis result data models."""

from dataclasses import dataclass, field
from enum import Enum


class IssueType(Enum):
    """Types of issues that can be detected in policy analysis."""

    DUPLICATE_STATEMENT = "duplicate"
    DUPLICATE_SID = "duplicate_sid"
    CONFLICT = "conflict"
    SHADOW = "shadow"
    UNREACHABLE = "unreachable"


@dataclass
class Issue:
    """Represents an issue found during policy analysis."""

    type: IssueType
    message: str
    policy1: str | None = None
    statement1: str | None = None
    policy2: str | None = None
    statement2: str | None = None
    actions: list[str] = field(default_factory=list)

    def __str__(self) -> str:
        loc1 = self.statement1 or "unknown"
        loc2 = self.statement2 or "unknown"
        policy_info = ""
        if self.policy1 and self.policy2:
            policy_info = f" ({self.policy1} vs {self.policy2})"
        elif self.policy1:
            policy_info = f" ({self.policy1})"
        return f"[{self.type.value}] {self.message}{policy_info} - {loc1} vs {loc2}"

    def to_dict(self) -> dict:
        """Convert issue to dictionary for JSON serialization."""
        return {
            "type": self.type.value,
            "message": self.message,
            "policy1": self.policy1,
            "statement1": self.statement1,
            "policy2": self.policy2,
            "statement2": self.statement2,
            "actions": self.actions,
        }


@dataclass
class AnalysisReport:
    """Report from analyzing one or more SCP policies."""

    issues: list[Issue] = field(default_factory=list)
    total_statements: int = 0
    total_policies: int = 0

    @property
    def has_issues(self) -> bool:
        return len(self.issues) > 0

    @property
    def duplicates(self) -> list[Issue]:
        return [
            i
            for i in self.issues
            if i.type in (IssueType.DUPLICATE_STATEMENT, IssueType.DUPLICATE_SID)
        ]

    @property
    def conflicts(self) -> list[Issue]:
        return [i for i in self.issues if i.type == IssueType.CONFLICT]

    @property
    def shadows(self) -> list[Issue]:
        return [i for i in self.issues if i.type == IssueType.SHADOW]

    @property
    def unreachable(self) -> list[Issue]:
        return [i for i in self.issues if i.type == IssueType.UNREACHABLE]

    def to_dict(self) -> dict:
        """Convert report to dictionary for JSON serialization."""
        return {
            "total_policies": self.total_policies,
            "total_statements": self.total_statements,
            "issues": [issue.to_dict() for issue in self.issues],
            "summary": {
                "total": len(self.issues),
                "duplicates": len(self.duplicates),
                "conflicts": len(self.conflicts),
                "shadows": len(self.shadows),
                "unreachable": len(self.unreachable),
            },
        }

    def summary(self) -> str:
        """Generate a human-readable summary string."""
        if not self.has_issues:
            return (
                f"No issues found in {self.total_policies} policies"
                f" ({self.total_statements} statements)"
            )

        parts = []
        if self.duplicates:
            parts.append(f"{len(self.duplicates)} duplicate(s)")
        if self.conflicts:
            parts.append(f"{len(self.conflicts)} conflict(s)")
        if self.shadows:
            parts.append(f"{len(self.shadows)} shadow(s)")
        if self.unreachable:
            parts.append(f"{len(self.unreachable)} unreachable")

        return f"{len(self.issues)} issues found ({', '.join(parts)})"
