"""
Django settings for das project.

Generated by 'django-admin startproject' using Django 1.8.2.

For more information on this file, see
https://docs.djangoproject.com/en/1.8/topics/settings/

For the full list of settings and their values, see
https://docs.djangoproject.com/en/1.8/ref/settings/
"""

# Build paths inside the project like this: os.path.join(BASE_DIR, ...)
import os

import environ
from corsheaders.defaults import default_headers

BASE_DIR = environ.Path(__file__) - 2
env = environ.Env(
    # set casting, default value
    DEBUG=(bool, False)
)

# this reads the .env file in the local dir. You can
# specify specific envs if needed.
environ.Env.read_env(BASE_DIR(".env"))

DOCS_ROOT = os.path.join(BASE_DIR, "../docs/_build/html")


# Quick-start development settings - unsuitable for production
# See https://docs.djangoproject.com/en/1.8/howto/deployment/checklist/

# SECURITY WARNING: keep the secret key used in production secret!
SECRET_KEY = "j(h&tc(u_#z-tf)u(9+3n39gmk92#6-v-he_p0ae+1rs*+2j@b"

# SECURITY WARNING: don't run with debug turned on in production!
DEBUG = False
ENABLE_SILK = env.bool("ENABLE_SILK", False)
MEMORY_PROFILING_ENABLED = env.bool("MEMORY_PROFILING_ENABLED", False)
DEV = False

# Application definition

INSTALLED_APPS = (
    "accounts.apps.AccountsConfig",
    "django.contrib.admin",
    "django.contrib.auth",
    "django.contrib.contenttypes",
    "django.contrib.sessions",
    "django.contrib.messages",
    "django.contrib.staticfiles",
    "django.contrib.gis",
    "versatileimagefield",
    "storages",
    "treebeard",
    "corsheaders",
    "oauth2_provider",
    "rest_framework",
    "rest_framework_gis",
    "drf_spectacular",
    "drf_spectacular_sidecar",
    "observations.apps.ObservationsConfig",
    "analyzers.apps.AnalyzersConfig",
    "das_server.apps.DasServerConfig",
    "tracking",
    "sensors.apps.SensorsConfig",
    "mapping.apps.MappingConfig",
    "activity.apps.ActivityConfig",
    "rt_api.apps.RTAPIConfig",
    "core.apps.CoreConfig",
    "choices",
    "reports.apps.ReportsConfig",
    "django_readonly_field",
    "usercontent.apps.UsercontentConfig",
    "django.contrib.postgres",
    "django.contrib.humanize",
    "django_extensions",
    "vectortiles",
    "docs",
    "buoy.apps.BuoyConfig",
    "schemas.apps.SchemasConfig",
)

MIDDLEWARE = (
    "utils.drf.ContentLengthMiddleware",
    "core.middleware.MaintenanceMiddleware",
    "utils.middleware.RequestDataMiddleware",
    "utils.middleware.TenantSettingsMiddleware",
    "django.middleware.security.SecurityMiddleware",
    "corsheaders.middleware.CorsMiddleware",
    "whitenoise.middleware.WhiteNoiseMiddleware",
    "django.contrib.sessions.middleware.SessionMiddleware",
    "django.middleware.common.CommonMiddleware",
    "django.middleware.locale.LocaleMiddleware",
    "django.middleware.csrf.CsrfViewMiddleware",
    "django.contrib.auth.middleware.AuthenticationMiddleware",
    "django.contrib.messages.middleware.MessageMiddleware",
    "django.middleware.clickjacking.XFrameOptionsMiddleware",
    "oauth2_provider.middleware.OAuth2TokenMiddleware",
    "revision.middleware.RevisionMiddleware",
    "utils.middleware.RequestLoggingMiddleware",
    "utils.middleware.EULARedirectMiddleware",
    "utils.middleware.GeographicMiddleware",
    "utils.middleware.ManageAdminEFBTokenMiddleware",
)

ROOT_URLCONF = "das_server.urls"

TEMPLATES = [
    {
        "BACKEND": "django.template.backends.django.DjangoTemplates",
        "DIRS": ["das_server/templates", "activity/templates", str(BASE_DIR)],
        "APP_DIRS": True,
        "OPTIONS": {
            "context_processors": [
                "django.template.context_processors.debug",
                "django.template.context_processors.request",
                "django.contrib.auth.context_processors.auth",
                "django.contrib.messages.context_processors.messages",
                "accounts.context_processors.eula_context_processor",
            ],
        },
    },
    {
        "NAME": "docx_template",
        "BACKEND": "reports.backends.DocxBackend",
        "DIRS": [
            "/var/www/env_configs/",
            str(BASE_DIR),
        ],
        "APP_DIRS": True,
        "OPTIONS": {"environment": "reports.environment.Environment", "optimized": False},
    },
    {
        "BACKEND": "django.template.backends.jinja2.Jinja2",
        "NAME": "jinja2",
        "DIRS": [
            str(BASE_DIR),
        ],
        "APP_DIRS": True,
        "OPTIONS": {"environment": "das_server.jinja2.environment"},
    },
]

