"""Settings, read from environment variables prefixed ORDERS_ (and an optional .env file)."""
from typing import Literal

from pydantic import Field, SecretStr, model_validator
from pydantic_settings import BaseSettings, SettingsConfigDict

DEV_JWT_SECRET = "dev-only-jwt-secret-change-me-0123456789"
DEV_WEBHOOK_SECRET = "dev-only-webhook-secret"


class Settings(BaseSettings):
    model_config = SettingsConfigDict(env_prefix="ORDERS_", env_file=".env", extra="ignore")

    environment: Literal["dev", "test", "production"] = "dev"
    database_url: str = "sqlite+aiosqlite:///./orders.db"
    create_tables: bool = True               # dev convenience; production runs migrations instead
    seed_demo_data: bool = True

    jwt_secret: SecretStr = SecretStr(DEV_JWT_SECRET)
    jwt_issuer: str = "orders-api"
    jwt_audience: str = "orders-clients"
    access_token_minutes: int = Field(15, ge=1, le=60)
    bcrypt_rounds: int = Field(12, ge=4, le=15)

    cors_origins: list[str] = ["http://localhost:5173"]
    docs_enabled: bool | None = None          # default: on, except in production

    rate_limit_per_minute: int = 120
    login_attempts_per_minute: int = 5

    webhook_url: str | None = None
    webhook_secret: SecretStr = SecretStr(DEV_WEBHOOK_SECRET)
    outbox_relay_enabled: bool = True         # tests switch it off and drive relay_once() directly
    outbox_poll_seconds: float = 1.0
    outbox_max_attempts: int = 8

    log_level: str = "INFO"

    @model_validator(mode="after")
    def _production_guards(self) -> "Settings":
        if self.environment == "production":
            if self.jwt_secret.get_secret_value() == DEV_JWT_SECRET:
                raise ValueError("ORDERS_JWT_SECRET must be set in production")
            if self.webhook_url and self.webhook_secret.get_secret_value() == DEV_WEBHOOK_SECRET:
                raise ValueError("ORDERS_WEBHOOK_SECRET must be set in production")
            if self.seed_demo_data:
                raise ValueError("demo data must not be seeded in production")
        if len(self.jwt_secret.get_secret_value()) < 32:
            raise ValueError("ORDERS_JWT_SECRET must be at least 32 characters")
        return self

    @property
    def show_docs(self) -> bool:
        return self.docs_enabled if self.docs_enabled is not None else self.environment != "production"
