"""Base settings shared by all environments."""
import os
from datetime import timedelta
from pathlib import Path

from dotenv import load_dotenv

BASE_DIR = Path(__file__).resolve().parent.parent.parent
load_dotenv(BASE_DIR / ".env")

SECRET_KEY = os.getenv("SECRET_KEY", "change-me-in-production")
DEBUG = False
ALLOWED_HOSTS = os.getenv("ALLOWED_HOSTS", "localhost,127.0.0.1").split(",")

# Secret required to call internal MCP-agent endpoints
INTERNAL_API_SECRET = os.getenv("INTERNAL_API_SECRET", "internal-secret-dev")

# MCP auth service (handles all MFA/TOTP operations)
MCP_URL = os.getenv("MCP_URL", "http://127.0.0.1:9000/mcp")

# When True (current default), a failed login tells the user *why* it failed —
# unregistered email -> "No account found with this email address.", wrong
# password -> "Incorrect password. Please try again." Note this lets an
# attacker enumerate which emails have accounts; set
# LOGIN_REVEAL_ACCOUNT_EXISTENCE=false in .env if that trade-off ever needs to
# change back to a single generic "Invalid email or password." message.
LOGIN_REVEAL_ACCOUNT_EXISTENCE = os.getenv("LOGIN_REVEAL_ACCOUNT_EXISTENCE", "true").lower() == "true"

# Email (for OTP MFA + candidate notifications). Credentials live in .env.
# Auto-select: real SMTP when EMAIL_HOST_USER is configured, else console
# backend (mail prints to the Django terminal — NOT actually delivered).
_default_email_backend = (
    "core.email_backends.SSLFailableEmailBackend"
    if os.getenv("EMAIL_HOST_USER")
    else "django.core.mail.backends.console.EmailBackend"
)
EMAIL_BACKEND = os.getenv("EMAIL_BACKEND", _default_email_backend)
EMAIL_HOST = os.getenv("EMAIL_HOST", "smtp.gmail.com")
EMAIL_PORT = int(os.getenv("EMAIL_PORT", "587"))
EMAIL_USE_TLS = os.getenv("EMAIL_USE_TLS", "true").lower() == "true"
EMAIL_USE_SSL = os.getenv("EMAIL_USE_SSL", "false").lower() == "true"
EMAIL_HOST_USER = os.getenv("EMAIL_HOST_USER", "")
EMAIL_HOST_PASSWORD = os.getenv("EMAIL_HOST_PASSWORD", "")
EMAIL_SSL_CERT_VERIFY = os.getenv("EMAIL_SSL_CERT_VERIFY", "true").lower() == "true"
if not EMAIL_SSL_CERT_VERIFY:
    import ssl
    try:
        ssl._create_default_https_context = ssl._create_unverified_context
    except AttributeError:
        pass
    orig_create_default_context = ssl.create_default_context
    def unverified_create_default_context(*args, **kwargs):
        context = orig_create_default_context(*args, **kwargs)
        context.check_hostname = False
        context.verify_mode = ssl.CERT_NONE
        return context
    ssl.create_default_context = unverified_create_default_context

DEFAULT_FROM_EMAIL = os.getenv("DEFAULT_FROM_EMAIL", "TA-ATS <no-reply@ta-ats.local>")
OTP_EXPIRY_MINUTES = int(os.getenv("OTP_EXPIRY_MINUTES", "5"))

# --- WhatsApp (send2.digital) ---
WHATSAPP_API_URL = os.getenv("WHATSAPP_API_URL", "")
WHATSAPP_API_USERNAME = os.getenv("WHATSAPP_API_USERNAME", "")
WHATSAPP_API_PASSWORD = os.getenv("WHATSAPP_API_PASSWORD", "")
WHATSAPP_TEMPLATE_NAME = os.getenv("WHATSAPP_TEMPLATE_NAME", "")
WHATSAPP_PHONE_PARAM = os.getenv("WHATSAPP_PHONE_PARAM", "number")
WHATSAPP_VAR_PARAM = os.getenv("WHATSAPP_VAR_PARAM", "variable")
WHATSAPP_MEDIA_TYPE = os.getenv("WHATSAPP_MEDIA_TYPE", "text")

