from dataclasses import dataclass
from os import getenv
from pathlib import Path
from typing import Any

from csirtmu.core.dataclass_config_loader import load_dataclass_config
from csirtmu.core.logging import LoggingConfig
from csirtmu.core.temporal import TemporalConfig as BaseTemporalConfig

from csirtmu.beta_temporal.constants import WorkflowReference
from csirtmu.beta_temporal.external_services.rt.structs import TransactionTypeEnum

BASE_DIR = Path(__file__).parent.parent.parent
ENV_PREFIX = "CSIRTMU_BETA"


@dataclass
class TemporalConfig(BaseTemporalConfig):
    periodic_tasks_queue: str = "periodic-workflows"
    beta_automatic_queue: str = "beta-automatic"


@dataclass
class NATSConfig:
    host: str
    username: str
    password: str
    subject: str
    subscriber_name: str = "beta_subscriber"


@dataclass
class Workflow:
    name: str
    events: list[str]
    params: dict[str, Any] | None = None

    @property
    def get_workflow_name(self) -> WorkflowReference:
        return WorkflowReference(self.name)

    @property
    def get_transaction_types(self) -> list[TransactionTypeEnum]:
        return [TransactionTypeEnum(event) for event in self.events]


@dataclass
class QueueConfig:
    name: str
    workflows: list[Workflow]
    temporal_queue: str


@dataclass
class TransactionRetentionConfig:
    use_jetstream: bool = False
    store_failed_transactions: bool = True


@dataclass
class RedisConfig:
    host: str
    username: str | None = None
    password: str | None = None
    port: int = 6379


@dataclass
class MonitoringConfig:
    dsn: str
    traces_sample_rate: float = 1.0
    profiles_sample_rate: float = 1.0


@dataclass
class Config:
    nats: NATSConfig
    temporal: TemporalConfig
    logging: LoggingConfig
    allow_metrics: bool
    metrics_port: int
    queue_mapping: list[QueueConfig]

    transaction_retention: TransactionRetentionConfig
    redis: RedisConfig
    monitoring: MonitoringConfig | None = None


class AppConfig:
    _config: Config | None = None

    @classmethod
    def get(cls, config_path: Path | None = None) -> Config:
        if cls._config is None:
            if config_path is None:  # pragma: no cover
                config_path = Path(getenv(f"{ENV_PREFIX}_CONFIG_PATH", (BASE_DIR / "config/config.yaml").resolve()))
            cls._config = load_dataclass_config(config_path, Config, ENV_PREFIX)
        return cls._config
