"""Company-related type definitions.

These dataclasses represent core domain objects for company resolution
and matching. They have no infrastructure dependencies.
"""

from __future__ import annotations

import time
from collections import deque
from dataclasses import dataclass, asdict
from typing import Any, Dict, List, Optional


@dataclass
class CompanyProfile:
    """Company profile from FoundryGraph or other data sources.

    Represents canonical company information including identifiers,
    firmographics, and corporate hierarchy.
    """
    domain: str
    canonical_name: str
    wikidata_id: Optional[str] = None
    industries: Optional[List[str]] = None
    headquarters: Optional[str] = None
    employee_count: Optional[int] = None
    stock_ticker: Optional[str] = None
    ultimate_parent: Optional[str] = None
    parent_domain: Optional[str] = None
    confidence: float = 0.0
    source: str = "foundrygraph"
    metadata: Optional[Dict[str, Any]] = None

    def to_dict(self) -> Dict[str, Any]:
        """Convert to dictionary representation."""
        return asdict(self)


@dataclass
class ResolutionResult:
    """Result of a company/domain resolution operation.

    Wraps the resolved value with caching metadata.
    """
    value: Dict[str, Any]
    cacheable: bool = True


@dataclass
class ResolverMetrics:
    """Metrics collected during batch resolution operations.

    Tracks hit rates across different resolution stages (registry,
    Wikidata, DNS verification, etc.) for monitoring and debugging.
    """
    mode: str
    total_unique: int = 0
    registry_hits: int = 0
    wikidata_hits: int = 0
    hardcoded_hits: int = 0
    override_hits: int = 0
    alias_hits: int = 0
    ticker_hits: int = 0
    cache_hits: int = 0
    heuristic_hits: int = 0
    dns_verified: int = 0
    needs_dns: int = 0
    unresolved: int = 0
    dns_attempts: int = 0
    dns_timeouts: int = 0
    dns_failures: int = 0
    breaker_tripped: bool = False
    elapsed_ms: float = 0.0


class CircuitBreaker:
    """Circuit breaker pattern for DNS timeout protection.

    Tracks failures within a sliding window and trips when the
    threshold is exceeded, preventing cascading failures.

    Args:
        threshold: Number of failures to trigger the breaker
        window_seconds: Time window for tracking failures
    """

    def __init__(self, threshold: int = 20, window_seconds: int = 120):
        self.threshold = threshold
        self.window_seconds = window_seconds
        self._events: deque[float] = deque()

    def record_timeout(self) -> bool:
        """Record a timeout event and return whether breaker is now tripped."""
        now = time.time()
        self._events.append(now)
        self._evict(now)
        return self.tripped

    def _evict(self, now: float) -> None:
        """Remove events outside the window."""
        while self._events and now - self._events[0] > self.window_seconds:
            self._events.popleft()

    @property
    def tripped(self) -> bool:
        """Check if the circuit breaker is currently tripped."""
        return len(self._events) >= self.threshold

    def reset(self) -> None:
        """Reset the circuit breaker."""
        self._events.clear()
