"""Application-wide configuration: paths, image storage rules,
admin/email settings, cache windows and the shared logger."""
import logging
import mimetypes
import os
from datetime import datetime
from pathlib import Path


# Python's mimetype DB lacks webp on some installs; openpyxl needs it when
# embedding .webp images into Excel exports.
mimetypes.add_type("image/webp", ".webp")


try:
    from dotenv import load_dotenv
except ImportError:
    def load_dotenv(*args, **kwargs):
        pass


# This file moved from the project root into the `nexora` package, so one
# extra .parent is needed for BASE_DIR to keep resolving to the project
# root. Every path below (DB_PATH, STATIC_DIR, UPLOAD_DIR, IMAGE_ROOT,
# .env, .secret_key) therefore points at exactly the same place as before.
BASE_DIR = Path(__file__).resolve().parent.parent


DB_PATH = Path(os.environ.get("DB_PATH", BASE_DIR / "nexora.db"))


STATIC_DIR = BASE_DIR / "static"


UPLOAD_DIR = STATIC_DIR / "uploads"


# â”€â”€ Canonical image storage architecture (single source of truth) â”€â”€
# All image uploads land under static/Images/<Category>[/Game]/ and the DB
# stores paths RELATIVE to static/, e.g. "Images/Games/TEKKEN 7/poster.webp".
# Legacy rows store bare filenames that historically meant static/uploads/.
IMAGE_ROOT = STATIC_DIR / "Images"


CANONICAL_IMAGE_DIRS = {
    "logo": "Logo",                    # Images/Logo/Nexora Logo.webp
    "partners": "Partners",            # sponsor / partner logos
    "home": "Nexora Home",             # homepage hero / background
    "leadership": "Leadership",
    "gallery": "Gallery",              # gallery / memories
    "bank_qr": "Bank QR",              # admin-uploaded payment QR
    "rewards": "Tournament Rewards",   # prize pool banners & items
    "games": "Games",                  # Games/<Game Name>/ per-game subfolder
    "registrations": "Registrations",  # Registrations/<Game Name>/ â€” SENSITIVE
    "team": "Our Team",                # existing on-disk folder name (do not rename)
}


GAME_SUBFOLDER_CATEGORIES = {"games", "registrations"}


PROTECTED_IMAGE_PREFIXES = ("Images/Registrations/",)  # never publicly served


DEFAULT_SITE_LOGO = "Nexora Logo.png"


DEFAULT_HOME_BACKGROUND = "NexoraGame.png"


MAX_CONTENT_LENGTH = 8 * 1024 * 1024  # 8 MB transport cap


ALLOWED_IMAGE_EXTENSIONS = {"png", "jpg", "jpeg", "webp", "gif", "jfif"}


ALLOWED_IMAGE_MIME_TYPES = {"image/png", "image/jpeg", "image/webp", "image/gif"}


IMAGE_SIGNATURES = (
    b"\x89PNG\r\n\x1a\n",
    b"\xff\xd8\xff",
    b"GIF87a",
    b"GIF89a",
    b"RIFF",
)


try:
    load_dotenv(BASE_DIR / ".env")
except Exception:
    pass


APP_START_TS = int(datetime.now().timestamp())


# â"€â"€ Logging â"€â"€
logging.basicConfig(level=logging.INFO, format="%(asctime)s [%(levelname)s] %(message)s")


logger = logging.getLogger("nexora")


logger.info("STATIC_DIR = %s (exists=%s)", STATIC_DIR, STATIC_DIR.is_dir())


logger.info("IMAGE_ROOT = %s (exists=%s)", IMAGE_ROOT, IMAGE_ROOT.is_dir())


ADMIN_USERNAME = os.environ.get("ADMIN_USERNAME", "admin")


ADMIN_PASSWORD = os.environ.get("ADMIN_PASSWORD", "")


