import os
from dataclasses import dataclass
from typing import Optional


@dataclass
class ElasticsearchConfig:
    url: str
    username: Optional[str]
    password: Optional[str]


@dataclass
class BrokerConfig:
    url: str


@dataclass
class ResultBackendConfig:
    url: str
    sentinel_mode: bool


@dataclass
class Config:
    elasticsearch: ElasticsearchConfig
    broker: BrokerConfig
    result_backend: ResultBackendConfig


class ConfigBuilder:
    """Logging service configuration"""

    es_url: str = "http://localhost:9200"
    broker_url: str = "amqp://rabbitmq:rabbitmq@localhost:5672/"
    result_backend: str = "redis://localhost:6379"
    sentinel_mode: bool = False

    @classmethod
    def __build_config(
        cls,
        es_url: str,
        es_username: Optional[str],
        es_password: Optional[str],
        broker_url: str,
        result_backend: str,
        sentinel_mode: bool,
    ) -> Config:
        es_config = ElasticsearchConfig(
            url=es_url,
            username=es_username,
            password=es_password,
        )
        broker_config = BrokerConfig(url=broker_url)
        result_backend_config = ResultBackendConfig(
            url=result_backend,
            sentinel_mode=sentinel_mode,
        )
        return Config(
            elasticsearch=es_config,
            broker=broker_config,
            result_backend=result_backend_config,
        )

    @classmethod
    def from_env(cls) -> Config:
        es_url = os.getenv("ES_URL")
        es_username = os.getenv("ES_USERNAME", None)
        es_password = os.getenv("ES_PASSWORD", None)

        amqp_broker = os.getenv("AMQP_BROKER")
        amqp_port = os.getenv("AMQP_PORT")
        amqp_user = os.getenv("AMQP_USER")
        amqp_pass = os.getenv("AMQP_PASSWORD")

        redis_host = os.getenv("REDIS_HOST")
        redis_port = os.getenv("REDIS_PORT")
        sentinel_mode = True if os.getenv("REDIS_SENTINEL", "False") == "True" else False  # type: ignore

        if any([amqp_broker, amqp_port, amqp_user, amqp_pass]):
            cls.broker_url = f"amqp://{amqp_user}:{amqp_pass}@{amqp_broker}:{amqp_port}/"

        if any([redis_host, redis_port]):
            cls.result_backend = (
                f"{'sentinel' if sentinel_mode else 'redis'}://{redis_host}:{redis_port}"
            )

        cls.sentinel_mode = sentinel_mode

        return cls.__build_config(
            es_url=es_url or cls.es_url,
            es_username=es_username,
            es_password=es_password,
            broker_url=cls.broker_url,
            result_backend=cls.result_backend,
            sentinel_mode=sentinel_mode or cls.sentinel_mode,
        )