AUTH_USER_MODEL = "accounts.User"
LOGIN_URL = "/login"
LOGOUT_URL = "/logout"
LOGIN_REDIRECT_URL = "/"

# The number of days a password reset link is valid for (259200 secs are 3 days)
PASSWORD_RESET_TIMEOUT = 259200
WSGI_APPLICATION = "das_server.wsgi.application"

AUTH_PASSWORD_VALIDATORS = [
    {
        "NAME": "django.contrib.auth.password_validation.UserAttributeSimilarityValidator",
    },
    {
        "NAME": "django.contrib.auth.password_validation.MinimumLengthValidator",
        "OPTIONS": {
            "min_length": 9,
        },
    },
    {
        "NAME": "django.contrib.auth.password_validation.CommonPasswordValidator",
    },
    {
        "NAME": "django.contrib.auth.password_validation.NumericPasswordValidator",
    },
]

REST_FRAMEWORK = {
    "DEFAULT_PERMISSION_CLASSES": (
        # 'rest_framework.permissions.DjangoModelPermissionsOrAnonReadOnly',
        "rest_framework.permissions.IsAuthenticated",
    ),
    "DEFAULT_AUTHENTICATION_CLASSES": (
        # Auth0JWTAuthentication must be first: when require_idp=True, it either succeeds
        # or raises AuthenticationFailed to prevent fallback to other auth methods
        "accounts.backends.Auth0JWTAuthentication",
        "accounts.backends.PriorityOAuth2SessionAuthentication",
        "utils.authentication.BearerTokenInUrlAuthentication",
    ),
    # 'VIEW_DESCRIPTION_FUNCTION': 'rest_framework_swagger.views.get_restructuredtext',
    "DEFAULT_RENDERER_CLASSES": (
        "utils.json.ExtendedJSONRenderer",
        "utils.json.ExtendedBrowsableAPIRenderer",
    ),
    "DEFAULT_METADATA_CLASS": "utils.meta.NoMetaData",
    "EXCEPTION_HANDLER": "utils.drf.api_exception_handler",
    "TEST_REQUEST_DEFAULT_FORMAT": "json",
    # 'DEFAULT_VERSIONING_CLASS': 'rest_framework.versioning.NamespaceVersioning',
    # 'DEFAULT_VERSION': 'v1.0',
    "SECURITY_DEFINITIONS": {
        "oauth2": {
            "type": "oauth2",
            "name": "",
            "authorizationUrl": "http://swagger.io/api/oauth/dialog",
            "flow": "password",
            "in": "header",
        }
    },
    # Custom openapi autoschema
    "DEFAULT_SCHEMA_CLASS": "das_server.views.CustomSchema",
    # Paginator overrides
    "OPTIONAL_PAGE_SIZE": 25,
    "MAX_PAGE_SIZE": 4000,
    "COUNT_TIMEOUT": 60 * 5,
    "ORDERING_PARAM": "sort_by",
    "DEFAULT_THROTTLE_RATES": {
        "chunked_upload_init": "60/min",
        "chunked_upload_chunk": "200/min",
    },
}

AUTHENTICATION_BACKENDS = (
    "accounts.backends.Auth0BackendForStaffUsers",
    "accounts.backends.NoLoginOAuth2Backend",
    "accounts.backends.AccountsModelBackend",
)

SERIALIZATION_MODULES = {"geojson": "core.serializers"}

# Database
# https://docs.djangoproject.com/en/1.8/ref/settings/#databases
# we use postgis, create the db from the spatial db template
# createdb -T template_postgis das ENCODING 'utf8';
DATABASES = {
    "default": {
        "ENGINE": "utils.db.backends.postgis",
        "NAME": "das",
        "USER": "das",
        "HOST": env.str("DB_HOST", "postgis"),
        "PORT": env.int("DB_PORT", 5432),
        "PASSWORD": env.str("DB_PASSWORD", "password"),
    },
}

# To enable or disable subject regions view on admin dashboard
SUBJECT_REGION_ENABLED = True

# Do not use Django logging config
LOGGING_CONFIG = None

# OpenTelemetry Tracing to Google Cloud Trace
TRACING_ENABLED = env.bool("TRACING_ENABLED", False)
SERVICE_NAME = env.str("SERVICE_NAME", "das-api")

# Internationalization
# https://docs.djangoproject.com/en/1.8/topics/i18n/

LANGUAGE_CODE = "en-us"

USE_I18N = True

USE_TZ = True
TIME_ZONE = "UTC"

# Static files (CSS, JavaScript, Images)
# https://docs.djangoproject.com/en/1.8/howto/static-files/

STATIC_URL = env.str("STATIC_URL", "/static/")
STATIC_ROOT = env.str("STATIC_ROOT", os.path.join(BASE_DIR, "www", "static"))

