import os
from pathlib import Path
from pydantic_settings import BaseSettings
from dotenv import load_dotenv

# Load environment variables from .env in project root
BASE_DIR = Path(__file__).resolve().parent.parent.parent
env_path = BASE_DIR / ".env"
load_dotenv(dotenv_path=env_path)

class Settings(BaseSettings):
    ENV: str = "production"

    # Remote PostgreSQL
    DB_HOST: str = "localhost"
    DB_PORT: str = "5432"
    DB_USER: str = "postgres"
    DB_PASSWORD: str
    DB_NAME: str = "galaxiq_tenants"
    MASTER_DB_NAME: str = "galaxiq_master"
    
    # Redis configuration
    REDIS_HOST: str = "localhost"
    REDIS_PORT: int = 6379
    REDIS_USER: str = "default"
    REDIS_PASSWORD: str = ""
    REDIS_SSL: bool = False
    QUOTA_REDIS_CACHE_ENABLED: bool = True
    
    # Analytics / dbt
    DBT_EXECUTABLE: str = ""
    
    # OpenAI / Azure OpenAI
    OPENAI_API_KEY: str
    AZURE_OPENAI_ENDPOINT: str
    AZURE_OPENAI_API_VERSION: str = "2024-12-01-preview"
    
    # Firestore
    # Empty rather than required: only the chat's Firestore client reads it,
    # and a service running the catalogue alone should not have to carry the
    # chatbot's credentials just to construct its settings.
    FIRESTORE_PROJECT: str = ""
    FIRESTORE_DATABASE: str = "(default)"
    GOOGLE_APPLICATION_CREDENTIALS: str = "credentials.json"

    LLM_MODEL: str = "gpt-5.2-chat"
    EMBED_MODEL: str = "text-embedding-3-large"
    
    # Azure Blob Storage
    # Same reasoning: document storage and email images use this, neither of
    # which the catalogue touches.
    AZURE_STORAGE_CONNECTION_STRING: str = ""
    
    # CORS
    ALLOWED_ORIGINS: str = "*"

    # Email (SMTP). Sender must be the authenticated account or a configured alias.
    EMAIL_ENABLED: bool = False
    SMTP_HOST: str = ""
    SMTP_PORT: int = 465
    SMTP_SECURE: bool = True
    SMTP_EMAIL: str = ""
    SMTP_PASS: str = ""
    EMAIL_FROM: str = ""
    EMAIL_FROM_NAME: str = "GalaxiQ"
    EMAIL_MAX_PER_THREAD: int = 0   # 0 or less = no cap

    # Body-image generation. The image model sits on its own Azure resource,
    # separate from the chat model.
    EMAIL_BODY_IMAGE: bool = False
    AZURE_OPENAI_ENDPOINT_IMAGE: str = ""
    AZURE_OPENAI_API_KEY_IMAGE: str = ""
    AZURE_OPENAI_API_VERSION_IMAGE: str = "2024-02-01"
    AZURE_OPENAI_DEPLOYMENT_IMAGE: str = "gpt-image-2"

    # Where this service is reachable from a browser. Document links handed to
    # visitors point here rather than at blob storage, so they never expire and
    # the storage account stays private.
    PUBLIC_BASE_URL: str = "http://localhost:8001"

    # How much of a tenant's site to crawl. Sixty pages covers most shops'
    # catalogues; a shop with a very large catalogue needs far more, and
    # raising this costs an embedding call per chunk.
    CRAWL_MAX_PAGES: int = 60

    # Pages visited with zero product-pattern URL matches before the crawl
    # tries the one-time LLM link-classification fallback (see
    # website.py::_classify_product_links). Low enough to still leave most
    # of the page budget for the products it finds.
    CRAWL_PRODUCT_FALLBACK_AFTER_PAGES: int = 3

    # Caps each traversal batch so the crawl proceeds in small steps -- letting
    # the frontier re-sort (and the LLM fallback trigger) run multiple times per
    # crawl instead of one batch silently consuming the whole page budget before
    # either gets a chance to matter.
    CRAWL_BATCH_SIZE: int = 5

    # Notification Service
    NOTIFICATION_API_URL: str = "https://dev-api.galaxiq.ai/api/system/notification"
    SYSTEM_JWT_KEY: str = ""
    SYSTEM_SERVICE_NAME: str = "python-worker"

    SHOPIFY_CLIENT_ID: str = ""
    # Signs every callback and webhook HMAC; rotating it invalidates nothing
    # stored, but a leaked one lets anyone forge callbacks.
    SHOPIFY_CLIENT_SECRET: str = ""

    GOOGLE_CALENDAR_CLIENT_ID: str = ""
    GOOGLE_CALENDAR_CLIENT_SECRET: str = ""

    MS_TEAMS_CLIENT_ID: str = ""
    MS_TEAMS_CLIENT_SECRET: str = ""

    # Fernet key for every product source's credentials, not just Shopify.
    # Rotating this makes all stored credentials undecryptable, so merchants
    # would have to reconnect.
    SOURCE_CREDENTIALS_KEY: str = ""

    # Where the OAuth callback sends the merchant when the flow finishes.
    FRONTEND_URL: str = "http://localhost:5173/chat_ui.html"

    class Config:
        env_file = ".env"
        extra = "ignore"

settings = Settings()
