from .base import *
import os

DEBUG = False

# ── Allowed hosts (read from .env) ────────────────────────────────────────────
# Already set in base.py via env.list('ALLOWED_HOSTS')

# ── Database ──────────────────────────────────────────────────────────────────
# Reads DATABASE_URL from .env — supports PostgreSQL and SQLite
# No default. A production install with no DATABASE_URL used to fall back to
# SQLite and fail deep inside a migration with a version error, which reads like
# a broken build rather than a missing line in .env.
_DATABASE_URL = env('DATABASE_URL', default='')
if not _DATABASE_URL:
    from django.core.exceptions import ImproperlyConfigured
    raise ImproperlyConfigured(
        'DATABASE_URL is not set in .env. Expected something like:\n'
        '    DATABASE_URL=postgres://user:password@127.0.0.1:5432/dbname'
    )
DATABASES = {'default': env.db_url_config(_DATABASE_URL)}

# On SQLite, switch to write-ahead logging so reads are not blocked by a write,
# and wait rather than failing when two writes collide. Without this, a busy
# moment produces "database is locked" errors. Ignored on PostgreSQL.
if 'sqlite' in DATABASES['default'].get('ENGINE', ''):
    DATABASES['default'].setdefault('OPTIONS', {})
    DATABASES['default']['OPTIONS'].update({
        'timeout': 20,
        'transaction_mode': 'IMMEDIATE',
        'init_command': (
            'PRAGMA journal_mode=WAL;'
            'PRAGMA synchronous=NORMAL;'
            'PRAGMA busy_timeout=20000;'
        ),
    })

# ── Cache (file-based — shared across all Gunicorn workers) ──────────────────
CACHES = {
    'default': {
        'BACKEND': 'django.core.cache.backends.filebased.FileBasedCache',
        # Inside the install, owned by this site's user. A shared path under
        # /tmp is owned by whichever process creates it first, so the second
        # site on the box gets Permission denied, and both can read each
        # other's cached values.
        'LOCATION': env('CACHE_DIR', default=str(BASE_DIR / '.cache')),
    }
}
SESSION_ENGINE = 'django.contrib.sessions.backends.db'

# ── Static & Media files ──────────────────────────────────────────────────────
# These default to this install's own directories. Pointing them at a fixed
# path is how one site ends up writing into another site's folders.
STATIC_ROOT = env('STATIC_ROOT', default=str(BASE_DIR / 'staticfiles'))
MEDIA_ROOT  = env('MEDIA_ROOT',  default=str(BASE_DIR / 'media'))
STATIC_URL  = '/static/'
MEDIA_URL   = '/media/'

# WhiteNoise compressed static files
STATICFILES_STORAGE = 'whitenoise.storage.CompressedManifestStaticFilesStorage'

# ── Security headers ──────────────────────────────────────────────────────────
SECURE_HSTS_SECONDS            = 31536000
SECURE_HSTS_INCLUDE_SUBDOMAINS = True
SECURE_HSTS_PRELOAD            = True
SECURE_SSL_REDIRECT            = True
SESSION_COOKIE_SECURE          = True
CSRF_COOKIE_SECURE             = True
SECURE_BROWSER_XSS_FILTER      = True
SECURE_CONTENT_TYPE_NOSNIFF    = True
X_FRAME_OPTIONS                = 'DENY'
SECURE_REFERRER_POLICY         = 'same-origin'
SECURE_PROXY_SSL_HEADER        = ('HTTP_X_FORWARDED_PROTO', 'https')

# Built from ALLOWED_HOSTS so a new install trusts its own hostnames and
# nobody else's. Add CSRF_TRUSTED_ORIGINS to .env to override.
CSRF_TRUSTED_ORIGINS = env.list(
    'CSRF_TRUSTED_ORIGINS',
    default=[f'https://{h}' for h in ALLOWED_HOSTS if h not in ('127.0.0.1', 'localhost', '*')],
)

# ── Email ─────────────────────────────────────────────────────────────────────
# The Settings page in the panel is the source of truth for SMTP. The plain
# backend reads .env only, so everything typed into Settings was saved,
# displayed, and never used to send a single email.
EMAIL_BACKEND       = env('EMAIL_BACKEND', default='apps.pages.email_backend.SiteSettingsEmailBackend')
EMAIL_HOST          = env('EMAIL_HOST',     default='')
EMAIL_PORT          = env.int('EMAIL_PORT', default=465)
EMAIL_USE_TLS       = env.bool('EMAIL_USE_TLS', default=False)
EMAIL_USE_SSL       = env.bool('EMAIL_USE_SSL', default=True)
DEFAULT_FROM_EMAIL  = env('DEFAULT_FROM_EMAIL',  default='')
ADMIN_EMAIL         = env('ADMIN_EMAIL',          default='')
# The no-reply mailbox, the support mailbox and both passwords come from
# Settings. This block used to hold them and the ticket fetcher read it,
# which is how a password sat in .env for months while the panel showed a
# different one.

# ── Google Analytics ──────────────────────────────────────────────────────────
GA_PROPERTY_ID      = env('GA_PROPERTY_ID', default='')

# ── Stripe and OpenAI ─────────────────────────────────────────────────────────
# Removed on 22 August 2026. Every one of these now comes from the
# Settings row, encrypted, and .env carries no credential at all.

# ── Logging ───────────────────────────────────────────────────────────────────
LOGS_DIR = BASE_DIR / 'logs'
LOGS_DIR.mkdir(exist_ok=True)

LOGGING = {
    'version': 1,
    'disable_existing_loggers': False,
    'formatters': {
        'verbose': {
            'format': '{levelname} {asctime} {module} {message}',
            'style': '{',
        },
    },
    'handlers': {
        'file': {
            'level': 'ERROR',
            'class': 'logging.FileHandler',
            'filename': LOGS_DIR / 'django_errors.log',
            'formatter': 'verbose',
        },
        'console': {
            'level': 'WARNING',
            'class': 'logging.StreamHandler',
            'formatter': 'verbose',
        },
        # Django reports why a CSRF check failed, but only at WARNING, and the
        # file handler above takes ERROR and up. So the one line that explains
        # a 403 has always been discarded. Its own file, so it cannot be lost
        # in the noise.
        'security': {
            'level': 'WARNING',
            'class': 'logging.FileHandler',
            'filename': LOGS_DIR / 'security.log',
            'formatter': 'verbose',
        },
    },
    'loggers': {
        'django': {
            'handlers': ['file', 'console'],
            'level': 'ERROR',
            'propagate': True,
        },
        # Everything this project writes. Without this entry no logger under
        # apps.* has a handler, so every logger.error and logger.exception in
        # our own code was discarded silently. Found on 22 August 2026 while
        # chasing a Stripe webhook that returned 400 and left no trace: the
        # view was logging the reason, into nothing.
        #
        # The file handler is ERROR level, so this does not fill the disk with
        # chatter. It only means our errors are as visible as Django's.
        'apps': {
            'handlers': ['file', 'console'],
            'level': 'INFO',
            'propagate': False,
        },
        'django.security': {
            'handlers': ['security', 'console'],
            'level': 'WARNING',
            'propagate': False,
        },
    },
}