# Django 4.2+ requires STORAGES to include "default" and "staticfiles" (see ref/files/storage).
STORAGES = {
    "default": {
        "BACKEND": "django.core.files.storage.FileSystemStorage",
    },
    "staticfiles": {
        # Dev/runserver uses plain StaticFilesStorage so `{% static %}` works
        # without first running `collectstatic`. The manifest (hashed-filename)
        # backend is enabled only in local_settings_docker.py for production.
        "BACKEND": "django.contrib.staticfiles.storage.StaticFilesStorage",
    },
}

# Only include static subdirectories, not entire app directories
STATICFILES_DIRS = (
    os.path.join(BASE_DIR, "activity", "static"),
    os.path.join(BASE_DIR, "das_server", "static"),
    os.path.join(BASE_DIR, "mapping", "static"),
    os.path.join(BASE_DIR, "observations", "static"),
    os.path.join(BASE_DIR, "rt_api", "static"),
)

SITE_ID = 1
UI_SITE_NAME = "EarthRanger"
UI_SITE_URL = "http://www.earthranger.com"

# socket.io uses the CORS_ORIGIN_WHITELIST as well
# caveat is that socket.io matches against the whole ORIGIN ie:
# http://localhost
CORS_ALLOW_CREDENTIALS = True
CORS_ORIGIN_ALLOW_ALL = True
CORS_ORIGIN_WHITELIST = []
CORS_ALLOWED_ORIGINS = []
CORS_ALLOW_HEADERS = default_headers + ("user-profile", "traceparent")

ALLOWED_HOSTS = ["*"]

# Session and CSRF cookie security settings
SESSION_COOKIE_SECURE = env.bool("SESSION_COOKIE_SECURE", True)
CSRF_COOKIE_SECURE = env.bool("CSRF_COOKIE_SECURE", True)

SESSION_COOKIE_HTTPONLY = True
CSRF_COOKIE_HTTPONLY = False  # Must be False so JavaScript can read it for AJAX requests
SESSION_COOKIE_SAMESITE = "Lax"  # Lax allows cookies on top-level navigation (redirects)
CSRF_COOKIE_SAMESITE = "Lax"

# CSRF_TRUSTED_ORIGINS needs to be set in local settings with proper schemes
CSRF_TRUSTED_ORIGINS = []

# Store CSRF token in session instead of cookie to avoid cookie-related issues
# This can prevent intermittent CSRF errors when cookies aren't set/sent properly
# Set to False by default, but can be enabled via env var if cookie issues persist
CSRF_USE_SESSIONS = env.bool("CSRF_USE_SESSIONS", False)

# tile.openstreetmap.org rejects requests with no Referer (403). SecurityMiddleware
# sends Referrer-Policy only when the response does not already define one.
SECURE_REFERRER_POLICY = "strict-origin-when-cross-origin"

AUTH0_CUSTOM_DOMAIN = env.str("AUTH0_CUSTOM_DOMAIN", "auth-dev.pamdas.org")
AUTH0_TENANT_DOMAIN = env.str("AUTH0_TENANT_DOMAIN", "")
AUTH0_RESOURCE_SERVER = env.str("AUTH0_RESOURCE_SERVER", "https://pamdas.org/api")
AUTH0_JWKS_CACHE_TTL_S = env.int("AUTH0_JWKS_CACHE_TTL_S", 3600)

AUTH0_CLIENT_ID_FOR_MANAGEMENT_API = env.str("AUTH0_CLIENT_ID_FOR_MANAGEMENT_API", "")
AUTH0_CLIENT_SECRET_FOR_MANAGEMENT_API = env.str("AUTH0_CLIENT_SECRET_FOR_MANAGEMENT_API", "")

# Auth0 settings for admin login OAuth flow
AUTH0_CLIENT_ID_FOR_DJANGO_ADMIN = env.str("AUTH0_CLIENT_ID_FOR_DJANGO_ADMIN", "")
AUTH0_CLIENT_SECRET_FOR_DJANGO_ADMIN = env.str("AUTH0_CLIENT_SECRET_FOR_DJANGO_ADMIN", "")

# Auth0 settings for Account Linker (public PKCE client, no secret)
AUTH0_CLIENT_ID_FOR_ACCOUNT_LINKER = env.str("AUTH0_CLIENT_ID_FOR_ACCOUNT_LINKER", "")
ACCOUNT_LINKER_MAGIC_LINK_MAX_AGE_SECONDS = env.int("ACCOUNT_LINKER_MAGIC_LINK_MAX_AGE_SECONDS", 86400)

# When require_idp=True (Auth0 enforced), allow these legacy DOT OAuth2 applications
# (identified by OAuth2 application client_id) to continue using OAuth2 access tokens.
# This is a global allowlist across tenants.
IDP_OAUTH2_CLIENT_IDS_ALLOWLIST = env.list(
    "IDP_OAUTH2_CLIENT_IDS_ALLOWLIST", default=["das_kml_export", "gundi", "EFB_APPLICATION_ID"]
)

