from rest_framework import status, viewsets
from rest_framework.decorators import action
from rest_framework.response import Response
from rest_framework.views import APIView
from .serializers import (
    InquiriesSerializer,
    InquiriesStatusSerializer,
    DownloadInquiriesFilterSerializer,
)
from .models import Inquiries, CustomInquiryPagination
from rest_framework.permissions import AllowAny
from django_filters.rest_framework import DjangoFilterBackend
from rest_framework.filters import SearchFilter
from .tasks import send_emails
import logging, os
from products.models import Products
from activity_logs.models import ActivityLogs
from .tasks import download_report_of_inquiries
from django.core.cache import cache
from django.http import FileResponse
from .filters import InquiriesFilter
from drf_spectacular.utils import extend_schema, OpenApiResponse
from users.permissions import IsAdminOrMaintainer

logging.basicConfig(
    level=logging.INFO, format="%(asctime)s - %(levelname)s - %(message)s"
)


# Create your views here.
class InquiriesViewset(viewsets.ModelViewSet):
    queryset = Inquiries.objects.order_by("-created_at").select_related("product")
    serializer_class = InquiriesSerializer
    pagination_class = CustomInquiryPagination
    filter_backends = [DjangoFilterBackend, SearchFilter]
    filterset_class = InquiriesFilter
    http_method_names = ["get", "post", "delete"]

    def get_permissions(self):
        method = self.request.method

        if method == "POST":
            return [AllowAny()]
        else:
            return [IsAdminOrMaintainer()]

    def create(self, request, *args, **kwargs):
        data = request.data

        serializer = self.serializer_class(data=data)
        serializer.is_valid(raise_exception=True)
        validated_data = serializer.validated_data

        product = validated_data.get("product", None)

        if product is None:
            return Response(
                {"message": "Inquiry must include a product to inquire."},
                status=status.HTTP_400_BAD_REQUEST,
            )

        try:
            if not isinstance(product, Products):  # pragma: no cover
                product = Products.objects.get(id=product)

            logging.info("Creating new inquiry object")
            created_inquiry = Inquiries.objects.create(**validated_data)

            created_inquiry_details = {
                "name": f"{created_inquiry.first_name} {created_inquiry.last_name}",
                "created_at": created_inquiry.created_at,
                "email": created_inquiry.email,
                "contact_number": created_inquiry.contact_number,
                "inquiry": created_inquiry.inquiry,
                "product": product.name,
                "product_subcategory": product.category.sub_category_name,
            }
            send_emails.delay(created_inquiry=created_inquiry_details)

            return Response(
                {"message": "Inquiry was created successfully."},
                status=status.HTTP_201_CREATED,
            )
        except Products.DoesNotExist:  # pragma: no cover
            return Response(
                {"message": "Product to inquire not found."},
                status=status.HTTP_404_NOT_FOUND,
            )


class InquiryMarkStatusAPIView(APIView):
    permission_classes = [IsAdminOrMaintainer]
    serializer_class = InquiriesStatusSerializer

    def post(self, request, *args, **kwargs):
        data = request.data
        init_status = data.get("status")

        if init_status.lower() not in ["pending", "endorsed", "spam"]:
            return Response(
                {
                    "message": f"'{init_status}' is not a valid option. Choose between 'pending', 'endorsed', and 'spam' only."
                },
                status=status.HTTP_400_BAD_REQUEST,
            )

        serializer = self.serializer_class(data=data)
        serializer.is_valid(raise_exception=True)
        validated_data = serializer.validated_data

        try:
            inquiry_id = validated_data["inquiry_id"]

            inquiry = Inquiries.objects.get(id=inquiry_id)
            inquiry.status = validated_data["status"]
            inquiry.save()

            ActivityLogs.record_activity(
                user=request.user,
                action=f"Marked inquiry from {inquiry.email} for {inquiry.product.name} to '{inquiry.status}'",
            )
            return Response(
                {"message": "Inquiry status was updated successfully."},
                status=status.HTTP_200_OK,
            )
        except Inquiries.DoesNotExist:
            return Response(
                {"message": "Inquiry not found."}, status=status.HTTP_404_NOT_FOUND
            )


class DownloadInquiryReportAPIView(APIView):
    permission_classes = [IsAdminOrMaintainer]
    serializer_class = DownloadInquiriesFilterSerializer

    def post(self, request):
        """
        Date formats must be YYYY-MM-DD
        """
        start_date = request.data.get("start_date", None)
        end_date = request.data.get("end_date", None)
        inquiry_status = request.data.get("status", None)

        filters_dict = {
            "start_date": start_date,
            "end_date": end_date,
            "inquiry_status": inquiry_status,
        }

        download_report_of_inquiries.delay(filters_dict=filters_dict)

        return Response(
            {"message": "File download initiated."}, status=status.HTTP_200_OK
        )

    @extend_schema(
        responses={
            200: OpenApiResponse(
                response={
                    "type": "object",
                    "properties": {
                        "message": {
                            "type": "string",
                            "example": "Upload in progress/No upload initiated/Upload finished",
                        },
                        "status": {
                            "type": "string",
                            "example": "none/uploading/finished",
                        },
                    },
                },
            ),
            500: OpenApiResponse(
                response={
                    "type": "object",
                    "properties": {
                        "message": {
                            "type": "string",
                            "example": "Error during upload.",
                        },
                        "status": {
                            "type": "string",
                            "example": "error",
                        },
                        "detailed_error": {
                            "type": "string",
                            "example": "Uploaded file is not a type of file",
                        },
                    },
                },
            ),
        },
    )
    def get(self, request):
        download_status = cache.get("inquiry_download_status", None)
        download_errors = cache.get("inquiry_download_errors", None)
        download_path = cache.get("inquiry_download_path", None)

        if download_status is None:
            return Response(
                {"message": "No file is being downloaded.", "status": "none"},
                status=status.HTTP_200_OK,
            )

        if download_status == "downloading":
            return Response(
                {"message": "File is downloading...", "status": download_status},
                status=status.HTTP_200_OK,
            )

        if download_status == "finished":
            filename = os.path.basename(download_path)
            return FileResponse(
                open(download_path, "rb"), as_attachment=True, filename=filename
            )

        if download_status == "error":
            return Response(
                {
                    "message": "Error while downloading",
                    "status": download_status,
                    "detailed_error": download_errors,
                },
                status=status.HTTP_500_INTERNAL_SERVER_ERROR,
            )
