from pydantic import Field
from pydantic_settings import BaseSettings, SettingsConfigDict


def build_database_url(
    *,
    user: str,
    password: str,
    host: str,
    port: int,
    database: str,
) -> str:
    return f"postgresql+asyncpg://{user}:{password}@{host}:{port}/{database}"


class Settings(BaseSettings):
    app_env: str = "development"
    database_url_override: str | None = Field(default=None, alias="DATABASE_URL")
    postgres_user: str = "headquarter"
    postgres_password: str = "headquarter"
    postgres_host: str = "postgres"
    postgres_port: int = 5432
    postgres_db: str = "headquarter"

    # Domain configuration
    api_domain: str = "localhost"
    web_domain: str = "localhost"
    authentik_domain: str = "authentik.local"

    # Public URLs (constructed from domains if not explicitly set)
    api_public_url: str | None = None
    web_public_url: str | None = None

    # Authentik configuration - no hardcoded URLs
    authentik_client_id: str = "headquarter-web"
    authentik_client_secret: str = "change-me"
    # Authentik application slug used in URLs (e.g., "headquarter-web")
    # This is different from the OAuth client_id which may be a UUID
    authentik_application_slug: str = "headquarter-web"
    authentik_authorize_url: str | None = None
    authentik_token_url: str | None = None
    authentik_jwks_url: str | None = None
    authentik_issuer: str | None = None
    authentik_audience: str = "headquarter-web"

    # Session configuration
    session_secret: str = "change-me-session-secret"
    session_ttl_hours: int = 24

    # Internal JWT configuration (used for service-to-service tokens)
    jwt_algorithm: str = "HS256"
    access_token_ttl_minutes: int = 15
    refresh_token_ttl_days: int = 7

    # Repository storage
    repo_base_path: str = "/data/repos"
    
    # Tool instance storage
    instance_base_path: str = "/data/instances"



    model_config = SettingsConfigDict(env_file=".env", extra="ignore", populate_by_name=True)

    @property
    def database_url(self) -> str:
        if self.database_url_override:
            return self.database_url_override

        return build_database_url(
            user=self.postgres_user,
            password=self.postgres_password,
            host=self.postgres_host,
            port=self.postgres_port,
            database=self.postgres_db,
        )

    @property
    def api_base_url(self) -> str:
        if self.api_public_url:
            return self.api_public_url
        protocol = "https" if self.app_env == "production" else "http"
        port = "" if self.app_env == "production" else ":8000"
        return f"{protocol}://{self.api_domain}{port}"

    @property
    def web_base_url(self) -> str:
        if self.web_public_url:
            return self.web_public_url
        protocol = "https" if self.app_env == "production" else "http"
        port = "" if self.app_env == "production" else ":3000"
        return f"{protocol}://{self.web_domain}{port}"

    @property
    def authentik_base_url(self) -> str:
        protocol = "https" if self.app_env == "production" else "http"
        return f"{protocol}://{self.authentik_domain}"

    @property
    def resolved_authentik_authorize_url(self) -> str:
        if self.authentik_authorize_url:
            return self.authentik_authorize_url
        return f"{self.authentik_base_url}/application/o/authorize/"

    @property
    def resolved_authentik_token_url(self) -> str:
        if self.authentik_token_url:
            return self.authentik_token_url
        return f"{self.authentik_base_url}/application/o/token/"

    @property
    def resolved_authentik_jwks_url(self) -> str:
        if self.authentik_jwks_url:
            return self.authentik_jwks_url
        return f"{self.authentik_base_url}/application/o/{self.authentik_application_slug}/jwks/"

    @property
    def resolved_authentik_issuer(self) -> str:
        if self.authentik_issuer:
            return self.authentik_issuer
        return f"{self.authentik_base_url}/application/o/{self.authentik_application_slug}/"

    @property
    def cookie_secure(self) -> bool:
        return self.app_env == "production"

    @property
    def cookie_samesite(self) -> str:
        if self.app_env == "production":
            return "strict"

        return "lax"

    @property
    def cookie_domain(self) -> str | None:
        """Return the parent domain for cross-subdomain cookies.

        E.g., api.example.com and app.example.com both share .example.com
        """
        if self.app_env != "production":
            return None

        # Extract parent domain from api_domain
        # e.g., "api.headquarter.commumedia.org" -> ".headquarter.commumedia.org"
        parts = self.api_domain.split(".")
        if len(parts) >= 3:
            return "." + ".".join(parts[1:])
        return None
