# views.py
import logging
from django.core.exceptions import ObjectDoesNotExist
from django.utils.decorators import method_decorator
from django.views.decorators.cache import cache_control
from django.http import JsonResponse

from rest_framework import generics, permissions, status, serializers
from rest_framework.exceptions import ValidationError

from core.models import AppSettings
from core.utils import get_api_message
from .models import CustomerField
from .serializers import CustomerFieldWriteSerializer, CustomerFieldReadSerializer

# logger = logging.getLogger(__name__)

logger = logging.getLogger("application-log")


# ---- Permissions (same as before) ----
class HasCustomerProfile(permissions.BasePermission):
    def has_permission(self, request, view):
        return getattr(request.user, "customer", None) is not None


class IsCustomerFieldOwner(permissions.BasePermission):
    def has_object_permission(self, request, view, obj: CustomerField):
        customer = getattr(request.user, "customer", None)
        return customer is not None and obj.customer_id == customer.id


def _reshape_errors_for_ui(detail: dict):
    """
    Convert DRF error dict so 'field_name' -> 'name' to match your UI.
    """
    if not isinstance(detail, dict):
        return detail
    out = {}
    for k, v in detail.items():
        out["name" if k == "field_name" else k] = v
    return out


@method_decorator(cache_control(no_cache=True, must_revalidate=True, no_store=True), name="dispatch")
class FieldListCreateView(generics.ListCreateAPIView):
    """
    GET  /api/v1/fields/
      -> { success, message, code, data: { default_field, fields } }

    POST /api/v1/fields/
      -> create field -> { success, message, code, data }
    """
    permission_classes = [permissions.IsAuthenticated, HasCustomerProfile]

    def get(self, request):
        customer = getattr(request.user, "customer", None)
        if not customer:
            # return empty but with the standard envelope
            return JsonResponse(
                {
                    "success": True,
                    "message": get_api_message("FIELD_LIST", request),
                    "code": "FIELD_LIST",
                    "data": {"default_field": None, "fields": []},
                },
                status=status.HTTP_200_OK,
            )

        # Read default field id from AppSettings
        default_field_id = None
        try:
            app_settings = AppSettings.objects.get(customer_user=customer)
            default_field_id = (app_settings.default_field or {}).get("id")
        except AppSettings.DoesNotExist:
            pass

        qs = CustomerField.objects.filter(customer=customer).order_by("-created_at")

        default_field = None
        if default_field_id:
            try:
                default_obj = qs.get(pk=default_field_id)
                default_field = CustomerFieldReadSerializer(default_obj, context={"request": request}).data
                qs = qs.exclude(pk=default_field_id)
            except CustomerField.DoesNotExist:
                default_field = None

        fields = CustomerFieldReadSerializer(qs, many=True, context={"request": request}).data

        # ✅ Standard envelope for GET
        return JsonResponse(
            {
                "success": True,
                "message": get_api_message("FIELD_LIST", request),
                "code": "FIELD_LIST",
                "data": {"default_field": default_field, "fields": fields},
            },
            status=status.HTTP_200_OK,
        )

    def get_serializer_class(self):
        return CustomerFieldWriteSerializer if self.request.method == "POST" else CustomerFieldReadSerializer

    def get_serializer_context(self):
        ctx = super().get_serializer_context()
        ctx["request"] = self.request
        return ctx

    def post(self, request):
        ser = self.get_serializer(data=request.data)
        try:
            ser.is_valid(raise_exception=True)
        except serializers.ValidationError as e:  # <- catch from rest_framework.serializers
            codes = e.get_codes() if hasattr(e, "get_codes") else {}
            # Detect duplicate-field-name to return 409 + FIELD_DUPLICATE
            if isinstance(codes, dict) and "field_name" in codes:
                c = codes["field_name"]
                if isinstance(c, (list, tuple)) and "duplicate-field-name" in c:
                    return JsonResponse(
                        {
                            "success": False,
                            "message": get_api_message("DUPLICATE_FIELD", request),
                            "code": "FIELD_DUPLICATE",
                            "errors": _reshape_errors_for_ui(e.detail),
                        },
                        status=status.HTTP_409_CONFLICT,
                    )
            return JsonResponse(
                {
                    "success": False,
                    "message": get_api_message("VALIDATION_ERROR", request),
                    "code": "VALIDATION_ERROR",
                    "errors": _reshape_errors_for_ui(e.detail),
                },
                status=status.HTTP_400_BAD_REQUEST,
            )

        instance = ser.save()
        read = CustomerFieldReadSerializer(instance).data
        # expose id & name (not field_name) like your UI
        data = {"id": read["id"], "field_name": getattr(instance, "field_name", read.get("field_name"))}

        return JsonResponse(
            {
                "success": True,
                "message": get_api_message("FIELD_CREATED", request),
                "code": "FIELD_CREATED",
                "data": data,
            },
            status=status.HTTP_201_CREATED,
        )


