from functools import lru_cache

from pydantic import computed_field
from pydantic_settings import BaseSettings, SettingsConfigDict


class Settings(BaseSettings):
    app_name: str = "Hospitality Backend Hub"
    app_environment: str = "development"
    backend_hub_cors_origins: str = "http://localhost:3000,http://localhost:3100,http://localhost:3200,http://localhost:3300"
    backend_hub_public_url: str = "http://localhost:8101"
    portal_public_url: str = "http://localhost:3000"
    prenotazioni_frontend_public_url: str = "http://localhost:3100"
    prenotazioni_backend_public_url: str = "http://localhost:8100"
    menu_legacy_public_url: str = "http://localhost:3200"
    ordini_frontend_public_url: str = "http://localhost:3300"
    ordini_backend_public_url: str = "http://localhost:8200"
    llm_base_url: str = "https://api.groq.com/openai/v1"
    llm_api_key: str | None = None
    llm_proxy_internal_token: str | None = None
    llm_request_timeout_seconds: float = 30.0
    assistant_display_name: str = "Assistente Locale"
    assistant_model: str | None = "openai/gpt-oss-120b"
    assistant_planner_model: str | None = "qwen/qwen3-32b"
    assistant_synthesis_model: str | None = "openai/gpt-oss-120b"
    assistant_fallback_model: str | None = "openai/gpt-oss-20b"
    assistant_max_tokens: int = 8000
    assistant_reasoning_effort: str | None = "low"
    assistant_include_reasoning: bool = False
    assistant_temperature: float = 0.2
    assistant_timezone: str = "Europe/Rome"
    assistant_data_request_timeout_seconds: float = 15.0
    assistant_prenotazioni_internal_url: str = "http://prenotazioni-backend:8000"
    assistant_menu_locale_data_path: str = "/app/data/baco_locale-data.js"
    assistant_system_prompt: str = (
        "Sei l'assistente operativo interno del locale. Rispondi sempre in italiano, con tono sobrio, "
        "pratico e orientato all'azione. Tratta ogni informazione come confidenziale. Se mancano dati "
        "operativi reali, dillo chiaramente e proponi il prossimo passo utile."
    )
    assistant_operational_context: str = (
        "Il backend-hub centralizzera' progressivamente dati sensibili, policy operative e contesto aziendale."
    )
    push_vapid_private_key_file: str = "/data/push-vapid-private.pem"
    push_vapid_subject: str = "mailto:admin@powerup.cool"
    google_workspace_client_id: str | None = None
    google_workspace_client_secret: str | None = None
    google_workspace_redirect_path: str = "/google-workspace/oauth/callback"
    google_workspace_scopes: str = (
        "openid,"
        "https://www.googleapis.com/auth/userinfo.email,"
        "https://www.googleapis.com/auth/documents,"
        "https://www.googleapis.com/auth/spreadsheets,"
        "https://www.googleapis.com/auth/drive"
    )
    google_workspace_state_file: str = "/tmp/google_workspace_state.json"
    google_workspace_request_timeout_seconds: float = 20.0
    google_workspace_sheet_preview_max_rows: int = 5000
    google_document_ai_project_id: str | None = None
    google_document_ai_location: str = "eu"
    google_document_ai_ocr_processor_id: str | None = None
    google_document_ai_invoice_processor_id: str | None = None
    google_document_ai_service_account_file: str | None = None
    google_document_ai_request_timeout_seconds: float = 30.0
    fiscal_document_inbox_poll_seconds: int = 900
    tenancy_registry_database: str = "/data/platform_registry.sqlite3"
    tenancy_databases_dir: str = "/data/tenants"
    tenancy_session_duration_hours: int = 168
    menu_asset_storage_dir: str = "/data/menu-assets"
    fiscal_document_storage_dir: str = "/data/fiscal-documents"
    menu_asset_max_upload_bytes: int = 15728640
    menu_asset_pdf_max_pages: int = 12
    menu_asset_extracted_text_max_chars: int = 24000
    menu_asset_analysis_max_chars: int = 4000
    menu_asset_context_max_chars: int = 8000
    menu_asset_ocr_languages: str = "ita+eng"

    model_config = SettingsConfigDict(env_file=".env", env_file_encoding="utf-8", case_sensitive=False)

    @computed_field  # type: ignore[prop-decorator]
    @property
    def cors_origins_list(self) -> list[str]:
        return [item.strip() for item in self.backend_hub_cors_origins.split(",") if item.strip()]

    @computed_field  # type: ignore[prop-decorator]
    @property
    def google_workspace_scopes_list(self) -> list[str]:
        return [item.strip() for item in self.google_workspace_scopes.split(",") if item.strip()]

    @computed_field  # type: ignore[prop-decorator]
    @property
    def google_workspace_redirect_uri(self) -> str:
        return f"{self.backend_hub_public_url.rstrip('/')}{self.google_workspace_redirect_path}"

    @computed_field  # type: ignore[prop-decorator]
    @property
    def is_production(self) -> bool:
        return self.app_environment.strip().lower() in {"prod", "production"}

    def validate_runtime(self) -> None:
        if not self.is_production:
            return
        if not (self.llm_proxy_internal_token or "").strip():
            raise RuntimeError("LLM_PROXY_INTERNAL_TOKEN e' obbligatorio in produzione")
        if self.llm_base_url.rstrip("/") == "https://api.groq.com/openai/v1" and not (self.llm_api_key or "").strip():
            raise RuntimeError("LLM_API_KEY e' obbligatoria quando LLM_BASE_URL punta a Groq")


@lru_cache
def get_settings() -> Settings:
    return Settings()
