from pathlib import Path
import environ
from datetime import timedelta
import pytz
import os
import sentry_sdk
from sentry_sdk.integrations.logging import LoggingIntegration
from sentry_sdk.integrations.django import DjangoIntegration

# Build paths inside the project like this: BASE_DIR / 'subdir'.
BASE_DIR = Path(__file__).resolve().parent.parent.parent

# Environment Variables
env = environ.Env()
environ.Env.read_env(env_file=BASE_DIR / '.env')

DEBUG = env.bool('DEBUG', default=False)

# SECURITY WARNING: keep the secret key used in production secret!
SECRET_KEY = env('SECRET_KEY', default='your-secret-key')
REFRESH_TOKEN_SECRET = env('SECRET_KEY', default='your-secret-key')
BASE_URL = env('BASE_URL', default='http://127.0.0.1:8000')
BACKEND_URL = env('BACKEND_URL', default='http://127.0.0.1:8000')
FRONTEND_URL = env('FRONTEND_URL', default='http://127.0.0.1:3000')

SENTRY_DSN = env('SENTRY_DSN', default='')

# ── Cloudflare R2 (S3-compatible) ────────────────────────────────
# All media is stored in Cloudflare R2. ``R2_PUBLIC_BASE_URL`` should
# be either the bucket's R2.dev subdomain or a custom domain bound to
# the bucket (this is what ends up in DB-persisted media URLs).
R2_ACCOUNT_ID = env('R2_ACCOUNT_ID', default='').strip()
R2_ACCESS_KEY_ID = env('R2_ACCESS_KEY_ID', default='').strip()
R2_SECRET_ACCESS_KEY = env('R2_SECRET_ACCESS_KEY', default='').strip()
R2_BUCKET = env('R2_BUCKET', default='miler-media').strip()
R2_REGION = env('R2_REGION', default='auto').strip()
R2_ENDPOINT = env(
    'R2_ENDPOINT',
    default=(
        f'https://{R2_ACCOUNT_ID}.r2.cloudflarestorage.com'
        if R2_ACCOUNT_ID else ''
    ),
).strip()
R2_PUBLIC_BASE_URL = env('R2_PUBLIC_BASE_URL', default='').strip()
if R2_PUBLIC_BASE_URL and not R2_PUBLIC_BASE_URL.startswith(('http://', 'https://')):
    R2_PUBLIC_BASE_URL = f'https://{R2_PUBLIC_BASE_URL}'
R2_PUBLIC_BASE_URL = R2_PUBLIC_BASE_URL.rstrip('/')
R2_MEDIA_PATH = env('R2_MEDIA_PATH', default='').strip('/ ')

# Canonical public base for media URLs. Consumers (e.g. serializers
# validating that a URL lives on our own storage) should reference
# this rather than any backend-specific setting.
MEDIA_BASE_URL = R2_PUBLIC_BASE_URL

DATABASE_ENGINE = env('DATABASE_ENGINE', default='django.db.backends.sqlite3')
DATABASE_NAME = env('DATABASE_NAME', default='db.sqlite3')
DATABASE_USER = env('DATABASE_USER', default='your-database-user')
DATABASE_PASSWORD = env('DATABASE_PASSWORD', default='your-database-password')
DATABASE_HOST = env('DATABASE_HOST', default='localhost')
DATABASE_PORT = env('DATABASE_PORT', default='5432')

EMAIL_HOST = env('EMAIL_HOST', default='localhost')
EMAIL_HOST_USER = env('EMAIL_HOST_USER', default='your-email-user')
EMAIL_HOST_PASSWORD = env('EMAIL_HOST_PASSWORD', default='your-email-password')
EMAIL_PORT = env('EMAIL_PORT', default='5432')
DEFAULT_FROM_EMAIL = env('DEFAULT_FROM_EMAIL', default='your-email@example.com')

# ── Azure Communication Services (Email) ──────────────────────────
# Production sends go through ACS when ``endpoint + access_key`` are
# configured. In dev / tests, leave them blank to fall back to
# ``console.EmailBackend``.
AZURE_COMMUNICATION_ENDPOINT = env(
    'AZURE_COMMUNICATION_ENDPOINT', default='',
)
AZURE_COMMUNICATION_ACCESS_KEY = env(
    'AZURE_COMMUNICATION_ACCESS_KEY', default='',
)
AZURE_COMMUNICATION_EMAIL_SENDER_NO_REPLY = env(
    'AZURE_COMMUNICATION_EMAIL_SENDER_NO_REPLY', default='',
)
AZURE_COMMUNICATION_EMAIL_SENDER_NOTIFICATION = env(
    'AZURE_COMMUNICATION_EMAIL_SENDER_NOTIFICATION', default='',
)
AZURE_COMMUNICATION_EMAIL_SENDER_SUPPORT = env(
    'AZURE_COMMUNICATION_EMAIL_SENDER_SUPPORT', default='',
)
AZURE_COMMUNICATION_EMAIL_SENDER_MARKETING = env(
    'AZURE_COMMUNICATION_EMAIL_SENDER_MARKETING', default='',
)
# Legacy single-sender env kept as a fallback. Most events should pick
# a purpose-specific sender via ``send_template_email(sender='...')``.
AZURE_COMMUNICATION_EMAIL_SENDER = env(
    'AZURE_COMMUNICATION_EMAIL_SENDER',
    default=(
        AZURE_COMMUNICATION_EMAIL_SENDER_NOTIFICATION
        or AZURE_COMMUNICATION_EMAIL_SENDER_NO_REPLY
        or AZURE_COMMUNICATION_EMAIL_SENDER_SUPPORT
        or AZURE_COMMUNICATION_EMAIL_SENDER_MARKETING
        or ''
    ),
)