# SMTP credentials come ONLY from server-side environment variables (.env).
# Never hardcode them here. Preferred names: SMTP_EMAIL / SMTP_PASSWORD;
# legacy EMAIL_* names still work as a fallback.
ADMIN_EMAIL = os.environ.get("ADMIN_EMAIL", "")


PUBLIC_CACHE_SECONDS = max(0, int(os.environ.get("PUBLIC_CACHE_SECONDS", "0") or 0))


STATIC_CACHE_SECONDS = max(0, int(os.environ.get("STATIC_CACHE_SECONDS", "31536000") or 31536000))


PUBLIC_SITE_DOMAIN = os.environ.get("PUBLIC_SITE_DOMAIN", "").strip().lower()
SMTP_FROM_EMAIL = os.environ.get("SMTP_FROM_EMAIL", "").strip().lower()
SMTP_ALLOW_CROSS_DOMAIN = os.environ.get("SMTP_ALLOW_CROSS_DOMAIN", "0") == "1"


def _email_domain(address):
    if "@" not in address:
        return ""
    return address.rsplit("@", 1)[-1].strip().lower()


def _base_domain(domain):
    parts = (domain or "").strip(".").split(".")
    if len(parts) >= 2:
        return ".".join(parts[-2:])
    return domain


def _smtp_domain_aligned():
    """Fail closed when transactional mail would use an unrelated From domain.

    A site on nexoraesport.com sending From: info@another-domain.com can hurt
    deliverability and may look suspicious to DNS/mail reputation systems. Use
    SMTP_ALLOW_CROSS_DOMAIN=1 only after SPF/DKIM/DMARC are deliberately set.
    """
    if not PUBLIC_SITE_DOMAIN or not SMTP_FROM_EMAIL:
        return True
    return _base_domain(PUBLIC_SITE_DOMAIN) == _base_domain(_email_domain(SMTP_FROM_EMAIL))


EMAIL_DOMAIN_ALIGNED = _smtp_domain_aligned()


EMAIL_SENDING_ENABLED = (
    os.environ.get("EMAIL_SENDING_ENABLED", "0") == "1"
    and (EMAIL_DOMAIN_ALIGNED or SMTP_ALLOW_CROSS_DOMAIN)
)

if os.environ.get("EMAIL_SENDING_ENABLED", "0") == "1" and not EMAIL_SENDING_ENABLED:
    logger.warning(
        "Email sending disabled: SMTP_FROM_EMAIL domain is not aligned with PUBLIC_SITE_DOMAIN. "
        "Use a same-domain mailbox or set SMTP_ALLOW_CROSS_DOMAIN=1 after SPF/DKIM/DMARC are configured."
    )


# ──── Background email queue configuration ────
EMAIL_WORKER_CONCURRENCY = max(1, int(os.environ.get("EMAIL_WORKER_CONCURRENCY", "3") or 3))
PDF_WORKER_CONCURRENCY = max(1, int(os.environ.get("PDF_WORKER_CONCURRENCY", "2") or 2))
EMAIL_BATCH_SIZE = max(1, int(os.environ.get("EMAIL_BATCH_SIZE", "20") or 20))
EMAIL_RATE_LIMIT_PER_MINUTE = max(1, int(os.environ.get("EMAIL_RATE_LIMIT_PER_MINUTE", "60") or 60))
EMAIL_MAX_RETRIES = max(0, int(os.environ.get("EMAIL_MAX_RETRIES", "5") or 5))
EMAIL_POLL_INTERVAL = max(1, int(os.environ.get("EMAIL_POLL_INTERVAL", "5") or 5))
EMAIL_JOB_TIMEOUT = max(30, int(os.environ.get("EMAIL_JOB_TIMEOUT", "300") or 300))
EMAIL_OUTBOX_RETENTION_HOURS = max(1, int(os.environ.get("EMAIL_OUTBOX_RETENTION_HOURS", "72") or 72))
SMTP_TIMEOUT_SECONDS = max(5, int(os.environ.get("SMTP_TIMEOUT_SECONDS", "12") or 12))
