"""Admin-portal-editable platform settings (V2 §0.8 direction).

AzamPay credentials and FCM push credentials, both via the same pattern
(encrypted PlatformSetting rows via core.settings_store) which is
provider-agnostic and can carry other secrets later without new plumbing.

Superuser-only, same as core.admin_rbac's access-management endpoints —
rotating a payment/push provider's credentials is at least as sensitive as
staff role management.
"""

import json

from django.conf import settings as django_settings
from rest_framework import status
from rest_framework.decorators import api_view
from rest_framework.response import Response

from . import push as fcm_push
from .admin_api import _audit, _operator, _require_admin
from .admin_rbac import _require_superuser
from .settings_store import get_setting, has_db_value, mask, set_setting

# (settings key suffix, request field name, env var fallback)
_AZAMPAY_FIELDS = [
    ("app_name", "app_name", "AZAMPAY_APP_NAME"),
    ("client_id", "client_id", "AZAMPAY_CLIENT_ID"),
    ("client_secret", "client_secret", "AZAMPAY_CLIENT_SECRET"),
    ("callback_secret", "callback_secret", "AZAMPAY_CALLBACK_SECRET"),
    ("checksum_public_key", "checksum_public_key", "AZAMPAY_CHECKSUM_PUBLIC_KEY"),
]


@api_view(["GET", "PUT"])
def admin_azampay_settings(request):
    err = _require_admin(request)
    if err:
        return err

    if request.method == "PUT":
        err = _require_superuser(request)
        if err:
            return err
        updated = []
        for key_suffix, field_name, _env_var in _AZAMPAY_FIELDS:
            value = request.data.get(field_name)
            if value is None or value == "":
                continue  # blank/omitted fields are left untouched, never cleared accidentally
            set_setting(f"azampay_{key_suffix}", str(value), updated_by=_operator(request))
            updated.append(field_name)
        _audit(request, "settings.azampay.update", None, {"fields_updated": updated})

    payload = {}
    for key_suffix, field_name, env_var in _AZAMPAY_FIELDS:
        value = get_setting(f"azampay_{key_suffix}", env_var)
        payload[field_name] = {
            "configured": bool(value),
            "source": "database" if has_db_value(f"azampay_{key_suffix}") else "env",
            "masked_value": mask(value),
        }
    payload["system"] = {
        "active_provider": getattr(django_settings, "PAYMENT_PROVIDER", "manual"),
        "demo_mode": bool(getattr(django_settings, "AZAMPAY_DEMO_MODE", False)),
        "checksum_fields_configured": bool(getattr(django_settings, "AZAMPAY_CHECKSUM_FIELDS", "")),
    }
    return Response(payload, status=status.HTTP_200_OK)


@api_view(["GET", "PUT"])
def admin_fcm_settings(request):
    """The Firebase service-account JSON that lets core.push send real FCM
    notifications — see core/push.py. Until this is set, push_notification()
    still always writes the in-app Notification; only the push dispatch is a
    no-op."""
    err = _require_admin(request)
    if err:
        return err

    if request.method == "PUT":
        err = _require_superuser(request)
        if err:
            return err
        raw = request.data.get("service_account_json")
        if raw not in (None, ""):
            if isinstance(raw, dict):
                raw = json.dumps(raw)
            try:
                parsed = json.loads(raw)
            except (TypeError, ValueError):
                return Response({"detail": "service_account_json must be valid JSON."}, status=status.HTTP_400_BAD_REQUEST)
            if not all(parsed.get(k) for k in ("client_email", "private_key", "project_id")):
                return Response(
                    {"detail": "service_account_json is missing client_email, private_key, or project_id."},
                    status=status.HTTP_400_BAD_REQUEST,
                )
            set_setting("fcm_service_account_json", json.dumps(parsed), updated_by=_operator(request))
            _audit(request, "settings.fcm.update", None, {"project_id": parsed.get("project_id")})

    value = get_setting("fcm_service_account_json", "FCM_SERVICE_ACCOUNT_JSON")
    project_id = ""
    if value:
        try:
            project_id = json.loads(value).get("project_id", "")
        except ValueError:
            project_id = ""
    return Response({
        "service_account_json": {
            "configured": fcm_push.is_configured(),
            "source": "database" if has_db_value("fcm_service_account_json") else "env",
            "masked_value": mask(project_id) if project_id else "",
        },
    }, status=status.HTTP_200_OK)


@api_view(["GET", "PUT"])
def admin_kyc_gating(request):
    """Whether — and at what level — sellers must pass KYC before creating a
    deal (see escrow.views._require_seller_kyc). Not a secret, but kept on
    the same PlatformSetting rails as everything else in this file so ops
    can flip it without a deploy."""
    err = _require_admin(request)
    if err:
        return err

    if request.method == "PUT":
        err = _require_superuser(request)
        if err:
            return err

        if "enabled" in request.data:
            enabled = bool(request.data.get("enabled"))
            set_setting("kyc_gating_enabled", "1" if enabled else "0", updated_by=_operator(request))

        if "min_level" in request.data:
            try:
                level = int(request.data.get("min_level"))
            except (TypeError, ValueError):
                return Response({"detail": "min_level must be an integer."}, status=status.HTTP_400_BAD_REQUEST)
            if level not in (0, 1, 2, 3):
                return Response({"detail": "min_level must be between 0 and 3."}, status=status.HTTP_400_BAD_REQUEST)
            set_setting("kyc_gating_min_level", str(level), updated_by=_operator(request))

        _audit(request, "settings.kyc_gating.update", None, {
            "enabled": request.data.get("enabled"), "min_level": request.data.get("min_level"),
        })

    from escrow.views import _seller_kyc_gating_settings

    enabled, min_level = _seller_kyc_gating_settings()
    return Response({"enabled": enabled, "min_level": min_level}, status=status.HTTP_200_OK)