# Canonical map used by ``core.services.azure.email`` to resolve a
# purpose keyword (``no_reply`` / ``notification`` / ``support`` /
# ``marketing``) to a concrete MailFrom address. Each slot falls back
# to the single-sender value so partial configs keep working.
AZURE_COMMUNICATION_EMAIL_SENDERS = {
    'no_reply': AZURE_COMMUNICATION_EMAIL_SENDER_NO_REPLY or AZURE_COMMUNICATION_EMAIL_SENDER,
    'notification': AZURE_COMMUNICATION_EMAIL_SENDER_NOTIFICATION or AZURE_COMMUNICATION_EMAIL_SENDER,
    'support': AZURE_COMMUNICATION_EMAIL_SENDER_SUPPORT or AZURE_COMMUNICATION_EMAIL_SENDER,
    'marketing': AZURE_COMMUNICATION_EMAIL_SENDER_MARKETING or AZURE_COMMUNICATION_EMAIL_SENDER,
}
AZURE_COMMUNICATION_EMAIL_DEFAULT_SENDER_KEY = env(
    'AZURE_COMMUNICATION_EMAIL_DEFAULT_SENDER_KEY', default='notification',
)

AZURE_COMMUNICATION_EMAIL_POLLING_INTERVAL_SECONDS = env.int(
    'AZURE_COMMUNICATION_EMAIL_POLLING_INTERVAL_SECONDS', default=2,
)
AZURE_COMMUNICATION_EMAIL_TIMEOUT_SECONDS = env.int(
    'AZURE_COMMUNICATION_EMAIL_TIMEOUT_SECONDS', default=60,
)

_ACS_HAS_CREDENTIALS = bool(
    AZURE_COMMUNICATION_ENDPOINT and AZURE_COMMUNICATION_ACCESS_KEY
)

if _ACS_HAS_CREDENTIALS and AZURE_COMMUNICATION_EMAIL_SENDER:
    EMAIL_BACKEND = (
        'core.services.azure.email.backend.AzureCommunicationEmailBackend'
    )
    # Honour the ACS sender as the default From if none was set explicitly.
    if DEFAULT_FROM_EMAIL == 'your-email@example.com':
        DEFAULT_FROM_EMAIL = AZURE_COMMUNICATION_EMAIL_SENDER
else:
    EMAIL_BACKEND = env(
        'EMAIL_BACKEND',
        default='django.core.mail.backends.console.EmailBackend',
    )

JWT_ACCESS_TTL_MINUTES = env.int('JWT_ACCESS_TTL_MINUTES', default=15)

REDIS_HOST = env('REDIS_HOST', default='localhost')
REDIS_USER = env('REDIS_USER', default='your-redis-user')
REDIS_PASSWORD = env('REDIS_PASSWORD', default='your-redis-password')
REDIS_PORT = env('REDIS_PORT', default='6379')

BEEM_API_KEY = env('BEEM_API_KEY', default='your-beem-api-key')
SELCOM_MERCHANT_ID = env('SELCOM_MERCHANT_ID', default='your-selcom-merchant-id')
CLICKPESA_CLIENT_ID = env('CLICKPESA_CLIENT_ID', default='your-clickpesa-client-id')
POLAR_API_KEY = env('POLAR_API_KEY', default='your-polar-api-key')

ALLOWED_HOSTS = ['*']

CORS_ORIGIN_ALLOW_ALL = False
CORS_ALLOW_CREDENTIALS = True
CORS_ORIGIN_WHITELIST = (
    'http://127.0.0.1:3000',
    'http://127.0.0.1:8000',
)


