from __future__ import annotations

from django.db.models import Q
from rest_framework import serializers, status
from rest_framework.pagination import PageNumberPagination
from rest_framework.response import Response
from rest_framework.views import APIView

from apps.access.drf import TenantPermission
from apps.crm import services
from apps.crm.models import Customer, Interaction
from interfaces.api_v1.serializers import UserBriefSerializer


class CustomerSerializer(serializers.ModelSerializer):
    owner = UserBriefSerializer(read_only=True)
    created_by = UserBriefSerializer(read_only=True)
    last_contact_on = serializers.SerializerMethodField()
    last_contact_time = serializers.SerializerMethodField()

    class Meta:
        model = Customer
        fields = [
            "id", "name", "kind", "status", "phone", "email", "address", "notes", "owner", "created_by",
            "created_at", "last_contact_on", "last_contact_time",
        ]

    def _last(self, obj):
        if hasattr(obj, "last_contact_on"):  # annotated by the list/detail queries
            return obj.last_contact_on, obj.last_contact_time
        latest = obj.interactions.first()  # Meta.ordering = newest first
        return (latest.occurred_on, latest.occurred_time) if latest else (None, None)

    def get_last_contact_on(self, obj):
        value = self._last(obj)[0]
        return value.isoformat() if value else None

    def get_last_contact_time(self, obj):
        value = self._last(obj)[1]
        return value.strftime("%H:%M") if value else None


class CustomerInput(serializers.Serializer):
    name = serializers.CharField(max_length=200, required=False)
    kind = serializers.CharField(required=False)
    status = serializers.CharField(required=False)
    phone = serializers.CharField(max_length=30, required=False, allow_blank=True)
    email = serializers.CharField(max_length=200, required=False, allow_blank=True)
    address = serializers.CharField(max_length=300, required=False, allow_blank=True)
    notes = serializers.CharField(required=False, allow_blank=True)
    owner = serializers.IntegerField(required=False, allow_null=True)


class InteractionSerializer(serializers.ModelSerializer):
    created_by = UserBriefSerializer(read_only=True)

    class Meta:
        model = Interaction
        fields = ["id", "type", "summary", "occurred_on", "occurred_time", "follow_up_on", "created_by"]


class InteractionInput(serializers.Serializer):
    type = serializers.CharField()
    summary = serializers.CharField()
    occurred_on = serializers.DateField()
    occurred_time = serializers.TimeField(required=False, allow_null=True)
    follow_up_on = serializers.DateField(required=False, allow_null=True)


class Pagination(PageNumberPagination):
    page_size = 50
    page_size_query_param = "page_size"
    max_page_size = 100


class CustomerListCreateView(APIView):
    permission_classes = [TenantPermission]
    module_code = "crm"
    permission_map = {"GET": "crm.view", "POST": "crm.create"}

    def get(self, request):
        qs = services.visible_customers(request.tenant, "crm.view")
        params = request.query_params
        if params.get("status"):
            qs = qs.filter(status=params["status"])
        search = (params.get("search") or "").strip()
        if search:
            qs = qs.filter(Q(name__icontains=search) | Q(phone__icontains=search) | Q(email__icontains=search))
        paginator = Pagination()
        page = paginator.paginate_queryset(qs, request)
        return paginator.get_paginated_response(CustomerSerializer(page, many=True).data)

    def post(self, request):
        data = CustomerInput(data=request.data)
        data.is_valid(raise_exception=True)
        customer = services.create_customer(request.tenant, data=data.validated_data, request=request)
        return Response(CustomerSerializer(customer).data, status=status.HTTP_201_CREATED)


class CustomerDetailView(APIView):
    permission_classes = [TenantPermission]
    module_code = "crm"
    permission_map = {"GET": "crm.view", "PATCH": "crm.update", "DELETE": "crm.delete"}
    scope_map = {"DELETE": "organization"}

    def get(self, request, pk):
        return Response(CustomerSerializer(services.get_customer(request.tenant, pk, "crm.view")).data)

    def patch(self, request, pk):
        customer = services.get_customer(request.tenant, pk, "crm.update")
        data = CustomerInput(data=request.data, partial=True)
        data.is_valid(raise_exception=True)
        return Response(CustomerSerializer(services.update_customer(request.tenant, customer, data=data.validated_data, request=request)).data)

    def delete(self, request, pk):
        services.delete_customer(request.tenant, services.get_customer(request.tenant, pk, "crm.delete"), request=request)
        return Response(status=status.HTTP_204_NO_CONTENT)


class InteractionListCreateView(APIView):
    permission_classes = [TenantPermission]
    module_code = "crm"
    permission_map = {"GET": "crm.view", "POST": "crm.update"}

    def get(self, request, pk):
        customer = services.get_customer(request.tenant, pk, "crm.view")
        return Response(InteractionSerializer(customer.interactions.select_related("created_by"), many=True).data)

    def post(self, request, pk):
        customer = services.get_customer(request.tenant, pk, "crm.update")
        data = InteractionInput(data=request.data)
        data.is_valid(raise_exception=True)
        interaction = services.add_interaction(request.tenant, customer, data=dict(data.validated_data), request=request)
        return Response(InteractionSerializer(interaction).data, status=status.HTTP_201_CREATED)


class InteractionDeleteView(APIView):
    permission_classes = [TenantPermission]
    module_code = "crm"
    permission_map = {"DELETE": "crm.update"}

    def delete(self, request, pk):
        services.get_interaction(request.tenant, pk).delete()
        return Response(status=status.HTTP_204_NO_CONTENT)


class OwnerListView(APIView):
    permission_classes = [TenantPermission]
    module_code = "crm"
    permission_map = {"GET": "crm.assign"}
    scope_map = {"GET": "organization"}

    def get(self, request):
        return Response([UserBriefSerializer(m.user).data for m in services.assignable_members(request.tenant)])