# --- SMS (leewayapi / DLT) ---
SMS_API_URL = os.getenv("SMS_API_URL", "")
SMS_USERNAME = os.getenv("SMS_USERNAME", "")
SMS_PASSWORD = os.getenv("SMS_PASSWORD", "")
SMS_SENDER_ID = os.getenv("SMS_SENDER_ID", "")
SMS_PEID = os.getenv("SMS_PEID", "")
SMS_TM_ID = os.getenv("SMS_TM_ID", "")
SMS_CONTENT_ID = os.getenv("SMS_CONTENT_ID", "")
# OTP-over-SMS. Message + DLT content-id are configurable so the ATS-specific
# template can be swapped in later without a code change. {otp} is substituted.
SMS_OTP_TEMPLATE = os.getenv(
    "SMS_OTP_TEMPLATE",
    "{otp} is your OTP for login in iHRMS portal - Indovision Services Pvt. Ltd",
)
SMS_OTP_CONTENT_ID = os.getenv("SMS_OTP_CONTENT_ID", "") or SMS_CONTENT_ID

DJANGO_APPS = [
    "django.contrib.admin",
    "django.contrib.auth",
    "django.contrib.contenttypes",
    "django.contrib.sessions",
    "django.contrib.messages",
    "django.contrib.staticfiles",
]
THIRD_PARTY_APPS = [
    "rest_framework",
    "corsheaders",
    "drf_spectacular",
    "rest_framework_simplejwt.token_blacklist",
    # "django_filters",  # TEMP: pkg not installed (offline). Re-add after `pip install django-filter`.
]
LOCAL_APPS = [
    "apps.users",
    "apps.authentication",
    "apps.audit_logs",
    "apps.dashboard",
    "apps.candidates",
    "apps.jobs",
    "apps.interviews",
    "apps.reports",
    "apps.clients",
    "apps.menus",
    "apps.pipeline",
    "apps.master_skills",
    "apps.master_data",
    "apps.master_designations",
    "apps.master_annual_ctc",
    "apps.llm",
    "apps.ai_calls",
    "apps.notifications",
    "apps.agents",
]
INSTALLED_APPS = DJANGO_APPS + THIRD_PARTY_APPS + LOCAL_APPS

# Custom user model — MUST be set before the first migration
AUTH_USER_MODEL = "users.User"

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

ALLOWED_HOSTS = [
    "localhost",
    "127.0.0.1",
    "indovisionconsultancy.in",
    ".indovisionconsultancy.in",
    "ats.indovisionconsultancy.in",
    "66.116.227.7",
]

ROOT_URLCONF = "config.urls"

TEMPLATES = [
    {
        "BACKEND": "django.template.backends.django.DjangoTemplates",
        "DIRS": [],
        "APP_DIRS": True,
        "OPTIONS": {
            "context_processors": [
                "django.template.context_processors.request",
                "django.contrib.auth.context_processors.auth",
                "django.contrib.messages.context_processors.messages",
            ],
        },
    },
]

WSGI_APPLICATION = "config.wsgi.application"
ASGI_APPLICATION = "config.asgi.application"

DATABASES = {
    "default": {
        "ENGINE": "django.db.backends.postgresql",
        "NAME": os.getenv("DB_NAME", "ats_main"),
        "USER": os.getenv("DB_USER", "postgres"),
        "PASSWORD": os.getenv("DB_PASSWORD", ""),
        "HOST": os.getenv("DB_HOST", "localhost"),
        "PORT": os.getenv("DB_PORT", "5432"),
    }
}

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"},
]