# This is the connection name we have defined (`foo-bar-baz`) in our Auth0 tenant.
# This is NOT the opaque connection id Auth0 generates (`con_uGlYF0oBaR`)
AUTH0_USER_DB_CONNECTION_NAME = env.str("AUTH0_USER_DB_CONNECTION_NAME", "")

DATA_UPLOAD_MAX_NUMBER_FIELDS = 10000

SPECTACULAR_SETTINGS = {
    "TITLE": "EarthRanger API Documentation",
    "DESCRIPTION": ("Welcome to the <b>EarthRanger API</b>! </br>"),
    "VERSION": "1.0.0",
    "SERVE_INCLUDE_SCHEMA": False,
    "SWAGGER_UI_DIST": "SIDECAR",
    "SWAGGER_UI_FAVICON_HREF": "SIDECAR",
    "REDOC_DIST": "SIDECAR",
    "COMPONENT_SPLIT_REQUEST": True,
    "GENERIC_ADDITIONAL_PROPERTIES": "bool",
    "AUTHENTICATION_WHITELIST": [],
    "POSTPROCESSING_HOOKS": [
        "drf_spectacular.hooks.postprocess_schema_enums",
        "utils.json.wrap_responses_with_data_envelope",
    ],
    "OAUTH2_FLOWS": {
        "password": {
            "tokenUrl": "/oauth2/token/",
            "scopes": {
                "read": "Read access",
                "write": "Write access",
            },
        }
    },
}

OAUTH2_PROVIDER = {
    "ACCESS_TOKEN_EXPIRE_SECONDS": 3600 * 48,  # two days
    "REFRESH_TOKEN_EXPIRE_SECONDS": 62 * 24 * 3600,  # two months, stay one month behind longest expiration
    "REFRESH_TOKEN_GRACE_PERIOD_SECONDS": 60 * 5,  # 5 minutes
    "OAUTH2_VALIDATOR_CLASS": "utils.oauth2_validators.ExtendExpiresInOAuth2Validator",
    "EXPIRE_OVERRIDES": {"er_mobile_tracker": 3600 * 24 * 30},
}

# Django System Checks
SILENCED_SYSTEM_CHECKS = ["auth.W004", "fields.W342"]

# Django autofield, but we prefer to use UUIDs
DEFAULT_AUTO_FIELD = "django.db.models.BigAutoField"

# RT API settings
ASYNC_MODE = "eventlet"

# override these if your libraries are in a different place
GEOS_LIBRARY_PATH = env.str("GEOS_LIBRARY_PATH", "/usr/lib/x86_64-linux-gnu/libgeos_c.so.1")
GDAL_LIBRARY_PATH = env.str("GDAL_LIBRARY_PATH", "/usr/lib/libgdal.so")

# Explicitly enable GDAL/OGR/OSR exceptions to suppress FutureWarning about
# GDAL 4.0 changing the default behavior.
from osgeo import gdal, ogr, osr  # noqa: E402

gdal.UseExceptions()
ogr.UseExceptions()
osr.UseExceptions()

RASTER_WORKDIR = "/tmp/raster"

"""
Associate a plugin name with a plugin-configuration dict that will override the plugin's configuration in the database.
"""
DATA_INPUT_PLUGINS = {}

# would want to set this to where you might have some MBTiles maps
MAPPING = {
    "MBTILES": {
        "root": r"/tmp",
    }
}

# In the ST environment variable are
# REDIS_SERVICE_HOST, REDIS_SERVICE_PORT
# In the MT environment variables are
# REDIS_HOST, REDIS_PORT
REDIS_PORT = env.int("REDIS_SERVICE_PORT", 0)
if not REDIS_PORT:
    REDIS_PORT = env.int("REDIS_PORT", 6379)
REDIS_HOST = env.str("REDIS_SERVICE_HOST", "")
if not REDIS_HOST:
    REDIS_HOST = env.str("REDIS_HOST", "redis")
REDIS_SERVER = f"redis://{REDIS_HOST}:{REDIS_PORT}"
REALTIME_BROKER_URL = f"{REDIS_SERVER}/2"
REALTIME_BROKER_OPTIONS = {"max_connections": 200}
PUBSUB_BROKER_URL = f"{REDIS_SERVER}/1"
PUBSUB_BROKER_OPTIONS = {"max_connections": 200}

# Celery Settings
# Keep Celery broker independent from general Redis server; allow env override
CELERY_BROKER_URL = env.str("CELERY_BROKER_URL", REDIS_SERVER)
CELERY_RESULT_BACKEND = env.str("CELERY_RESULT_BACKEND", CELERY_BROKER_URL)
CELERY_ACCEPT_CONTENT = ["application/json"]
CELERY_TASK_SERIALIZER = "json"
CELERY_RESULT_SERIALIZER = "json"
CELERY_ENABLE_UTC = True
CELERY_TIMEZONE = "UTC"

