"""
Configuration centrale — lit les variables d'environnement une seule fois.

⚠️  CLÉ API STORYFACE (thèmes IA « photo magique ») : STORYFACE_API_KEY dans
    backend/.env, puis redémarrer le service.

APP_ENV=production active les contrôles de démarrage stricts (voir
core.security.validate_production_config) : mots de passe par défaut, secret
JWT absent, Stripe non configuré → le service refuse de démarrer.
"""
import os
from pathlib import Path

from dotenv import load_dotenv

load_dotenv()


def _bool(name: str, default: str = "false") -> bool:
    return os.getenv(name, default).strip().lower() in ("1", "true", "yes", "on")


APP_ENV: str = os.getenv("APP_ENV", "development").strip().lower()
IS_PRODUCTION: bool = APP_ENV == "production"

# ─── Réseau / serveur ──────────────────────────────────────────────────────────
PORT: int = int(os.getenv("PORT", "3002"))
HOST: str = os.getenv("HOST", "0.0.0.0")
CORS_ORIGINS: list[str] = [s.strip() for s in os.getenv(
    "CORS_ORIGINS", "http://localhost:5174,http://localhost:5173").split(",") if s.strip()]
# IP/CIDR des reverse proxies de confiance : seuls ceux-là peuvent fixer
# X-Forwarded-For. Sans cela le rate limiting verrait l'IP du proxy pour tout le monde.
TRUSTED_PROXIES: list[str] = [s.strip() for s in os.getenv("TRUSTED_PROXIES", "127.0.0.1,::1").split(",") if s.strip()]

# ─── Chemins fichiers ──────────────────────────────────────────────────────────
PHOTOS_DIR:   Path = Path(os.getenv("PHOTOS_DIR",   "./photos")).resolve()
THUMBS_DIR:   Path = Path(os.getenv("THUMBS_DIR",   "./thumbs")).resolve()
INCOMING_DIR: Path = Path(os.getenv("INCOMING_DIR", "./incoming")).resolve()
BACKUPS_DIR:  Path = Path(os.getenv("BACKUPS_DIR",  "./backups")).resolve()
# Example visuals of the catalogue products (one folder per school). Marketing images: no personal data.
PRODUCTS_DIR: Path = Path(os.getenv("PRODUCTS_DIR", "./products")).resolve()
LOG_DIR:      Path = Path(os.getenv("LOG_DIR",      "./logs")).resolve()

# ─── Base de données MySQL (mêmes variables que hec-photo-app) ─────────────────
MYSQL_HOST:      str = os.getenv("MYSQL_HOST", "127.0.0.1")
MYSQL_PORT:      int = int(os.getenv("MYSQL_PORT", "3306"))
MYSQL_USER:      str = os.getenv("MYSQL_USER", "meeconic")
MYSQL_PASSWORD:  str = os.getenv("MYSQL_PASSWORD", "")
MYSQL_DB:        str = os.getenv("MYSQL_DB", "meeconic")
MYSQL_POOL_SIZE: int = int(os.getenv("MYSQL_POOL_SIZE", "10"))

# ─── Génération IA storyface (photo magique) ───────────────────────────────────
AUTH_SERVER_URL:      str = os.getenv("AUTH_SERVER_URL", "https://auth.storyface.ai").rstrip("/")
STORYFACE_API_KEY:    str = os.getenv("STORYFACE_API_KEY", "")
STORYFACE_SHORT_CODE: str = os.getenv("STORYFACE_SHORT_CODE", "meeconic")

# ─── Organizer / FTP (ingestion des photos du photographe) ─────────────────────
FTP_HOST:            str   = os.getenv("FTP_HOST", "")
FTP_PORT:            int   = int(os.getenv("FTP_PORT", "21"))
ORGANIZER_ENABLED:   bool  = _bool("ORGANIZER_ENABLED", "true")
ORGANIZER_POLL_SECS: float = float(os.getenv("ORGANIZER_POLL_SECS", "60"))
FTP_STABLE_SECS:     float = float(os.getenv("FTP_STABLE_SECS", "1.5"))
PURGE_MIN_AGE_SECS:  float = float(os.getenv("PURGE_MIN_AGE_SECS", "30"))

# ─── Rétention RGPD ────────────────────────────────────────────────────────────
# Valeur par défaut ; chaque école peut la surcharger (réglage « rgpd_days »).
PHOTO_RETENTION_DAYS: int = int(os.getenv("PHOTO_RETENTION_DAYS", "60"))
# Au-delà de ce nombre de fichiers supprimés en un cycle, une alerte e-mail part.
RGPD_ALERT_THRESHOLD: int = int(os.getenv("RGPD_ALERT_THRESHOLD", "200"))

IMAGE_EXTENSIONS = {".jpg", ".jpeg", ".png", ".webp", ".JPG", ".JPEG", ".PNG", ".WEBP"}

# ─── Paiement Stripe ───────────────────────────────────────────────────────────
STRIPE_SECRET_KEY:     str = os.getenv("STRIPE_SECRET_KEY", "")
STRIPE_WEBHOOK_SECRET: str = os.getenv("STRIPE_WEBHOOK_SECRET", "")
# Commandes jamais payées : annulées (et PaymentIntent annulé) après N heures.
UNPAID_ORDER_TTL_HOURS: int = int(os.getenv("UNPAID_ORDER_TTL_HOURS", "24"))

