"""gRPC configuration for server and client with centralized defaults."""

from __future__ import annotations

from dataclasses import dataclass, field
from typing import TYPE_CHECKING, Final

from noteflow.config.constants import DEFAULT_GRPC_PORT

if TYPE_CHECKING:
    from noteflow.application.services.calendar_service import CalendarService
    from noteflow.application.services.ner_service import NerService
    from noteflow.application.services.project_service import ProjectService
    from noteflow.application.services.summarization_service import SummarizationService
    from noteflow.application.services.webhook_service import WebhookService
    from noteflow.infrastructure.diarization import DiarizationEngine

# =============================================================================
# Constants
# =============================================================================

DEFAULT_PORT: Final[int] = DEFAULT_GRPC_PORT  # Re-export for backwards compatibility
DEFAULT_MODEL: Final[str] = "base"
DEFAULT_ASR_DEVICE: Final[str] = "cpu"
DEFAULT_COMPUTE_TYPE: Final[str] = "int8"
DEFAULT_DIARIZATION_DEVICE: Final[str] = "auto"


# =============================================================================
# Server Configuration (run_server parameters as structured config)
# =============================================================================


@dataclass(frozen=True, slots=True)
class AsrConfig:
    """ASR (Automatic Speech Recognition) configuration.

    Attributes:
        model: Model size (tiny, base, small, medium, large).
        device: Device for inference (cpu, cuda).
        compute_type: Compute precision (int8, float16, float32).
    """

    model: str = DEFAULT_MODEL
    device: str = DEFAULT_ASR_DEVICE
    compute_type: str = DEFAULT_COMPUTE_TYPE


@dataclass(frozen=True, slots=True)
class DiarizationConfig:
    """Speaker diarization configuration.

    Attributes:
        enabled: Whether speaker diarization is enabled.
        hf_token: HuggingFace token for pyannote models.
        device: Device for inference (auto, cpu, cuda, mps).
        streaming_latency: Streaming diarization latency in seconds.
        min_speakers: Minimum expected speakers for offline diarization.
        max_speakers: Maximum expected speakers for offline diarization.
        refinement_enabled: Whether to allow diarization refinement RPCs.
    """

    enabled: bool = False
    hf_token: str | None = None
    device: str = DEFAULT_DIARIZATION_DEVICE
    streaming_latency: float | None = None
    min_speakers: int | None = None
    max_speakers: int | None = None
    refinement_enabled: bool = True


@dataclass(frozen=True, slots=True)
class GrpcServerConfig:
    """Complete server configuration.

    Combines all sub-configurations needed to run the NoteFlow gRPC server.

    Attributes:
        port: Port to listen on.
        asr: ASR engine configuration.
        database_url: PostgreSQL connection URL. If None, runs in-memory mode.
        diarization: Speaker diarization configuration.
    """

    port: int = DEFAULT_PORT
    asr: AsrConfig = field(default_factory=AsrConfig)
    database_url: str | None = None
    diarization: DiarizationConfig = field(default_factory=DiarizationConfig)

    @classmethod
    def from_args(
        cls,
        port: int,
        asr_model: str,
        asr_device: str,
        asr_compute_type: str,
        database_url: str | None = None,
        diarization_enabled: bool = False,
        diarization_hf_token: str | None = None,
        diarization_device: str = DEFAULT_DIARIZATION_DEVICE,
        diarization_streaming_latency: float | None = None,
        diarization_min_speakers: int | None = None,
        diarization_max_speakers: int | None = None,
        diarization_refinement_enabled: bool = True,
    ) -> GrpcServerConfig:
        """Create config from flat argument values.

        Convenience factory for transitioning from the 12-parameter
        run_server() signature to structured configuration.
        """
        return cls(
            port=port,
            asr=AsrConfig(
                model=asr_model,
                device=asr_device,
                compute_type=asr_compute_type,
            ),
            database_url=database_url,
            diarization=DiarizationConfig(
                enabled=diarization_enabled,
                hf_token=diarization_hf_token,
                device=diarization_device,
                streaming_latency=diarization_streaming_latency,
                min_speakers=diarization_min_speakers,
                max_speakers=diarization_max_speakers,
                refinement_enabled=diarization_refinement_enabled,
            ),
        )


# =============================================================================
# Client Configuration
# =============================================================================


@dataclass(frozen=True)
class ServerDefaults:
    """Default server connection settings."""

    HOST: str = "localhost"
    PORT: int = DEFAULT_PORT
    TIMEOUT_SECONDS: float = 5.0
    MAX_MESSAGE_SIZE: int = 50 * 1024 * 1024  # 50MB for audio

    @property
    def address(self) -> str:
        """Return default server address."""
        return f"{self.HOST}:{self.PORT}"


@dataclass(frozen=True)
class StreamingConfig:
    """Configuration for audio streaming sessions."""

    CHUNK_TIMEOUT_SECONDS: float = 0.1
    QUEUE_MAX_SIZE: int = 1000
    SAMPLE_RATE: int = 16000
    CHANNELS: int = 1


# Singleton instances for easy import - defined before ClientConfig for type inference
SERVER_DEFAULTS = ServerDefaults()
STREAMING_CONFIG = StreamingConfig()


@dataclass
class ClientConfig:
    """Configuration for NoteFlowClient."""

    server_address: str = field(default_factory=lambda: SERVER_DEFAULTS.address)
    timeout_seconds: float = field(default=SERVER_DEFAULTS.TIMEOUT_SECONDS)
    max_message_size: int = field(default=SERVER_DEFAULTS.MAX_MESSAGE_SIZE)
    streaming: StreamingConfig = field(default_factory=StreamingConfig)


# =============================================================================
# Services Configuration (for NoteFlowServer and NoteFlowServicer)
# =============================================================================


@dataclass(frozen=True, slots=True)
class ServicesConfig:
    """Configuration for optional services injected into NoteFlowServer/Servicer.

    Groups the optional service dependencies to reduce parameter count in
    __init__ methods while maintaining backward compatibility.

    Attributes:
        summarization_service: Service for generating meeting summaries.
        diarization_engine: Engine for speaker identification.
        diarization_refinement_enabled: Whether to allow post-meeting diarization refinement.
        ner_service: Service for named entity extraction.
        calendar_service: Service for OAuth and calendar event fetching.
        webhook_service: Service for webhook event notifications.
        project_service: Service for project management.
    """

    summarization_service: SummarizationService | None = None
    diarization_engine: DiarizationEngine | None = None
    diarization_refinement_enabled: bool = True
    ner_service: NerService | None = None
    calendar_service: CalendarService | None = None
    webhook_service: WebhookService | None = None
    project_service: ProjectService | None = None