CELERY_REDIS_MAX_CONNECTIONS = 500
CELERY_WORKER_MAX_TASKS_PER_CHILD = 100

CELERY_RESULT_PERSISTENT = False
CELERY_RESULT_EXPIRES = 300
CELERY_TASK_IGNORE_RESULT = True
CELERY_TASK_STORE_ERRORS_EVEN_IF_IGNORED = True
# TODO: update in production
CELERY_WORKER_PREFETCH_MULTIPLIER = 1
# Enables error emails.
CELERY_SEND_TASK_ERROR_EMAILS = False

CELERY_TASK_DEFAULT_QUEUE = "default"
CELERY_TASK_DEFAULT_EXCHANGE = "default"
CELERY_TASK_DEFAULT_ROUTING_KEY = "default"

CELERY_BROKER_TRANSPORT_OPTIONS = {"visibility_timeout": 3600, "fanout_prefix": True}

# task:
CELERY_TASK_TRACK_STARTED = True

# Max observation UUIDs per post-save segment Celery message (create/update batches).
OBSERVATION_SEGMENT_POST_SAVE_BATCH_SIZE = env.int("OBSERVATION_SEGMENT_POST_SAVE_BATCH_SIZE", 200)
# Lag (seconds) at which a segment task increments observation_segment.backlog_threshold_breach.
OBSERVATION_SEGMENT_BACKLOG_LAG_WARN_SECONDS = env.int("OBSERVATION_SEGMENT_BACKLOG_LAG_WARN_SECONDS", 300)
# Daily reconciliation looks back this many hours per tenant to verify segment coverage.
# Wider than 24h gives overlap when the daily run is delayed or skipped, so observations
# don't fall between cracks.
OBSERVATION_SEGMENT_RECONCILE_HOURS = env.int("OBSERVATION_SEGMENT_RECONCILE_HOURS", 30)

DEFAULT_CACHE_ALIAS = "default"
SHARED_CACHE_ALIAS = "shared"
VECTOR_TILE_CACHE_ALIAS = "vector_tiles"
UPLOAD_SESSION_CACHE_ALIAS = "upload_sessions"


# Vector tiles cache Redis location (dedicated in deployed contexts)
_vt_redis_host = env.str("REDIS_VT_SERVICE_HOST", "")
if not _vt_redis_host:
    _vt_redis_host = env.str("REDIS_HOST_VT", "redis-vt")
_vt_redis_server = f"redis://{_vt_redis_host}:{REDIS_PORT}"
CACHES = {
    DEFAULT_CACHE_ALIAS: {
        "BACKEND": "django.core.cache.backends.locmem.LocMemCache",
        "LOCATION": "unique-snowflake",
        "KEY_FUNCTION": "utils.tenant.cache.make_cache_key",
    },
    SHARED_CACHE_ALIAS: {
        "BACKEND": "django.core.cache.backends.locmem.LocMemCache",
        "LOCATION": "shared-cache",
        "KEY_PREFIX": "shared",
    },
    VECTOR_TILE_CACHE_ALIAS: {
        "BACKEND": "django_redis.cache.RedisCache",
        "LOCATION": _vt_redis_server,
        "OPTIONS": {"CLIENT_CLASS": "django_redis.client.DefaultClient"},
        "KEY_PREFIX": "vector-tiles",
    },
    # Chunked upload sessions (ERA-9210): must be shared across Gunicorn/uwsgi workers and pods.
    # LocMem here is for dev/tests only; production images override this alias to Redis in
    # local_settings_docker.py (see UPLOAD_SESSION_CACHE_ALIAS).
    # NOTE: Adding KEY_FUNCTION changes the stored key shape. On first deploy, any in-flight
    # upload sessions will be invalidated (clients will receive 404 and must restart the upload).
    UPLOAD_SESSION_CACHE_ALIAS: {
        "BACKEND": "django.core.cache.backends.locmem.LocMemCache",
        "LOCATION": "upload-sessions",
        "KEY_FUNCTION": "utils.tenant.cache.make_cache_key",
    },
}


# the address to send notification emails from
# FROM_EMAIL is used by the inreach send message and the send KML link by email
FROM_EMAIL = "notifications@pamdas.org"
DEFAULT_FROM_EMAIL = "notifications@earthranger.com"
# Used by password reset email
EMAIL_HOST_USER = "info@pamdas.org"

SENDSMS_BACKEND = "utils.smsbackend.AfricasTalkingBackend"
SENDSMS_FROM = None

# use these when you want to send SMS from kenya
SENDSMS_AFRICAS_TALKING_USERNAME = ""
SENDSMS_AFRICAS_TALKING_API_KEY = ""

# use these when you don't want to send SMS from kenya or when you want to
# use WhatsApp
TWILIO_ACCOUNT_SID = env.str("TWILIO_ACCOUNT_SID", None)
TWILIO_AUTH_TOKEN = env.str("TWILIO_AUTH_TOKEN", None)