@method_decorator(cache_control(no_cache=True, must_revalidate=True, no_store=True), name="dispatch")
class FieldDetailView(generics.RetrieveUpdateDestroyAPIView):
    """
    GET    /api/v1/fields/<id>/
    PUT    /api/v1/fields/<id>/
    PATCH  /api/v1/fields/<id>/
    DELETE /api/v1/fields/<id>/
    """
    permission_classes = [permissions.IsAuthenticated, HasCustomerProfile, IsCustomerFieldOwner]
    lookup_url_kwarg = "id"

    def get_queryset(self):
        customer = getattr(self.request.user, "customer", None)
        if customer is None:
            return CustomerField.objects.none()
        return CustomerField.objects.filter(customer=customer)

    def get_serializer_class(self):
        return CustomerFieldWriteSerializer if self.request.method in {"PUT", "PATCH"} else CustomerFieldReadSerializer

    def get_serializer_context(self):
        ctx = super().get_serializer_context()
        ctx["request"] = self.request
        return ctx

    # --- Fetch (optional envelope to match Buyer) ---
    def get(self, request, *args, **kwargs):
        instance = self.get_object()
        data = CustomerFieldReadSerializer(instance).data
        return JsonResponse(
            {
                "success": True,
                "message": get_api_message("FIELD_FETCHED", request),
                "code": "FIELD_FETCHED",
                "data": data,
            },
            status=200,
        )

    # --- Update ---
    def put(self, request, *args, **kwargs):
        return self._update(request, partial=False)

    def patch(self, request, *args, **kwargs):
        return self._update(request, partial=True)

    def _update(self, request, partial: bool):
        instance = self.get_object()
        ser = self.get_serializer(instance, data=request.data, partial=partial)
        try:
            ser.is_valid(raise_exception=True)
        except ValidationError as e:
            logger.error(e)
            codes = getattr(e, "get_codes", lambda: {})()
            if isinstance(codes, dict) and "field_name" in codes:
                c = codes["field_name"]
                if isinstance(c, (list, tuple)) and "duplicate-field-name" in c:
                    return JsonResponse(
                        {
                            "success": False,
                            "message": get_api_message("DUPLICATE_FIELD", request),
                            "code": "DUPLICATE_FIELD",
                            "errors": _reshape_errors_for_ui(e.detail),
                        },
                        status=409,
                    )
            return JsonResponse(
                {
                    "success": False,
                    "message": get_api_message("VALIDATION_ERROR", request),
                    "code": "VALIDATION_ERROR",
                    "errors": _reshape_errors_for_ui(e.detail),
                },
                status=400,
            )

        updated = ser.save()
        # Minimal data like your screenshot
        data = {"id": updated.id, "name": updated.field_name}
        return JsonResponse(
            {
                "success": True,
                "message": get_api_message("FIELD_UPDATED", request),
                "code": "FIELD_UPDATED",
                "data": data,
            },
            status=200,
        )

    # --- Delete ---
    def delete(self, request, *args, **kwargs):
        instance = self.get_object()

        # 1) Block if default field
        is_default = AppSettings.objects.filter(
            customer_user=instance.customer,
            default_field__id=instance.id
        ).exists()
        if is_default:
            return JsonResponse(
                {
                    "success": False,
                    "message": get_api_message("FIELD_DEFAULT_DELETE_BLOCKED", request),
                    "code": "FIELD_DEFAULT_DELETE_BLOCKED",
                },
                status=409,
            )

        # 2) Block if related results/records exist
        related_fields = [f for f in instance._meta.get_fields() if (f.one_to_many or f.one_to_one) and f.auto_created]
        for rel in related_fields:
            accessor = rel.get_accessor_name()
            related_attr = getattr(instance, accessor)
            try:
                if hasattr(related_attr, "exists"):  # one-to-many
                    if related_attr.exists():
                        return JsonResponse(
                            {
                                "success": False,
                                "message": get_api_message("FIELD_HAS_RELATED_RECORDS", request),
                                "code": "FIELD_HAS_RELATED_RECORDS",
                            },
                            status=409,
                        )
                else:  # one-to-one present
                    _ = related_attr
                    return JsonResponse(
                        {
                            "success": False,
                            "message": get_api_message("FIELD_HAS_RELATED_RECORDS", request),
                            "code": "FIELD_HAS_RELATED_RECORDS",
                        },
                        status=409,
                    )
            except ObjectDoesNotExist:
                pass

        # 3) Safe delete
        self.perform_destroy(instance)
        return JsonResponse(
            {
                "success": True,
                "message": get_api_message("FIELD_DELETED", request),
                "code": "FIELD_DELETED",
            },
            status=200,
        )
