from __future__ import annotations
from typing import Optional, Any, ClassVar
from pydantic import SecretStr
from pydantic_settings import BaseSettings, SettingsConfigDict


class SibiBaseSettings(BaseSettings):
    """Base settings class with common configuration."""

    model_config = SettingsConfigDict(
        env_file=".env", env_file_encoding="utf-8", extra="ignore"
    )

    conf_name: ClassVar[str] = ""


class FsSettings(SibiBaseSettings):
    """Common filesystem settings."""

    fs_type: str = "s3"
    fs_path: str = "s3://dev-bucket/warehouse"
    fs_key: Optional[str] = None
    fs_secret: Optional[SecretStr] = None
    fs_endpoint: Optional[str] = None
    fs_token: Optional[SecretStr] = None
    fs_region: str = "us-east-1"

    def to_fsspec_options(self) -> dict[str, Any]:
        """Convert settings to fsspec compatible options dict."""
        if self.fs_type == "s3":
            opts: dict[str, Any] = {
                "key": self.fs_key,
                "secret": self.fs_secret.get_secret_value() if self.fs_secret else None,
                "skip_instance_cache": True,
                "use_listings_cache": False,
                "client_kwargs": {
                    "endpoint_url": self.fs_endpoint,
                    "region_name": self.fs_region,
                },
                "config_kwargs": {
                    "signature_version": "s3v4",
                    "s3": {"addressing_style": "path"},
                },
            }
            if self.fs_token:
                opts["token"] = self.fs_token.get_secret_value()
            return opts
        return {}


class WebDavSettings(SibiBaseSettings):
    """Common WebDAV settings."""

    fs_type: str = "webdav"
    fs_verify_ssl: bool = True
    fs_endpoint: str = ""
    fs_key: str = ""
    fs_secret: Optional[SecretStr] = None
    fs_token: Optional[SecretStr] = None

    # AWS specific config often mixed in WebDAV context in legacy
    aws_access_key_id: Optional[str] = None
    aws_secret_access_key: Optional[str] = None
    region_name: Optional[str] = None
    session_token: Optional[str] = None
    endpoint_url: Optional[str] = None

    model_config = SettingsConfigDict(env_prefix="WEBDAV_")

    def to_fsspec_options(self) -> dict[str, Any]:
        verify = self.fs_verify_ssl
        opts: dict[str, Any] = {
            "base_url": self.fs_endpoint,
            "username": self.fs_key,
            "password": self.fs_secret.get_secret_value() if self.fs_secret else "",
            "verify": verify,
        }
        if self.fs_token:
            opts["token"] = self.fs_token.get_secret_value()
        return opts


# --- Database Base Settings ---


class DatabaseSettings(SibiBaseSettings):
    """Generic SQL Database settings."""

    db_url: str | SecretStr = "sqlite:///:memory:"
    host: str = "localhost"
    port: int = 5432
    database: str = "default"
    user: str = "default"
    password: Optional[SecretStr] = None

    def to_legacy_dict(self) -> dict[str, Any]:
        return {
            "host": self.host,
            "port": self.port,
            "dbname": self.database,
            "user": self.user,
            "password": self.password.get_secret_value() if self.password else None,
            "db_url": self.db_url,
        }


class ClickhouseBaseSettings(SibiBaseSettings):
    """Base settings for ClickHouse connection."""

    interface: str = "http"
    host: str = "localhost"
    port: int = 8123
    database: str = "default"
    username: str = "default"
    password: Optional[SecretStr] = None

    def to_legacy_dict(self) -> dict[str, Any]:
        return {
            "interface": self.interface,
            "host": self.host,
            "port": self.port,
            "database": self.database,
            "username": self.username,
            "password": self.password.get_secret_value() if self.password else None,
        }


class RedisBaseSettings(SibiBaseSettings):
    """Base settings for Redis connection."""

    host: str = "localhost"
    port: int = 6379
    db: int = 0
    password: Optional[SecretStr] = None

    def to_legacy_dict(self) -> dict[str, Any]:
        return {
            "host": self.host,
            "port": self.port,
            "db": self.db,
            "password": self.password.get_secret_value() if self.password else None,
        }


class DbPoolSettings(SibiBaseSettings):
    """Base settings for SQLAlchemy connection pooling."""

    db_pool_size: int = 5
    db_max_overflow: int = 10
    db_pool_timeout: int = 30
    db_pool_recycle: int = 1800