SENDSMS_TWILIO_FROM_NUMBER = env.str("SENDSMS_TWILIO_FROM_NUMBER", None)
if SENDSMS_TWILIO_FROM_NUMBER:
    SENDSMS_BACKEND = "utils.smsbackend.TwilioSmsBackend"

WHATSAPP_FROM_NUMBER = env.str("WHATSAPP_FROM_NUMBER", "")
WHATSAPP_CONTENT_SID = env.str("WHATSAPP_CONTENT_SID", "HXc0d9e484f97c27890999e7d859f84919")

VERSATILEIMAGEFIELD_RENDITION_KEY_SETS = {
    "default": [
        ("original", "url"),
        ("icon", "crop__64x64"),  # Crop for use as icon
        ("thumbnail", "thumbnail__150x150"),  # Resize to fit within
        ("large", "thumbnail__800x800"),  # Resize to fit within
        ("xlarge", "thumbnail__1920x1920"),  # Resize to fit within
    ],
    "event_photo": [
        ("original", "url"),
        ("thumbnail", "thumbnail__150x150"),  # Resize to fit within
        ("large", "thumbnail__800x800"),  # Resize to fit within
    ],
}

VERSATILEIMAGEFIELD_SETTINGS = {
    # The amount of time, in seconds, that references to created images
    # should be stored in the cache. Defaults to `2592000` (30 days)
    "cache_length": 2592000,
    # The name of the cache you'd like `django-versatileimagefield` to use.
    # Defaults to 'versatileimagefield_cache'. If no cache exists with the name
    # provided, the 'default' cache will be used instead.
    "cache_name": "versatileimagefield_cache",
    # The save quality of modified JPEG images. More info here:
    # http://pillow.readthedocs.org/en/latest/handbook/image-file-formats.html#jpeg
    # Defaults to 70
    "jpeg_resize_quality": 70,
    # The name of the top-level folder within storage classes to save all
    # sized images. Defaults to '__sized__'
    "sized_directory_name": "sz",
    # The name of the directory to save all filtered images within.
    # Defaults to '__filtered__':
    "filtered_directory_name": "fltr",
    # The name of the directory to save placeholder images within.
    # Defaults to '__placeholder__':
    "placeholder_directory_name": "ph",
    # Whether or not to create new images on-the-fly. Set this to `False` for
    # speedy performance but don't forget to 'pre-warm' to ensure they're
    # created and available at the appropriate URL.
    "create_images_on_demand": True,
    # A dot-notated python path string to a function that processes sized
    # image keys. Typically used to md5-ify the 'image key' portion of the
    # filename, giving each a uniform length.
    # `django-versatileimagefield` ships with two post processors:
    # 1. 'versatileimagefield.processors.md5' Returns a full length (32 char)
    #    md5 hash of `image_key`.
    # 2. 'versatileimagefield.processors.md5_16' Returns the first 16 chars
    #    of the 32 character md5 hash of `image_key`.
    # By default, image_keys are unprocessed. To write your own processor,
    # just define a function (that can be imported from your project's
    # python path) that takes a single argument, `image_key` and returns
    # a string.
    "image_key_post_processor": None,
    # Whether to create progressive JPEGs. Read more about progressive JPEGs
    # here: https://optimus.io/support/progressive-jpeg/
    "progressive_jpeg": True,
}

USERCONTENT_SETTINGS = {
    # ---------------------------------------------------------------------------
    # UPLOAD ALLOWLIST
    # Only files whose extension appears here are accepted by the chunked upload
    # API.  Add extensions freely; remove with care (existing stored files are
    # unaffected, but clients will no longer be able to upload that type).
    # Extensions must be lowercase and without the leading dot.
    # ---------------------------------------------------------------------------
    "allowed_extensions": (
        # Images
        "jpg",
        "jpeg",
        "png",
        "gif",
        "tif",
        "tiff",
        "webp",
        "heic",
        "bmp",
        "svg",
        # Documents
        "pdf",
        "doc",
        "docx",
        "xls",
        "xlsx",
        "csv",
        "ppt",
        "pptx",
        "odt",
        "ods",
        "txt",
        "rtf",
        # Audio
        "mp3",
        "wav",
        "aac",
        "ogg",
        "flac",
        "m4a",
        "opus",
        # Video
        "mp4",
        "mov",
        "avi",
        "mkv",
        "wmv",
        "webm",
        "m4v",
        "3gp",
    ),
    # ---------------------------------------------------------------------------
    # IMAGE ROUTING
    # Files with these extensions are stored as ImageFileContent (with thumbnail
    # generation) rather than plain FileContent.  Must be a subset of
    # allowed_extensions above.
    # ---------------------------------------------------------------------------
    "imagefile_extensions": ("jpg", "jpeg", "png", "gif", "tif", "tiff"),
    # ---------------------------------------------------------------------------
    # SERVE BEHAVIOUR
    # Force these MIME types to download as application/octet-stream so browsers
    # never render or execute them inline.
    # ---------------------------------------------------------------------------
    "force_download_mimetypes": (
        "text/html",
        "text/javascript",
        "image/svg+xml",
    ),
}

