"""Shared data models for Vibelexity complexity analysis."""

from __future__ import annotations

from dataclasses import dataclass, field


@dataclass
class PatternViolation:
    type: str
    line: int
    description: str
    severity: str = "warning"


@dataclass
class HalsteadMetrics:
    n1: int = 0  # distinct operators
    n2: int = 0  # distinct operands
    N1: int = 0  # total operators
    N2: int = 0  # total operands
    vocabulary: int = 0  # n = n1 + n2
    length: int = 0  # N = N1 + N2
    volume: float = 0.0  # V = N * log2(n)
    difficulty: float = 0.0  # D = (n1/2) * (N2/n2)
    effort: float = 0.0  # E = D * V
    time: float = 0.0  # T = E / 18 (seconds)
    bugs: float = 0.0  # B = E^(2/3) / 3000


@dataclass
class FunctionComplexity:
    name: str
    line: int
    complexity: int
    halstead: HalsteadMetrics | None = None
    npath: int | None = None
    dtd: int | None = None
    mi: float | None = None
    ldi: float | None = None
    cyclomatic: int | None = None
    type1_hash: str | None = None
    type2_hash: str | None = None
    func_loc: int = 0
    stmt_count: int = 0
    param_count: int = 0


@dataclass
class DuplicateCluster:
    dup_type: int  # 1 or 2
    hash_value: str
    members: list[tuple[str, FunctionComplexity]]


@dataclass
class FileComplexity:
    path: str
    functions: list[FunctionComplexity] = field(default_factory=list)
    loc: int = 0
    lloc: int = 0
    sloc: int = 0
    pattern_violations: list[PatternViolation] = field(default_factory=list)

    @property
    def total(self) -> int:
        return sum(f.complexity for f in self.functions)


@dataclass
class DeadCodeViolation:
    type: str
    symbol: str | None
    location: str
    line: int
    confidence: str


@dataclass
class FunctionDefinition:
    name: str
    filepath: str
    line: int
    def_type: str
    class_name: str | None = None
    params: list[str] = field(default_factory=list)


@dataclass
class CallEdge:
    caller_file: str
    caller_function: str
    caller_line: int
    callee_file: str | None
    callee_function: str
    callee_line: int | None
    call_site_line: int
    call_type: str = "local"
    receiver_object: str | None = None


@dataclass
class CallGraph:
    functions: dict[tuple[str, str], FunctionDefinition] = field(default_factory=dict)
    calls: list[CallEdge] = field(default_factory=list)
    reverse_calls: dict[str, list[CallEdge]] = field(default_factory=dict)
