from __future__ import annotations

import logging
from typing import Optional

from ..config import GatewayConfig
from ..settings import GatewaySettings, get_gateway_settings
from ..stores import (
    BillingStore,
    IdempotencyStore,
    InMemoryBillingStore,
    InMemoryIdempotencyStore,
    PostgresBillingStore,
    RedisIdempotencyStore,
)

logger = logging.getLogger(__name__)


class GatewayRuntime:
    """Runtime wiring for stores and configuration.

    Selects production drivers when configured, otherwise in-memory defaults.
    """

    def __init__(
        self,
        config: Optional[GatewayConfig] = None,
        billing_store: Optional[BillingStore] = None,
        idem_store: Optional[IdempotencyStore] = None,
        settings: Optional[GatewaySettings] = None,
    ) -> None:
        if settings is None and config is not None and config.settings is not None:
            settings = config.settings

        if config is None:
            settings = settings or get_gateway_settings()
            config = GatewayConfig.from_settings(settings)
        elif settings is None:
            settings = get_gateway_settings()

        self.settings = settings
        self.config = config
        self.billing_store = billing_store or self._init_billing_store()
        self.idem_store = idem_store or self._init_idem_store()

    def _init_billing_store(self) -> BillingStore:
        dsn = self.config.postgres_dsn
        if dsn:
            try:
                logger.info("Using PostgresBillingStore")
                return PostgresBillingStore(
                    dsn,
                    auto_init=self.config.auto_init,
                )
            except Exception as exc:
                raise RuntimeError("Failed to initialize Postgres billing store") from exc
        return InMemoryBillingStore()

    def _init_idem_store(self) -> IdempotencyStore:
        url = self.config.redis_url
        if url:
            try:
                import redis  # type: ignore

                client = redis.Redis.from_url(url)
                logger.info("Using RedisIdempotencyStore")
                return RedisIdempotencyStore(client)
            except Exception as exc:
                raise RuntimeError("Failed to initialize Redis idempotency store") from exc
        return InMemoryIdempotencyStore()


__all__ = ["GatewayRuntime"]
