import pandas as pd
from rest_framework import status
from rest_framework.generics import CreateAPIView
from rest_framework.parsers import MultiPartParser
from rest_framework.permissions import IsAuthenticated, IsAdminUser
from rest_framework.response import Response

from apps.master.serializers import csv_master_serializers


class AmenitiesCSVUploadView(CreateAPIView):
    """
    This is the AmenitiesCSVUploadView.

    It handles the CSV file upload for amenities data.

    Attributes:
        parser_classes (tuple): The parsers used for request data (MultiPartParser for handling file uploads).
        serializer_class (Serializer): The serializer class for the uploaded data.
        permission_classes (tuple): Permissions required to access this view (IsAuthenticated for authenticated users).

    Methods:
        post(request, *args, **kwargs): Handles the processing of uploaded CSV data.
    """

    parser_classes = (MultiPartParser,)
    serializer_class = csv_master_serializers.AmenitiesUploadCSVSerializers
    permission_classes = (IsAuthenticated, IsAdminUser)

    def post(self, request, *args, **kwargs):
        """
        Handles the processing of uploaded CSV data and creation of amenities.

        Args:
            request (HttpRequest): The HTTP request containing the uploaded CSV file.

        Returns:
            Response: A response indicating the success or failure of the CSV data upload.
        """
        file = request.FILES.get("file")

        # Check if the file was provided in the request
        if not file:
            return Response(
                {"message": "File not provided"}, status=status.HTTP_400_BAD_REQUEST
            )

        # Check if the file has a .csv extension
        if not file.name.endswith(".csv"):
            return Response(
                {"message": "Invalid file format"}, status=status.HTTP_400_BAD_REQUEST
            )

        # Parse the CSV file and create data for the model
        df = pd.read_csv(file)
        columns = list(df.columns)

        # Required column names for csv file
        required_columns = ["name", "type_id"]

        # Check if the required columns are present in the CSV file
        if all(col in columns for col in required_columns):
            json_data = [dict(row) for _, row in df.iterrows()]

            # Serialize and save the data
            serializer = csv_master_serializers.AmenitiesUploadCSVSerializers(
                data=json_data, many=True
            )

            print(serializer)

            if serializer.is_valid():
                serializer.save()
                return Response(
                    {"message": "Amenities uploaded successfully"},
                    status=status.HTTP_200_OK,
                )
            else:
                return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
        else:
            return Response(
                {"message": f"File must have {', '.join(required_columns)} columns"},
                status=status.HTTP_400_BAD_REQUEST,
            )


class ConnectorCSVUploadView(CreateAPIView):
    """
    This is the ConnectorCSVUploadView.

    It handles the CSV file upload for connectors data.

    Attributes:
        parser_classes (tuple): The parsers used for request data (MultiPartParser for handling file uploads).
        serializer_class (Serializer): The serializer class for the uploaded data.
        permission_classes (tuple): Permissions required to access this view (IsAuthenticated for authenticated users).

    Methods:
        post(request, *args, **kwargs): Handles the processing of uploaded CSV data.
    """

    # Set the parser for handling file uploads
    parser_classes = (MultiPartParser,)
    serializer_class = csv_master_serializers.ConnectorCSVUploadSerializers
    permission_classes = (IsAuthenticated, IsAdminUser)

    def post(self, request, *args, **kwargs):
        """
        Handles the processing of uploaded CSV data.

        Args:
            request (HttpRequest): The HTTP request containing the uploaded CSV file.
            *args: Variable-length argument list.
            **kwargs: Variable-length keyword argument list.

        Returns:
            Response: The response message indicating whether the connectors were uploaded successfully.
        """

        file = request.FILES.get("file")

        # Check if the file was provided in the request
        if not file:
            return Response(
                {"message": "File not provided"}, status=status.HTTP_400_BAD_REQUEST
            )

        # Check if the file has a .csv extension
        if not file.name.endswith(".csv"):
            return Response(
                {"message": "Invalid file format"}, status=status.HTTP_400_BAD_REQUEST
            )

        # Parse the CSV file and create data for the model
        df = pd.read_csv(file)
        columns = list(df.columns)

        # Required column names for the CSV file
        required_columns = ["type_id", "name", "short_name"]

        # Check if the required columns are present in the CSV file
        if all(col in columns for col in required_columns):
            json_data = [dict(v) for _, v in df.iterrows()]

            # Serialize and save the data
            serializer = csv_master_serializers.ConnectorCSVUploadSerializers(
                data=json_data, many=True
            )

            if serializer.is_valid():
                serializer.save()
                return Response(
                    {"message": "Connectors uploaded successfully"},
                    status=status.HTTP_200_OK,
                )
            else:
                return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
        else:
            return Response(
                {"message": f"File must have {', '.join(required_columns)} columns"},
                status=status.HTTP_400_BAD_REQUEST,
            )


