from pathlib import Path
from typing import Optional
from urllib.parse import quote_plus
from pydantic_settings import BaseSettings, SettingsConfigDict


class Settings(BaseSettings):
    PROJECT_NAME: str = "TJWater Server"
    ENVIRONMENT: str = "local"
    API_V1_STR: str = "/api/v1"

    # JWT 配置
    SECRET_KEY: str = (
        "your-secret-key-here-change-in-production-use-openssl-rand-hex-32"
    )
    ALGORITHM: str = "HS256"
    ACCESS_TOKEN_EXPIRE_MINUTES: int = 30
    REFRESH_TOKEN_EXPIRE_DAYS: int = 7

    # 数据加密密钥 (使用 Fernet)
    ENCRYPTION_KEY: str = ""  # 必须从环境变量设置
    DATABASE_ENCRYPTION_KEY: str = ""  # project_databases.dsn_encrypted 专用

    # Database Config (PostgreSQL)
    DB_NAME: str = "tjwater"
    DB_HOST: str = "localhost"
    DB_PORT: str = "5432"
    DB_USER: str = "postgres"
    DB_PASSWORD: str = "password"

    # Database Config (TimescaleDB)
    TIMESCALEDB_DB_NAME: str = "tjwater"
    TIMESCALEDB_DB_HOST: str = "localhost"
    TIMESCALEDB_DB_PORT: str = "5433"
    TIMESCALEDB_DB_USER: str = "postgres"
    TIMESCALEDB_DB_PASSWORD: str = "password"

    # Metadata Database Config (PostgreSQL)
    METADATA_DB_NAME: str = "system_hub"
    METADATA_DB_HOST: str = "localhost"
    METADATA_DB_PORT: str = "5432"
    METADATA_DB_USER: str = "postgres"
    METADATA_DB_PASSWORD: str = "password"

    METADATA_DB_POOL_SIZE: int = 5
    METADATA_DB_MAX_OVERFLOW: int = 10

    PROJECT_PG_CACHE_SIZE: int = 50
    PROJECT_TS_CACHE_SIZE: int = 50
    PROJECT_PG_POOL_SIZE: int = 5
    PROJECT_PG_MAX_OVERFLOW: int = 10
    PROJECT_TS_POOL_MIN_SIZE: int = 1
    PROJECT_TS_POOL_MAX_SIZE: int = 10

    # Keycloak JWT (optional override)
    KEYCLOAK_PUBLIC_KEY: str = ""
    KEYCLOAK_ALGORITHM: str = "RS256"
    KEYCLOAK_AUDIENCE: str = ""

    @property
    def SQLALCHEMY_DATABASE_URI(self) -> str:
        db_password = quote_plus(self.DB_PASSWORD)
        return f"postgresql://{self.DB_USER}:{db_password}@{self.DB_HOST}:{self.DB_PORT}/{self.DB_NAME}"

    @property
    def METADATA_DATABASE_URI(self) -> str:
        metadata_password = quote_plus(self.METADATA_DB_PASSWORD)
        return (
            f"postgresql+psycopg://{self.METADATA_DB_USER}:{metadata_password}"
            f"@{self.METADATA_DB_HOST}:{self.METADATA_DB_PORT}/{self.METADATA_DB_NAME}"
        )

    model_config = SettingsConfigDict(
        env_file=Path(__file__).resolve().parents[2] / ".env",
        extra="ignore",
    )


settings = Settings()


def get_pgconn_string(
    db_name: Optional[str] = None,
    db_host: Optional[str] = None,
    db_port: Optional[str] = None,
    db_user: Optional[str] = None,
    db_password: Optional[str] = None,
) -> str:
    """Return PostgreSQL connection string in psycopg conninfo format."""
    resolved_db_name = db_name or settings.DB_NAME
    resolved_db_host = db_host or settings.DB_HOST
    resolved_db_port = db_port or settings.DB_PORT
    resolved_db_user = db_user or settings.DB_USER
    resolved_db_password = db_password or settings.DB_PASSWORD
    return (
        f"dbname={resolved_db_name} host={resolved_db_host} port={resolved_db_port} "
        f"user={resolved_db_user} password={resolved_db_password}"
    )


def get_pg_config() -> dict:
    """Return PostgreSQL configuration except password."""
    return {
        "name": settings.DB_NAME,
        "host": settings.DB_HOST,
        "port": settings.DB_PORT,
        "user": settings.DB_USER,
    }


def get_pg_password() -> str:
    """Return PostgreSQL password (use with care)."""
    return settings.DB_PASSWORD