# ─── Sécurité ──────────────────────────────────────────────────────────────────
ADMIN_PASSWORD:   str = os.getenv("ADMIN_PASSWORD", "")
ADMIN_JWT_SECRET: str = os.getenv("ADMIN_JWT_SECRET", "")
MEDIA_SECRET:     str = os.getenv("MEDIA_SECRET", "")   # signature des URLs photos (défaut : dérivé du secret JWT)
MEDIA_URL_TTL_SECS:    int = int(os.getenv("MEDIA_URL_TTL_SECS", "7200"))      # aperçus : 2 h
DOWNLOAD_URL_TTL_SECS: int = int(os.getenv("DOWNLOAD_URL_TTL_SECS", "86400"))  # téléchargements : 24 h
# Total size of the HD originals attached to the order e-mail; above it they are not attached and the
# family downloads them from "My orders". Measured on the raw files: base64 adds ~33 %, so 25 MB of photos is
# a ~33 MB message. A server that refuses it is handled (the confirmation is resent without the files).
EMAIL_ATTACH_MAX_MB: int = int(os.getenv("EMAIL_ATTACH_MAX_MB", "25"))

# ─── Prix par défaut (copiés dans chaque nouvelle école, modifiables dans l'admin) ──
DEFAULT_PRICES = {
    "price_print_10x15":   float(os.getenv("PRICE_PRINT_10X15",   "9")),
    "price_print_20x30":   float(os.getenv("PRICE_PRINT_20X30",   "14")),
    "price_digital":       float(os.getenv("PRICE_DIGITAL",       "7")),
    "price_pack":          float(os.getenv("PRICE_PACK",          "14")),
    "price_magic_print":   float(os.getenv("PRICE_MAGIC_PRINT",   "14")),
    "price_magic_digital": float(os.getenv("PRICE_MAGIC_DIGITAL", "9")),
    "price_magic_pack":    float(os.getenv("PRICE_MAGIC_PACK",    "20")),
}

# ─── Observabilité ─────────────────────────────────────────────────────────────
SENTRY_DSN:  str = os.getenv("SENTRY_DSN", "")
ALERT_EMAIL: str = os.getenv("ALERT_EMAIL", "") or os.getenv("COMPANY_NOTIFICATION_EMAIL", "")
ALERT_COOLDOWN_SECS: int = int(os.getenv("ALERT_COOLDOWN_SECS", "3600"))
LOG_LEVEL: str = os.getenv("LOG_LEVEL", "INFO").upper()

# ─── Processus ─────────────────────────────────────────────────────────────────
# Les tâches de fond (nettoyage, backup, organizer, surveillance) ne tournent que
# sur UN worker à la fois (élection par verrou en base) : lancer plusieurs workers
# uvicorn est sans danger.
BACKGROUND_TASKS_ENABLED: bool = _bool("BACKGROUND_TASKS_ENABLED", "true")


# ─── Protección de caras en servidor (StoryFace KIS, como hec-photo-app) ───────
KIS_API_URL: str = os.getenv("KIS_API_URL", "https://auth.storyface.ai/api/v2/kis/apply_effect")
KIS_PARALLEL_MAX: int = max(1, int(os.getenv("KIS_PARALLEL_MAX", "2")))
# Reintentos con backoff de las llamadas a StoryFace (ver utils/retry.py)
SF_RETRY_ATTEMPTS: int = max(1, int(os.getenv("SF_RETRY_ATTEMPTS", "3")))
SF_RETRY_BASE_DELAY: float = float(os.getenv("SF_RETRY_BASE_DELAY", "3.0"))

# ─── Organizer (lector de QR) ──────────────────────────────────────────────────
# Espera tras el último evento de disco antes de organizar, para no arrancar a mitad de una tanda FTP.
WATCHDOG_DEBOUNCE_SECS: float = float(os.getenv("WATCHDOG_DEBOUNCE_SECS", "5"))
# Tras un fallo del ciclo se espera esto (con backoff hasta 120 s). El organizador NUNCA se rinde.
ORGANIZER_RETRY_SECS: float = float(os.getenv("ORGANIZER_RETRY_SECS", "10"))
# Hay fotos esperando y no se ha movido nada en este tiempo → "atascado" (stalled).
ORGANIZER_STALL_SECS: float = float(os.getenv("ORGANIZER_STALL_SECS", "300"))
# Cada cuánto el gestor mira si hay colegios nuevos o desactivados.
ORGANIZER_RESCAN_SECS: float = float(os.getenv("ORGANIZER_RESCAN_SECS", "30"))

# ─── Papelera de fotos (borrar = mover, recuperable) ───────────────────────────
TRASH_RETENTION_DAYS: int = int(os.getenv("TRASH_RETENTION_DAYS", "30"))

# Huso del evento: las búsquedas "por fecha y hora" se hacen en la hora del colegio, no en la del servidor (UTC en un VPS).
EVENT_TIMEZONE: str = os.getenv("EVENT_TIMEZONE", "Europe/Paris")

# Escaneo de fotogramas desde el portal (cámara del móvil de la familia).
SCAN_MAX_IMAGE_BYTES: int = int(os.getenv("SCAN_MAX_IMAGE_BYTES", str(3 * 1024 * 1024)))

# Esquema de la redirección /r/{código} (tras un proxy el scheme interno llega como http).
QR_REDIRECT_SCHEME: str = os.getenv("QR_REDIRECT_SCHEME", "https")