class LocationCSVUploadView(CreateAPIView):
    """
    This is the LocationCSVUploadView class responsible for handling CSV file uploads containing location data.

    It allows users to upload location data from a CSV file, which is then processed and saved to the database.

    Attributes:
        parser_classes (tuple): The parsers used for request data, including MultiPartParser for handling file uploads.
        serializer_class (Serializer): The serializer class for deserializing the uploaded data.
        permission_classes (tuple): Specifies the permissions required to access this view,
        set to IsAuthenticated for authenticated users.

    Methods:
        post(request, *args, **kwargs): Handles the processing of uploaded CSV data, validating,
        and saving it to the database.
    """

    # Set the parser for handling file uploads
    parser_classes = (MultiPartParser,)
    serializer_class = csv_master_serializers.ConnectorCSVUploadSerializers
    permission_classes = (IsAuthenticated, IsAdminUser)

    def post(self, request, *args, **kwargs):
        """
        Handles the processing of uploaded CSV data.

        Args:
            request (HttpRequest): The HTTP request containing the uploaded CSV file.
            *args: Variable-length argument list.
            **kwargs: Variable-length keyword argument list.

        Returns:
            Response: A response message indicating whether the connectors
            were uploaded successfully or any errors encountered.

        This method processes the uploaded CSV file containing location data. It validates the data,
        checks for required columns, and saves the location data to the database.
        """

        file = request.FILES.get("file")

        # Check if the file was provided in the request
        if not file:
            return Response(
                {"message": "File not provided"}, status=status.HTTP_400_BAD_REQUEST
            )

        # Check if the file has a .csv extension
        if not file.name.endswith(".csv"):
            return Response(
                {"message": "Invalid file format"}, status=status.HTTP_400_BAD_REQUEST
            )

        # Parse the CSV file and create data for the model
        df = pd.read_csv(file)
        columns = list(df.columns)

        # Required column names for the CSV file
        required_columns = ["type_id", "name"]

        # Check if the required columns are present in the CSV file
        if all(col in columns for col in required_columns):
            json_data = [dict(v) for _, v in df.iterrows()]

            # Serialize and save the data
            serializer = csv_master_serializers.LocationsCSVUploadSerializers(
                data=json_data, many=True
            )

            if serializer.is_valid():
                serializer.save()
                return Response(
                    {"message": "Locations uploaded successfully"},
                    status=status.HTTP_200_OK,
                )
            else:
                return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
        else:
            return Response(
                {"message": f"File must have {', '.join(required_columns)} columns"},
                status=status.HTTP_400_BAD_REQUEST,
            )


class NetworkOperatorCSVUploadView(CreateAPIView):
    """
    This is the NetworkOperatorCSVUploadView class responsible for handling CSV file uploads containing network operator data.

    It allows users to upload network operator data from a CSV file, which is then processed and saved to the database.

    Attributes:
        parser_classes (tuple): The parsers used for request data, including MultiPartParser for handling file uploads.
        serializer_class (Serializer): The serializer class for deserializing the uploaded data.
        permission_classes (tuple): Specifies the permissions required to access this view,
        set to IsAuthenticated for authenticated users.

    Methods:
        post(request, *args, **kwargs): Handles the processing of uploaded CSV data, validating,
        and saving it to the database.

    Meta:
        permissions (tuple): Permissions required to access this view (IsAuthenticated for authenticated users).
        serializer_class (NetworkOperatorUploadCSVSerializers): The serializer used for input/output data.
        parser_classes (tuple): Parsers used for request data, including MultiPartParser for handling file uploads.
    """

    # Set the parser for handling file uploads
    parser_classes = (MultiPartParser,)
    serializer_class = csv_master_serializers.NetworkOperatorUploadCSVSerializers
    permission_classes = (IsAuthenticated, IsAdminUser)

    def post(self, request, *args, **kwargs):
        """
        Handles the processing of uploaded CSV data.

        Args:
            request (HttpRequest): The HTTP request containing the uploaded CSV file.
            *args: Variable-length argument list.
            **kwargs: Variable-length keyword argument list.

        Returns:
            Response: The response message indicating whether the network operators were uploaded successfully.

        This method processes a CSV file containing network operator data, validates the data, and saves it to the database.
        It checks if the required file format and columns are present in the CSV file and handles the uploading process.
        """

        file = request.FILES.get("file")

        # Check if the file was provided in the request
        if not file:
            return Response(
                {"message": "File not provided"}, status=status.HTTP_400_BAD_REQUEST
            )

        # Check if the file has a .csv extension
        if not file.name.endswith(".csv"):
            return Response(
                {"message": "Invalid file format"}, status=status.HTTP_400_BAD_REQUEST
            )

        # Parse the CSV file and create data for the model
        df = pd.read_csv(file)
        columns = list(df.columns)

        # Required column names for the CSV file
        required_columns = ["type_id", "name"]

        # Check if the required columns are present in the CSV file
        if all(col in columns for col in required_columns):
            json_data = [dict(v) for _, v in df.iterrows()]

            # Serialize and save the data
            serializer = self.get_serializer(data=json_data, many=True)

            if serializer.is_valid():
                serializer.save()
                return Response(
                    {"message": "Network Operator uploaded successfully"},
                    status=status.HTTP_200_OK,
                )
            else:
                return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
        else:
            return Response(
                {"message": f"File must have {', '.join(required_columns)} columns"},
                status=status.HTTP_400_BAD_REQUEST,
            )
