"""Data models for edge-tts."""

# pylint: disable=too-few-public-methods

import argparse
import re
from dataclasses import dataclass

from typing_extensions import Literal


@dataclass
class TTSConfig:
    """
    Represents the internal TTS configuration for edge-tts's Communicate class.
    """

    voice: str
    rate: str
    volume: str
    pitch: str
    boundary: Literal["WordBoundary", "SentenceBoundary"]

    @staticmethod
    def validate_string_param(param_name: str, param_value: str, pattern: str) -> str:
        """
        Validates the given string parameter based on type and pattern.

        Args:
            param_name (str): The name of the parameter.
            param_value (str): The value of the parameter.
            pattern (str): The pattern to validate the parameter against.

        Returns:
            str: The validated parameter.
        """
        if not isinstance(param_value, str):
            raise TypeError(f"{param_name} must be str")
        if re.match(pattern, param_value) is None:
            raise ValueError(f"Invalid {param_name} '{param_value}'.")
        return param_value

    def __post_init__(self) -> None:
        """
        Validates the TTSConfig object after initialization.
        """

        # Possible values for voice are:
        # - Microsoft Server Speech Text to Speech Voice (cy-GB, NiaNeural)
        # - cy-GB-NiaNeural
        # - fil-PH-AngeloNeural
        # Always send the first variant as that is what Microsoft Edge does.
        if not isinstance(self.voice, str):
            raise TypeError("voice must be str")
        match = re.match(r"^([a-z]{2,})-([A-Z]{2,})-(.+Neural)$", self.voice)
        if match is not None:
            lang = match.group(1)
            region = match.group(2)
            name = match.group(3)
            if name.find("-") != -1:
                region = f"{region}-{name[:name.find('-')]}"
                name = name[name.find("-") + 1 :]
            self.voice = (
                "Microsoft Server Speech Text to Speech Voice"
                + f" ({lang}-{region}, {name})"
            )

        # Validate the rate, volume, and pitch parameters.
        self.validate_string_param(
            "voice",
            self.voice,
            r"^Microsoft Server Speech Text to Speech Voice \(.+,.+\)$",
        )
        self.validate_string_param("rate", self.rate, r"^[+-]\d+%$")
        self.validate_string_param("volume", self.volume, r"^[+-]\d+%$")
        self.validate_string_param("pitch", self.pitch, r"^[+-]\d+Hz$")


class UtilArgs(argparse.Namespace):
    """CLI arguments."""

    text: str
    file: str
    voice: str
    list_voices: bool
    rate: str
    volume: str
    pitch: str
    write_media: str
    write_subtitles: str
    proxy: str