AUTHENTICATION_BACKENDS = [
    "apps.authentication.backends.MCPAuthBackend",
    "django.contrib.auth.backends.ModelBackend",
]

REST_FRAMEWORK = {
    "DEFAULT_AUTHENTICATION_CLASSES": (
        "rest_framework_simplejwt.authentication.JWTAuthentication",
    ),
    "DEFAULT_PERMISSION_CLASSES": (
        "rest_framework.permissions.IsAuthenticated",
    ),
    "DEFAULT_PAGINATION_CLASS": "core.pagination.DefaultPagination",
    "PAGE_SIZE": 20,
    "EXCEPTION_HANDLER": "core.exceptions.custom_exception_handler",
    "DEFAULT_SCHEMA_CLASS": "drf_spectacular.openapi.AutoSchema",
}

SPECTACULAR_SETTINGS = {
    "TITLE": "TA-ATS API",
    "DESCRIPTION": "Applicant Tracking System backend API",
    "VERSION": "1.0.0",
    "SERVE_INCLUDE_SCHEMA": False,
}

SIMPLE_JWT = {
    "ACCESS_TOKEN_LIFETIME": timedelta(minutes=15),
    "REFRESH_TOKEN_LIFETIME": timedelta(days=7),
    "AUTH_HEADER_TYPES": ("Bearer",),
    "USER_ID_FIELD": "id",
    "USER_ID_CLAIM": "user_id",
}

CORS_ALLOWED_ORIGINS = os.getenv(
    "CORS_ALLOWED_ORIGINS", "http://localhost:3000"
).split(",")

# Public base URL of the Next.js frontend, used to build deep links in emails
# (e.g. the "View JD" button). Defaults to the first CORS origin.
FRONTEND_URL = os.getenv(
    "FRONTEND_URL", (CORS_ALLOWED_ORIGINS[0] if CORS_ALLOWED_ORIGINS else "http://localhost:3000")
).rstrip("/")

LANGUAGE_CODE = "en-us"
TIME_ZONE = "Asia/Kolkata"
USE_I18N = True
USE_TZ = True

STATIC_URL = "static/"
STATIC_ROOT = BASE_DIR / "staticfiles"
MEDIA_URL = "media/"
# Uploads are written into the Next.js frontend's public/ so they can be served
# by both Django (dev) and Next.js static hosting.
MEDIA_ROOT = BASE_DIR.parent / "frontend" / "public" / "media"

# Private media — sensitive uploads (candidate résumés) that must NOT be served
# statically. Files here are reachable ONLY through the signed, permission-checked
# download endpoint (apps.candidates.views.CandidateResumeDownloadView).
PRIVATE_MEDIA_ROOT = BASE_DIR / "private_media"
# TTL (seconds) for signed résumé URLs handed to the frontend.
RESUME_URL_TTL = int(os.getenv("RESUME_URL_TTL", "3600"))

DEFAULT_AUTO_FIELD = "django.db.models.BigAutoField"

# Fernet key for encrypting LLM API keys at rest. Set a dedicated key in .env;
# falls back to a SECRET_KEY-derived key for dev if unset.
LLM_ENCRYPTION_KEY = os.getenv("LLM_ENCRYPTION_KEY", "")

# Fernet key for encrypting numeric IDs embedded in emailed deep links (e.g.
# the JD approval "View JD" button), so raw primary keys aren't exposed in
# URLs. Set a dedicated key in .env; falls back to a SECRET_KEY-derived key
# for dev if unset. See core/crypto.py.
ID_ENCRYPTION_KEY = os.getenv("ID_ENCRYPTION_KEY", "")

# Fernet key for the encrypted source-tracking token carried by public job
# application URLs (/careers/jobs/<public_id>?t=...), so the publishing platform
# is never exposed in a public link and can't be edited by the visitor. Set a
# dedicated key in .env; falls back to a SECRET_KEY-derived key for dev.
# See apps/jobs/tracking_tokens.py.
JOB_TRACKING_ENCRYPTION_KEY = os.getenv("JOB_TRACKING_ENCRYPTION_KEY", "")

