"""تنظیمات مرکزی برنامه با Pydantic v2 Settings.

همه مقادیر از متغیرهای محیطی (env) خوانده می‌شوند تا هیچ چیز در کد
hardcode نشود (نام برند، رنگ‌ها، آدرس‌ها و ...).
"""
from __future__ import annotations

from functools import lru_cache
from typing import Literal

from pydantic import Field
from pydantic_settings import BaseSettings, SettingsConfigDict


class Settings(BaseSettings):
    model_config = SettingsConfigDict(
        env_file=".env",
        env_file_encoding="utf-8",
        case_sensitive=False,
        extra="ignore",
    )

    # ---- General ----
    environment: Literal["development", "staging", "production", "test"] = "development"
    debug: bool = True
    log_level: str = "INFO"
    service_name: str = "core-service"
    api_v1_prefix: str = "/api/v1"

    # ---- Platform Branding (White-label) ----
    platform_name: str = "SuperApp"
    platform_support_email: str = "support@example.com"
    platform_primary_color: str = "#0284c7"
    platform_secondary_color: str = "#0f172a"
    # دامنه پایه برای تخصیص زیردامنه خودکار در onboarding (مثلاً tenant.slug + "." + این مقدار)
    platform_base_domain: str = Field(default="", validation_alias="PLATFORM_BASE_DOMAIN")

    # ---- Auto SSL (Let's Encrypt via nginx host) ----
    ssl_provision_enabled: bool = Field(default=False, validation_alias="SSL_PROVISION_ENABLED")
    ssl_provision_host: str = Field(default="", validation_alias="SSL_PROVISION_HOST")
    ssl_provision_user: str = Field(default="", validation_alias="SSL_PROVISION_USER")
    ssl_provision_password: str = Field(default="", validation_alias="SSL_PROVISION_PASSWORD")
    ssl_provision_script: str = Field(
        default="/opt/torbatyar/bin/provision_ssl.py",
        validation_alias="SSL_PROVISION_SCRIPT",
    )

    # ---- Database ----
    # آدرس async برای برنامه و sync برای Alembic.
    database_url: str = "postgresql+asyncpg://superapp:superapp_password@localhost:5432/core_platform_db"
    database_url_sync: str = "postgresql+psycopg://superapp:superapp_password@localhost:5432/core_platform_db"
    db_echo: bool = False
    db_pool_size: int = 10
    db_max_overflow: int = 20

    # ---- Redis ----
    redis_url: str = "redis://localhost:6379/0"
    feature_access_cache_ttl: int = 300
    tenant_metadata_cache_ttl: int = 300

    # ---- Celery ----
    celery_broker_url: str = "redis://localhost:6379/1"
    celery_result_backend: str = "redis://localhost:6379/2"

    # ---- Keycloak / SSO ----
    keycloak_enabled: bool = False
    keycloak_server_url: str = "http://localhost:8080"
    keycloak_public_url: str = Field(default="", validation_alias="KEYCLOAK_PUBLIC_URL")
    keycloak_realm: str = "superapp"
    keycloak_client_id: str = "core-service"
    keycloak_client_secret: str = "change-me"
    jwt_algorithm: str = "RS256"
    jwt_audience: str = "account"
    jwt_verify_signature: bool = False
    # اگر true باشد همه endpointهای محافظت‌شده نیازمند JWT معتبر هستند.
    auth_required: bool = False
    cors_origins: str = Field(
        default="http://localhost:3000,http://127.0.0.1:3000",
        validation_alias="CORS_ORIGINS",
    )

    # ---- Identity Service ----
    identity_service_url: str = "http://localhost:8001"

    # ---- Internal Service Tokens ----
    internal_token_secret: str = "change-me-internal-secret"

    # ---- OTP / Payamak SMS ----
    payamak_username: str = "9155105404"
    payamak_from: str = Field(default="9982004961", validation_alias="PAYAMAK_FROM")
    payamak_api_key: str = Field(default="", validation_alias="PAYAMAK_API_KEY")
    payamak_apikey: str = Field(default="", validation_alias="PAYAMAK_APIKEY")
    payamak_password: str = Field(default="", validation_alias="PAYAMAK_PASSWORD")
    payamak_body_id: int = Field(default=245189, validation_alias="PAYAMAK_BODY_ID")
    otp_expire_seconds: int = 120

    # ---- Platform bootstrap admins (OTP) ----
    platform_admin_mobiles: str = Field(
        default="",
        validation_alias="PLATFORM_ADMIN_MOBILES",
    )

    @property
    def platform_admin_mobile_set(self) -> set[str]:
        from app.utils.phone import normalize_mobile

        result: set[str] = set()
        for raw in self.platform_admin_mobiles.split(","):
            item = raw.strip()
            if not item:
                continue
            try:
                result.add(normalize_mobile(item))
            except ValueError:
                continue
        return result

    @property
    def payamak_auth_secret(self) -> str:
        """ApiKey در پارامتر password (طبق مستندات ملی‌پیامک)."""
        return (self.payamak_api_key or self.payamak_apikey or self.payamak_password).strip()

    @property
    def payamak_verification_body_id(self) -> int:
        """شناسه الگوی کد تأیید — همان PAYAMAK_BODY_ID در torbatkar-back."""
        return self.payamak_body_id

    # ---- Local JWT (OTP users) ----
    jwt_secret: str = "change-me-jwt-secret"
    jwt_access_token_expire_seconds: int = 3600
    jwt_refresh_token_expire_seconds: int = 604800

    @property
    def is_production(self) -> bool:
        return self.environment == "production"

    @property
    def keycloak_browser_url(self) -> str:
        return self.keycloak_public_url or self.keycloak_server_url

    @property
    def keycloak_public_realm_url(self) -> str:
        return f"{self.keycloak_browser_url}/realms/{self.keycloak_realm}"

    @property
    def cors_origin_list(self) -> list[str]:
        return [origin.strip() for origin in self.cors_origins.split(",") if origin.strip()]

    @property
    def jwks_url(self) -> str:
        """آدرس JWKS در Keycloak برای اعتبارسنجی امضای JWT."""
        return (
            f"{self.keycloak_server_url}/realms/{self.keycloak_realm}"
            "/protocol/openid-connect/certs"
        )


@lru_cache
def get_settings() -> Settings:
    """نمونه cache شده تنظیمات (singleton)."""
    return Settings()


settings = get_settings()
