import datetime
from dataclasses import dataclass, field
from os import getenv
from pathlib import Path

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.core.temporal.s3 import S3Config
from sqlalchemy import URL

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


@dataclass(unsafe_hash=True)
class DatabaseConfig:
    username: str
    password: str
    host: str
    port: int
    database: str
    pool_size: int = 5
    max_overflow: int = 10
    timeout: float = 30.0
    use_lifo: bool = False

    @property
    def engine_url(self) -> URL:
        return URL.create(
            "postgresql+psycopg",
            username=self.username,
            password=self.password,
            host=self.host,
            port=self.port,
            database=self.database,
        )


@dataclass
class TemporalConfig(BaseTemporalConfig):
    schedule_interval: int
    schedule_offset: int = 0


@dataclass
class AliasSyncConfig:
    url: str
    sync_from_alias_file: bool = False


@dataclass
class Token:
    token: str
    name: str


@dataclass
class AuthConfig:
    tokens: list[Token]


@dataclass
class CorsConfig:
    allowed_origins: list[str]
    allowed_methods: list[str]
    allowed_headers: list[str]


@dataclass(unsafe_hash=True, kw_only=True)
class Config:
    allowed_hosts: list[str] = field(hash=False)
    cors: CorsConfig = field(hash=False)
    auth: AuthConfig
    temporal: TemporalConfig
    logging: LoggingConfig
    s3: S3Config
    allow_metrics: bool = True
    metrics_port: int = 9000
    database: DatabaseConfig
    workflow_id: str
    alias_sync: AliasSyncConfig
    s3_listen_timeout: int = int(datetime.timedelta(hours=24).total_seconds())
    dry_run: bool = False


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(
                        ENV_PREFIX + "_CONFIG_PATH",
                        (BASE_DIR / "config/config.yaml").resolve(),
                    )
                )
            cls._config = load_dataclass_config(config_path, Config, ENV_PREFIX)
        return cls._config
