from rest_framework.views import APIView
from rest_framework.response import Response
from rest_framework import status
from drf_yasg.utils import swagger_auto_schema
from drf_yasg import openapi
from django.db.models import Q
from rest_framework.permissions import IsAuthenticated
from django.shortcuts import get_object_or_404
from django.utils.dateparse import parse_date

from user.models import User, Plan
from master.models import FemaleReward, Banner
from user.serializers import UserSerializer, FemalrequestSerializer, PlanSerializer
from master.authentication import IsActiveAdmin
from master.serializers import FemaleRewardSerializer, BannerSerializer

# Helper function to apply search
def apply_search(queryset, search_term, fields):
    q = Q()
    for field in fields:
        q |= Q(**{f"{field}__icontains": search_term})
    return queryset.filter(q)

class UserByGenderView(APIView):
    permission_classes = [IsAuthenticated, IsActiveAdmin]

    @swagger_auto_schema(
        operation_description="Retrieve users based on gender (1 for male, 2 for female), with optional search, date filters, and admin_status=1 only.",
        manual_parameters=[
            openapi.Parameter('gender', openapi.IN_QUERY, description="1 (Male), 2 (Female)", type=openapi.TYPE_INTEGER, required=True),
            openapi.Parameter('search', openapi.IN_QUERY, description="Search by real_name, display_name, email, mobile", type=openapi.TYPE_STRING),
            openapi.Parameter('start_date', openapi.IN_QUERY, description="Start date in YYYY-MM-DD", type=openapi.TYPE_STRING),
            openapi.Parameter('end_date', openapi.IN_QUERY, description="End date in YYYY-MM-DD", type=openapi.TYPE_STRING),
        ],
        responses={200: UserSerializer(many=True)}
    )
    def get(self, request):
        gender = request.query_params.get('gender')

        if not gender:
            return Response({"error": "Gender is required as query param (1 or 2)."}, status=status.HTTP_400_BAD_REQUEST)

        try:
            gender = int(gender)
            if gender not in [1, 2]:
                raise ValueError
        except ValueError:
            return Response({"error": "Gender must be 1 or 2."}, status=status.HTTP_400_BAD_REQUEST)

        users = User.objects.filter(Q(gender=gender) & Q(admin_status__in=[1, 3]))

        start_date = parse_date(request.query_params.get("start_date", ""))
        end_date = parse_date(request.query_params.get("end_date", ""))
        if start_date:
            users = users.filter(created_at__date__gte=start_date)
        if end_date:
            users = users.filter(created_at__date__lte=end_date)

        search = request.query_params.get("search")
        if search:
            users = apply_search(users, search, ['display_name', 'real_name', 'email', 'mobile'])

        serializer = UserSerializer(users, many=True)
        return Response(serializer.data, status=status.HTTP_200_OK)
    


class FemaleUnverifiedUserView(APIView):
    permission_classes = [IsAuthenticated, IsActiveAdmin]

    @swagger_auto_schema(
        operation_description="Get female users (gender=2), filter by admin_status, search, and date.",
        manual_parameters=[
            openapi.Parameter('search', openapi.IN_QUERY, description="Search keyword", type=openapi.TYPE_STRING),
            openapi.Parameter('admin_status', openapi.IN_QUERY, description="Comma-separated admin_status (e.g. 1,2)", type=openapi.TYPE_STRING),
            openapi.Parameter('start_date', openapi.IN_QUERY, description="Start date (YYYY-MM-DD)", type=openapi.TYPE_STRING),
            openapi.Parameter('end_date', openapi.IN_QUERY, description="End date (YYYY-MM-DD)", type=openapi.TYPE_STRING),
        ],
        responses={200: FemalrequestSerializer(many=True)}
    )
    def get(self, request):
        users = User.objects.filter(gender=2)

        # Admin status filter
        admin_status_param = request.query_params.get("admin_status")
        if admin_status_param:
            try:
                admin_status_list = [int(x.strip()) for x in admin_status_param.split(',') if x.strip().isdigit()]
                users = users.filter(admin_status__in=admin_status_list)
            except ValueError:
                return Response({"error": "Invalid admin_status value(s). Must be integers."}, status=400)

        # Date filter
        start_date = parse_date(request.query_params.get("start_date", ""))
        end_date = parse_date(request.query_params.get("end_date", ""))
        if start_date:
            users = users.filter(created_at__date__gte=start_date)
        if end_date:
            users = users.filter(created_at__date__lte=end_date)

        # Search filter
        search = request.query_params.get("search")
        if search:
            users = apply_search(users, search, ['display_name', 'real_name', 'email', 'mobile'])

        serializer = FemalrequestSerializer(users, many=True)
        return Response(serializer.data, status=status.HTTP_200_OK)
    
