"""Processor types, protocols, and base classes."""

import logging
from abc import ABC, abstractmethod
from dataclasses import dataclass, field
from datetime import datetime
from enum import Enum
from pathlib import Path
from typing import Any, Dict, List, Optional, Protocol, runtime_checkable

logger = logging.getLogger(__name__)


class AsyncProcessor(ABC):
    """Base class for async processors."""

    def __init__(self, name: str, config: Optional[Dict[str, Any]] = None):
        self.name = name
        self.config = config or {}

    @abstractmethod
    async def process_async(self, data: Any) -> Any:
        """Process data asynchronously."""
        pass


class CircuitBreakerState(Enum):
    """Circuit breaker states."""

    CLOSED = "closed"
    OPEN = "open"
    HALF_OPEN = "half_open"


@dataclass
class CircuitBreaker:
    """Simplified circuit breaker implementation."""

    failure_threshold: int = 5
    recovery_timeout: int = 60
    expected_exception: type = Exception
    state: CircuitBreakerState = field(default=CircuitBreakerState.CLOSED, init=False)
    failure_count: int = field(default=0, init=False)
    success_count: int = field(default=0, init=False)
    last_failure_time: Optional[datetime] = field(default=None, init=False)

    async def __aenter__(self):
        if self.state == CircuitBreakerState.OPEN:
            if self.last_failure_time:
                elapsed = (datetime.now() - self.last_failure_time).total_seconds()
                if elapsed > self.recovery_timeout:
                    self.state = CircuitBreakerState.HALF_OPEN
                else:
                    raise Exception("Circuit breaker is open")
        return self

    async def __aexit__(self, exc_type, exc_val, exc_tb):
        if exc_type is None:
            self.success_count += 1
            if self.state == CircuitBreakerState.HALF_OPEN:
                self.state = CircuitBreakerState.CLOSED
                self.failure_count = 0
        else:
            self.failure_count += 1
            self.last_failure_time = datetime.now()
            if self.failure_count >= self.failure_threshold:
                self.state = CircuitBreakerState.OPEN


@dataclass
class RetryConfig:
    """Retry configuration."""

    max_attempts: int = 3
    initial_delay: float = 1.0
    backoff_factor: float = 2.0
    jitter: bool = True


class RetryHandler:
    """Simple retry handler."""

    def __init__(self, config: RetryConfig):
        self.config = config


@runtime_checkable
class MediaProcessor(Protocol):
    """Protocol for media processing operations."""

    async def process(self, input_path: Path) -> Path:
        """Process media file."""
        ...

    def can_process(self, input_path: Path) -> bool:
        """Check if processor can handle the file."""
        ...