# App loggers (résumé parsing, LLM calls, …) — INFO+ to console so parser
# successes/fallbacks/failures are always visible in the server output.
LOGGING = {
    "version": 1,
    "disable_existing_loggers": False,
    "formatters": {
        "app": {"format": "[{levelname}] {asctime} {name}: {message}", "style": "{"},
    },
    "handlers": {
        "console": {"class": "logging.StreamHandler", "formatter": "app"},
    },
    "loggers": {
        "apps": {"handlers": ["console"], "level": "INFO", "propagate": False},
    },
}

# ── AI screening calls ───────────────────────────────────────────────────────
# Provider: mock | selfhosted | hunar — see apps/ai_calls/providers/ and
# docs/ai-calling-platform/PHASE1-ARCHITECTURE.md. mock simulates the full
# call lifecycle locally (NO phone is dialled); selfhosted talks to the
# open-source platform; hunar places real calls via Hunar AI's hosted API.
AI_CALL_PROVIDER = (os.getenv("AI_CALL_PROVIDER", "") or "mock").lower()
# `mock` fabricates a full call lifecycle (Connected/Completed + a generated
# transcript and score) without dialling anything, which is indistinguishable
# from a real result once stored. Running it therefore requires this explicit
# opt-in; otherwise AI calling fails loudly instead of faking success.
AI_CALL_ALLOW_SIMULATED = os.getenv("AI_CALL_ALLOW_SIMULATED", "").lower() in ("1", "true", "yes")
# Self-hosted platform (scheduler_service) endpoint + shared HMAC secret
AI_PLATFORM_URL = os.getenv("AI_PLATFORM_URL", "http://localhost:9100")
AI_PLATFORM_SIGNING_SECRET = os.getenv("AI_PLATFORM_SIGNING_SECRET", "")
# Hunar AI hosted calling. Secrets come from the environment only — never commit
# a key. Required when AI_CALL_PROVIDER=hunar.
HUNAR_BASE_URL = os.getenv("HUNAR_BASE_URL", "https://api.voice.hunar.ai")
HUNAR_API_KEY = os.getenv("HUNAR_API_KEY", "")
HUNAR_AGENT_ID = os.getenv("HUNAR_AGENT_ID", "")
# Country code prepended when a candidate's number has no international prefix
# (most stored numbers are bare 10-digit Indian mobiles). Only affects the number
# sent to the provider — never the stored value.
HUNAR_DEFAULT_COUNTRY_CODE = os.getenv("HUNAR_DEFAULT_COUNTRY_CODE", "91")
# Public URL the platform uses to reach our callbacks (ngrok/host URL in prod)
PUBLIC_BASE_URL = os.getenv("PUBLIC_BASE_URL", "http://localhost:8001")
# Completed calls scoring at/above this are marked QUALIFIED (stage AI Qualified)
AI_QUALIFY_THRESHOLD = int(os.getenv("AI_QUALIFY_THRESHOLD", "60"))

# LinkedIn job posting (JD-006). Leave blank to simulate.
LINKEDIN_ACCESS_TOKEN = os.getenv("LINKEDIN_ACCESS_TOKEN", "")
LINKEDIN_AUTHOR_URN = os.getenv("LINKEDIN_AUTHOR_URN", "")
LINKEDIN_CLIENT_ID = os.getenv("LINKEDIN_CLIENT_ID", "")
LINKEDIN_CLIENT_SECRET = os.getenv("LINKEDIN_CLIENT_SECRET", "")
LINKEDIN_REDIRECT_URI = os.getenv("LINKEDIN_REDIRECT_URI", "http://localhost:8000/api/v1/jobs/linkedin/callback/")