class UserDeleteView(APIView):
    permission_classes = [IsAuthenticated, IsActiveAdmin]

    @swagger_auto_schema(
        operation_description="Retrieve soft-deleted users based on gender (1 for male, 2 for female), with optional search and date filters.",
        manual_parameters=[
            openapi.Parameter('gender', openapi.IN_QUERY, description="1 (Male), 2 (Female)", type=openapi.TYPE_INTEGER, required=True),
            openapi.Parameter('search', openapi.IN_QUERY, description="Search by real_name, display_name, email, mobile", type=openapi.TYPE_STRING),
            openapi.Parameter('start_date', openapi.IN_QUERY, description="Start date in YYYY-MM-DD", type=openapi.TYPE_STRING),
            openapi.Parameter('end_date', openapi.IN_QUERY, description="End date in YYYY-MM-DD", type=openapi.TYPE_STRING),
        ],
        responses={200: UserSerializer(many=True)}
    )
    def get(self, request):
        gender = request.query_params.get('gender')

        if not gender:
            return Response({"error": "Gender is required as query param (1 or 2)."}, status=status.HTTP_400_BAD_REQUEST)

        try:
            gender = int(gender)
            if gender not in [1, 2]:
                raise ValueError
        except ValueError:
            return Response({"error": "Gender must be 1 or 2."}, status=status.HTTP_400_BAD_REQUEST)

        users = User.objects.filter(
            gender=gender,
            deleted_at__isnull=False
        )

        start_date = parse_date(request.query_params.get("start_date", ""))
        end_date = parse_date(request.query_params.get("end_date", ""))
        if start_date:
            users = users.filter(created_at__date__gte=start_date)
        if end_date:
            users = users.filter(created_at__date__lte=end_date)

        search = request.query_params.get("search")
        if search:
            users = apply_search(users, search, ['display_name', 'real_name', 'email', 'mobile'])

        result = []
        for user in users:
            user_data = UserSerializer(user).data
            user_data['deleted_at'] = user.deleted_at
            user_data['delete_reason'] = user.delete_reason if hasattr(user, 'delete_reason') else None
            result.append(user_data)

        return Response(result, status=status.HTTP_200_OK)

class OfferPlanListView(APIView):
    permission_classes = [IsAuthenticated]

    @swagger_auto_schema(
        operation_description="Retrieve all active offer plans (type=1 and status=true)",
        responses={200: PlanSerializer(many=True)}
    )
    def get(self, request):
        plans = Plan.objects.filter(type=1, status=True)
        serializer = PlanSerializer(plans, many=True)
        return Response({
            "status": "success",
            "message": "Offer plans retrieved successfully",
            "data": serializer.data
        }, status=status.HTTP_200_OK)

class NormalPlanListView(APIView):
    permission_classes = [IsAuthenticated]

    @swagger_auto_schema(
        operation_description="Retrieve all active normal plans (type=2 and status=true)",
        responses={200: PlanSerializer(many=True)}
    )
    def get(self, request):
        plans = Plan.objects.filter(type=2, status=True)
        serializer = PlanSerializer(plans, many=True)
        return Response({
            "status": "success",
            "message": "Normal plans retrieved successfully",
            "data": serializer.data
        }, status=status.HTTP_200_OK)


class FemaleRewardListView(APIView):
    permission_classes = [IsAuthenticated]

    @swagger_auto_schema(
        operation_description="Get all active female rewards (status=true)",
        responses={200: FemaleRewardSerializer(many=True)}
    )
    def get(self, request):
        rewards = FemaleReward.objects.filter(status=True)
        serializer = FemaleRewardSerializer(rewards, many=True)
        return Response({
            "status": "success",
            "message": "Active rewards fetched successfully",
            "data": serializer.data
        }, status=status.HTTP_200_OK)

class UserBannerView(APIView):
    permission_classes = [IsAuthenticated]

    @swagger_auto_schema(
        operation_description="Get all active banners (status = true)",
        responses={200: BannerSerializer(many=True)}
    )
    def get(self, request):
        banners_with_other_types = Banner.objects.filter(
            status=True,
            type__in=[1, 2, 3]
        ).order_by('-created_at')

        if banners_with_other_types.exists():
            banners = banners_with_other_types
        else:
            banners = Banner.objects.filter(status=True, type=0).order_by('-created_at')

        serializer = BannerSerializer(banners, many=True)
        return Response({
            "status": "success",
            "data": serializer.data
        }, status=status.HTTP_200_OK)