# Chunked, resumable file upload (ERA-9210)
# Default 2 MiB: each chunk PUT must stay below Django's DATA_UPLOAD_MAX_MEMORY_SIZE (2621440 bytes by default).
# See usercontent.chunked_upload._effective_max_chunk_bytes() which also clamps env overrides to that ceiling.
CHUNKED_UPLOAD_CHUNK_SIZE = env.int("CHUNKED_UPLOAD_CHUNK_SIZE", 2 * 1024 * 1024)  # 2 MiB
CHUNKED_UPLOAD_MAX_FILE_SIZE = env.int("CHUNKED_UPLOAD_MAX_FILE_SIZE", 500 * 1024 * 1024)  # 500 MiB
CHUNKED_UPLOAD_SESSION_TTL_SECONDS = env.int("CHUNKED_UPLOAD_SESSION_TTL_SECONDS", 86400)  # 24 hours
CHUNKED_UPLOAD_GCS_TIMEOUT_SECONDS = env.int("CHUNKED_UPLOAD_GCS_TIMEOUT_SECONDS", 120)

SHOW_TRACK_DAYS = 16
DEFAULT_EVENT_FILTER_FROM_DAYS = -1
DEFAULT_PATROL_FILTER_FROM_DAYS = -1

REALTIME_AUTH_TIMEOUT_SECONDS = 1.0

NOTIFY_HIGH_PRIORITY_EVENT = None
NOTIFY_MEDIUM_PRIORITY_EVENT = None
NOTIFY_LOW_PRIORITY_EVENT = None

REPORTED_BY_PERMISSION_SET = "b5057387-9f6c-4685-8ec1-46ad29684eea"

EVENT_MATRIX_ENABLED = False
EXPORT_KML_ENABLED = False
KML_FEED_TITLE = "EarthRanger KML Service"
KML_OVERLAY_IMAGE = None
KML_TOKEN_TTL_DAYS = 5 * 365

SHOW_STATIONARY_SUBJECTS_ON_MAP = True

# Default speed-threshold (in km/h) by subject-subtype. These are default values that maybe overridden in an
# ObservationAnnotation instance.
# If a subject_sub-type is not found here, then the annotation routine
# will not do anything.
ANNOTATION_SETTINGS = {
    "speed_thresholds": {
        "forest_elephant": 7.0,
        "elephant": 7.5,
        "vehicle": 200.0,
        "plane": 500.0,
        "helicopter": 500.0,
        "ranger": 200.0,
        "ranger_team": 200.0,
    }
}

SENSORS = {
    "camera_trap": {
        "default_time_zone": "UTC",
        "priority": 300,
    }
}

DEEP_LINK_EVENT_TYPES = [
    "low_speed_wilcoxon",
    "immobility",
    "low_speed_wilcoxon_all_clear",
    "low_speed_percentile",
    "low_speed_percentile_all_clear",
    "geofence_break",
    "immobility_all_clear",
    "proximity",
]

EUS_SETTINGS = {
    # 'zendesk' or 'email'
    "type": "",
    "name": "",
    "email": "",
    "organization": "",
}


def whitenoise_headers_func(headers, path, url):
    # This is intended for testing purposes, to add a header to assets that are served up by whitenoise.
    # We'll take it out but for now it will help us identify whether we're
    # using whitenoise properly.
    headers["x-er-source"] = "wn"


WHITENOISE_ADD_HEADERS_FUNCTION = whitenoise_headers_func
WHITENOISE_MAX_AGE = 604800

DAILY_REPORT_ENABLED = False
ALERTS_ENABLED = True
ALERTS_RATE_LIMIT = 20
ALERTS_RATE_LIMIT_DURATION_SECONDS = 86400  # 24 hours
ALERTS_REMAINING_COUNTER_FOR_WARNING = 3

CARTO_URL = "https://wri-01.cartodb.com/api/v2/sql"  # For: VIIRS-Fire-Alerts

GFW_API_ROOT = "https://production-api.globalforestwatch.org/v1"
GFW_WEB_ROOT = "https://www.globalforestwatch.org"
MAPBOX_TOKEN = env.str("MAPBOX_TOKEN", "")

GFW_CREDENTIALS = {"username": "support@pamdas.org", "password": "ns2S#@Bh3V&W2eR17Ru8"}
GFW_CLUSTER_RADIUS = 5  # kilometers
GFW_BACKFILL_INTERVAL_DAYS = 10  # run backfill every n days

METRICS_BUCKET = "er-site-metrics"

ACCEPT_EULA = True
PATROL_ENABLED = True

# Has to be a multiple of 256
GS_BLOB_CHUNK_SIZE = 10485760
UBI_API_URL = "https://api.ubignss.com/position"
UBI_API_USERNAME = env.str("UBI_API_USERNAME", "username")
UBI_API_PASSWORD = env.str("UBI_API_PASSWORD", "password")