SIMPLE_JWT = {
    "TOKEN_OBTAIN_SERIALIZER": "nexent.auth_serializer.TokenObtainPairSerializer",
    'ACCESS_TOKEN_LIFETIME': timedelta(minutes=JWT_ACCESS_TTL_MINUTES),
    'REFRESH_TOKEN_LIFETIME': timedelta(days=14),
    'ROTATE_REFRESH_TOKENS': False,
    'BLACKLIST_AFTER_ROTATION': False,
    'UPDATE_LAST_LOGIN': True,

    'ALGORITHM': 'HS256',
    'SIGNING_KEY': SECRET_KEY,
    'VERIFYING_KEY': None,
    'AUDIENCE': None,
    'ISSUER': None,
    'JWK_URL': None,
    'LEEWAY': 0,

    'AUTH_HEADER_TYPES': ('Bearer',),
    'AUTH_HEADER_NAME': 'HTTP_AUTHORIZATION',
    'USER_ID_FIELD': 'id',
    'USER_ID_CLAIM': 'user_id',
    'USER_AUTHENTICATION_RULE': 'rest_framework_simplejwt.authentication.default_user_authentication_rule',

    'AUTH_TOKEN_CLASSES': ('rest_framework_simplejwt.tokens.AccessToken',),
    'TOKEN_TYPE_CLAIM': 'token_type',
    'TOKEN_USER_CLASS': 'rest_framework_simplejwt.models.TokenUser',

    'JTI_CLAIM': 'jti',

    'SLIDING_TOKEN_REFRESH_EXP_CLAIM': 'refresh_exp',
    'SLIDING_TOKEN_LIFETIME': timedelta(minutes=5),
    'SLIDING_TOKEN_REFRESH_LIFETIME': timedelta(days=1),

    'AUTH_COOKIE': 'access_token',  # Cookie name. Enables cookies if value is set.
    'AUTH_COOKIE_DOMAIN': None,     # A string like "example.com", or None for standard domain cookie.
    'AUTH_COOKIE_SECURE': False,    # Whether the auth cookies should be secure (https:// only).
    'AUTH_COOKIE_HTTP_ONLY' : True, # Http only cookie flag.It's not fetch by javascript.
    'AUTH_COOKIE_PATH': '/',        # The path of the auth cookie.
    'AUTH_COOKIE_SAMESITE': 'Lax',  # Whether to set the flag restricting cookie leaks on cross-site requests. This can be 'Lax', 'Strict', or None to disable the flag.
}

INSTALLED_APPS = [
    "django.contrib.admin",
    "django.contrib.auth",
    "django.contrib.contenttypes",
    "django.contrib.sessions",
    "django.contrib.messages",
    "django.contrib.staticfiles",
    'rest_framework',
    'rest_framework.authtoken',
    'rest_framework_simplejwt',
    'rest_framework_simplejwt.token_blacklist',
    'django_celery_beat',
    'corsheaders',
    # Project apps
    'apps.common',
]

MIDDLEWARE = [
    'django.middleware.security.SecurityMiddleware',
    'django.contrib.sessions.middleware.SessionMiddleware',
    'django.middleware.common.CommonMiddleware',
    'django.middleware.csrf.CsrfViewMiddleware',
    'django.contrib.auth.middleware.AuthenticationMiddleware',
    'django.contrib.messages.middleware.MessageMiddleware',
    'corsheaders.middleware.CorsMiddleware',
]

ROOT_URLCONF = '{project_name}.urls'
WSGI_APPLICATION = '{project_name}.wsgi.application'
ASGI_APPLICATION = '{project_name}.asgi.application'

TEMPLATES = [
    {
        "BACKEND": "django.template.backends.django.DjangoTemplates",
        "DIRS": [],
        "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",
            ],
        },
    },
]

DATABASES = {
    'default': {
        'ENGINE': DATABASE_ENGINE,
        'NAME': DATABASE_NAME,
        'USER': DATABASE_USER,
        'PASSWORD': DATABASE_PASSWORD,
        'HOST': DATABASE_HOST,
        'PORT': DATABASE_PORT,
    }
}

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

REST_FRAMEWORK = {
    'DEFAULT_AUTHENTICATION_CLASSES': [
        'rest_framework_simplejwt.authentication.JWTAuthentication',
    ],
    'DEFAULT_RENDERER_CLASSES': [
        'rest_framework.renderers.JSONRenderer',
    ]
}

LANGUAGE_CODE = "en-us"

TIME_ZONE = "UTC"

USE_I18N = True

USE_L10N = True

USE_TZ = True

STATIC_URL = '/static/'

if not DEBUG:
    SESSION_COOKIE_SECURE = True
    CSRF_COOKIE_SECURE = True
    SECURE_SSL_REDIRECT = True
    SECURE_PROXY_SSL_HEADER = ('HTTP_X_FORWARDED_PROTO', 'https')

# ── Sentry Configuration ───────────────────────────────────────────
sentry_logging = LoggingIntegration(
    level=None,  # Capture all log levels
    event_level=None,  # Send all log levels as events
)

if SENTRY_DSN:
    sentry_sdk.init(
        dsn=SENTRY_DSN,
        # Add data like request headers and IP for users,
        # see https://docs.sentry.io/platforms/python/data-management/data-collected/ for more info
        send_default_pii=True,
        enable_logs=True,
        integrations=[
            sentry_logging,
            DjangoIntegration(),
        ],
        traces_sample_rate=1.0,
        profiles_sample_rate=1.0,
    )