from rest_framework import status, viewsets
from rest_framework.response import Response
from rest_framework.views import APIView
from .serializers import ContactUsSerializer, ContactUsMarkStatusSerializer
from .models import ContactUs
from django_filters.rest_framework import DjangoFilterBackend
from rest_framework.filters import SearchFilter
from .tasks import send_contact_us_inquiry_emails
from inquiry.models import CustomInquiryPagination
from .filters import ContactUsFilter
from rest_framework.decorators import action
from activity_logs.models import ActivityLogs
from inquiry.serializers import DownloadInquiriesFilterSerializer
from .tasks import download_report_of_general_inquiries
from django.core.cache import cache
from django.http import FileResponse
import os
from drf_spectacular.utils import extend_schema, OpenApiResponse
from users.permissions import IsAdminOrMaintainer


# Create your views here.
class ContactUsViewset(viewsets.ModelViewSet):
    queryset = ContactUs.objects.order_by("-created_at")
    filter_backends = [DjangoFilterBackend, SearchFilter]
    filterset_class = ContactUsFilter
    http_method_names = ["get", "post", "delete"]
    pagination_class = CustomInquiryPagination

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

        is_admin_path = any(route in path for route in ["/mark-status"])

        if method == "POST" and not is_admin_path:
            return []

        return [IsAdminOrMaintainer()]

    def get_serializer_class(self):
        path = self.request.path

        if "mark-status" in path:
            return ContactUsMarkStatusSerializer

        return ContactUsSerializer

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

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

        ContactUs.objects.create(**validated_data)
        send_contact_us_inquiry_emails.delay(validated_data)

        return Response(
            {"message": "Inquiry has been submitted successfully."},
            status=status.HTTP_200_OK,
        )

    @action(detail=False, methods=["POST"], url_path="mark-status")
    def mark_status(self, request):
        data = request.data

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

        id = validated_data.get("inquiry_id")
        inquiry_status = validated_data.get("status")

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

        try:
            inquiry = ContactUs.objects.get(id=id)
            inquiry.status = inquiry_status
            inquiry.save()

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


class DownloadGeneralInquiryReportAPIView(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_general_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("general_inquiry_download_status", None)
        download_errors = cache.get("general_inquiry_download_errors", None)
        download_path = cache.get("general_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,
            )