# Kerlink.
KERLINK_BASEURL = "https://tanapa.wanesy.com/gms/application"

# Tableau Server:
TABLEAU_ENABLED = False
TABLEAU_SERVER = "https://tableau.pamdas.org"
TABLEAU_VERSION = 3.9
TABLEAU_API_TOKEN = None
TABLEAU_API_USERNAME = "ER Server"
TABLEAU_API_PASSWORD = None
TABLEAU_DEFAULT_DASHBOARD = "er_standard_analytics/summary"

# Sensible default domain name.
SERVER_FQDN = "tempuri.org"

# SERVER_NAMES should be a list for extending with tenant domains
SERVER_NAMES = env.list("SERVER_NAMES", default=["localhost"])

# Default to re-use the site's domain-name as a folder for daily-report template.
DAILY_REPORT_TEMPLATE_SUBFOLDER = SERVER_FQDN

TRACK_LENGTH = 21
OBSERVATION_ACCURACY_THRESHOLD = env.int("OBSERVATION_ACCURACY_THRESHOLD", 25)  # meters

PATROL_VIEW_REFRESH_HOURS = 1

INREACH_INBOUND_ENDPOINT = "https://explore.garmin.com/IPCInbound/V1/Messaging.svc/Message"
INREACH_USERNAME = env.str("INREACH_USERNAME", "username")
INREACH_PASSWORD = env.str("INREACH_PASSWORD", "password")

GEO_PERMISSION_RADIUS_METERS = 3704
GEO_PERMISSION_SPEED_KM_H = 75
GEO_PERMISSION_VIOLATION_BAN_DURATION_MIN = 10

PERSISTENT_STORAGE = {
    "CLIENT": "utils.persistent.MultitenantRedisStorage",
    "HOST": REDIS_HOST,
    "PORT": REDIS_PORT,
    "DATABASE": 0,
}

ALERTS_STORAGE = {
    "CLIENT": "utils.persistent.MultitenantRedisStorage",
    "HOST": REDIS_HOST,
    "PORT": REDIS_PORT,
    "DATABASE": 3,
}

TMS_API = {
    "CLIENT": env.str("TMS_API_CLIENT", "core.tms.HTTPClient"),
    "HOST": env.str("TMS_API_HOST", ""),
    "API_VERSION": env.str("TMS_API_VERSION", "v1.0"),
    "API_KEY": env.str("TMS_API_KEY", "secret"),
}

# Local-dev seed for the per-tenant release-toggle registry (utils/tenant/release_toggles.py).
# In production these arrive in the tenant payload's `releaseToggles` block from TMS; locally
# the DjangoSettingsTenantBuilder seeds `release_toggles` from this JSON so a developer can flip
# a registered toggle from .env, e.g.:
#   RELEASE_TOGGLES={"community_input_admin_enabled": true}
RELEASE_TOGGLES = env.json("RELEASE_TOGGLES", default={})

TENANT_DOCUMENT_CACHE = {
    "CLIENT": "utils.persistent.RedisStorage",
    "HOST": REDIS_HOST,
    "PORT": REDIS_PORT,
    "DATABASE": 0,
}

DISABLE_STATSD = env.bool("DISABLE_STATSD", True)

if not env.bool("IS_OAUTH2_PROVIDER_MIGRATION", False):
    # Django oauth custom models
    OAUTH2_PROVIDER_ACCESS_TOKEN_MODEL = "core.DASAccessToken"
    OAUTH2_PROVIDER_APPLICATION_MODEL = "core.DASApplication"
    OAUTH2_PROVIDER_GRANT_MODEL = "core.DASGrant"
    OAUTH2_PROVIDER_ID_TOKEN_MODEL = "core.DASIDToken"
    OAUTH2_PROVIDER_REFRESH_TOKEN_MODEL = "core.DASRefreshToken"

# You would only set this in a development environment
# In production, the tenant id will come from the TMS
TENANT_ID = env.str("TENANT_ID", "")

CLUSTER_NAME = env.str("CLUSTER_NAME", "UNSET")
CLUSTER_NAMESPACE = env.str("CLUSTER_NAMESPACE", "UNSET")


if CLUSTER_NAME in ["das1-prod-asia", "das-prod1"]:
    PUBSUB_PROJECT_ID = "earthranger-prod"
elif CLUSTER_NAME == "das-dev":
    PUBSUB_PROJECT_ID = "earthranger-dev"
else:
    PUBSUB_PROJECT_ID = env.str(var="PUBSUB_PROJECT_ID", default="earthranger-dev")


# LD_PRELOAD = "/usr/lib/aarch64-linux-gnu/libgomp.so.1"

# Initialize ALT_SERVER_NAMES as an empty list
ALT_SERVER_NAMES = []

# Data Warehouse API
DWH_API_URL = env.str("DWH_API_URL", "")
