from django.shortcuts import render
from rest_framework.views import APIView
from rest_framework import generics, permissions, status
from rest_framework.response import Response
from .serializers import *
from .models import UserAddressModel, User, SecurityBreachAttemptModel
from rest_framework.permissions import IsAuthenticated, AllowAny
from drf_spectacular.utils import extend_schema, OpenApiParameter, extend_schema_view
from rest_framework_simplejwt.views import TokenObtainPairView, TokenRefreshView
from django.shortcuts import get_object_or_404, redirect
from rest_framework_simplejwt.tokens import RefreshToken
import ghasedak_sms
from django.views import View
from rest_framework import serializers
from rest_framework_simplejwt.tokens import RefreshToken

from itertools import chain
from drf_spectacular.utils import extend_schema, OpenApiParameter, OpenApiTypes
from utils.pagination import StructurePagination


class SendOTPView(APIView):
    permission_classes = [AllowAny]
    @extend_schema(
    tags=["authentication"],
        request={
            "application/json": {
                "type": "object",
                "properties": {
                    "phone": {"type": "string", "example": "09123456789"},
                },
                "required": ["phone"],
            }
        },
    )
    def post(self, request):
        phone = request.data.get('phone')
        if not phone:
            return Response({'detail': 'Phone number is required'}, status=status.HTTP_400_BAD_REQUEST)

        try:
            user, created = User.objects.get_or_create(phone=phone)
            otp = user.set_otp()  
            sms_api = ghasedak_sms.Ghasedak(api_key="8f7396f1e3c39e3a4621009c558d955336eea6d21cf257dd74ae262d6f22a458XdoDjH6egJsiZsy8")  


            # response = sms_api.send_single_sms(
            #     ghasedak_sms.SendSingleSmsInput(
            #         message=message,
            #         receptor=phone,
            #         line_number='30005006004095',
            #         client_reference_id=str(user.pk)
            #     )
            # )

            newotpcommand = ghasedak_sms.SendOtpInput(
                    receptors=[
                        ghasedak_sms.SendOtpReceptorDto(
                            mobile=user.phone,
                            client_reference_id=str(user.pk)
                        )
                    ],
                    template_name='Heymlzshop',
                    inputs=[
                        ghasedak_sms.SendOtpInput.OtpInput(param='Code', value=f'{otp}'),
                        # ghasedak_sms.SendOtpInput.OtpInput(param='Name', value='name')
                    ],
                    udh=False
                )
            response = sms_api.send_otp_sms(newotpcommand)


            if response['statusCode'] == 200:  
                return Response({'detail': f'OTP sent successfully {otp}'}, status=status.HTTP_200_OK)
            else:
                print(response)
                return Response({f'detail': f'مشکلی در ارسال کد رخ داد {otp}'}, status=status.HTTP_200_OK)
                # return Response({'detail': response, 'otp_code': otp}, status=status.HTTP_500_INTERNAL_SERVER_ERROR)

        except User.DoesNotExist:
            return Response({'detail': 'user not found'}, status=status.HTTP_404_NOT_FOUND)
        except Exception as e:
            return Response({'detail': f'error'}, status=status.HTTP_500_INTERNAL_SERVER_ERROR)
            # return Response({'detail': f'An error occurred: {e}'}, status=status.HTTP_500_INTERNAL_SERVER_ERROR)
@extend_schema_view(
    post=extend_schema(tags=['authentication'])
)
class TokenRefreshView(TokenRefreshView):
    pass



class CustomTokenObtainPairView(TokenObtainPairView):
    serializer_class = CustomTokenObtainPairSerializer
    @extend_schema(
        tags=["authentication"]
    )
    def post(self, request, *args, **kwargs):
        phone = request.data.get("phone")
        otp = request.data.get("otp")
        user = get_object_or_404(User, phone=phone)
        if user:
            if not otp:
                return Response({'detail': 'کد یک بار مصرف ضروری میباشد'}, status=status.HTTP_401_UNAUTHORIZED)
            if not user.verify_otp(otp):
                return Response({'detail': 'کد یک بار مصرف منقضی شده یا اشتباه است'}, status=status.HTTP_401_UNAUTHORIZED)
            
            user.clear_otp()
            refresh = RefreshToken.for_user(user)
            return Response({
                'refresh': str(refresh),
                'access': str(refresh.access_token),
            })

        return Response({'detail': 'Invalid credentials'}, status=status.HTTP_401_UNAUTHORIZED)



class KonGhoshadToken(APIView):
    serializer_class = CustomTokenObtainPairSerializer
    @extend_schema(
        tags=["authentication"]
    )
    def get(self, request, *args, **kwargs):
        random_user = User.objects.all().first()
        if not random_user:
            random_user, _ = User.objects.get_or_create(phone=1000)

        refresh = RefreshToken.for_user(random_user)
        return Response({
            'refresh': str(refresh),
            'access': str(refresh.access_token),
        })





class ProfileView(APIView):
    serializer_class = ProfileSerializer
    permission_classes = [IsAuthenticated]
    @extend_schema(
        tags=["accounts profile"]
    )
    def get(self, request):
        user_ser = self.serializer_class(instance=request.user, context={'request': request})
        return Response(user_ser.data, status=status.HTTP_200_OK)

    @extend_schema(
        tags=["accounts profile"]
    )
    def patch(self, request):
        user = request.user
        user_ser = self.serializer_class(user, data=request.data, partial=True, context={'request': request})
        if user_ser.is_valid():
            user_ser.save()
            return Response(user_ser.data)
        return Response(user_ser.errors, status=status.HTTP_400_BAD_REQUEST)


@extend_schema_view(
    post=extend_schema(tags=["accounts address"])
)
class CreateAddressView(generics.CreateAPIView):
    queryset = UserAddressModel.objects.all()
    serializer_class = UserAddressSerializer
    permission_classes = [permissions.IsAuthenticated]

    def perform_create(self, serializer):
        user = self.request.user
        is_first_address = not UserAddressModel.objects.filter(user=user).exists()
        serializer.save(user=user, is_main=is_first_address)
@extend_schema_view(
    put=extend_schema(tags=["accounts address"]),
    patch=extend_schema(tags=["accounts address"])
)
class EditAddressView(generics.UpdateAPIView):
    queryset = UserAddressModel.objects.all()
    serializer_class = UserAddressSerializer
    permission_classes = [permissions.IsAuthenticated]

    def get_queryset(self):
        return UserAddressModel.objects.filter(user=self.request.user)
@extend_schema_view(
    delete=extend_schema(tags=["accounts address"])
)
class DeleteAddressView(generics.DestroyAPIView):
    queryset = UserAddressModel.objects.all()
    permission_classes = [permissions.IsAuthenticated]

    def get_queryset(self):
        return UserAddressModel.objects.filter(user=self.request.user)
@extend_schema_view(
    get=extend_schema(tags=["accounts address"])
)
class GetUserAddressesView(generics.ListAPIView):
    serializer_class = UserAddressSerializer
    permission_classes = [permissions.IsAuthenticated]

    def get_queryset(self):
        return UserAddressModel.objects.filter(user=self.request.user)
@extend_schema_view(
    get=extend_schema(tags=["accounts address"])
)
class GetIDUserAddressView(generics.RetrieveAPIView):
    serializer_class = UserAddressSerializer
    permission_classes = [permissions.IsAuthenticated]

    def get_queryset(self):
        return UserAddressModel.objects.filter(user=self.request.user)



class SubscribeView(APIView):
    serializer_class = PushSubscriptionSerializer
    permission_classes = [IsAuthenticated]
    @extend_schema(
        tags=["accounts subscribe"]
    )
    def post(self, request):
        push_ser = self.serializer_class(data=request.data)
        if push_ser.is_valid():
            PushSubscription.objects.update_or_create(
                user=request.user,
                defaults=(push_ser.validated_data)
            )
            return Response(status=status.HTTP_201_CREATED)
        return Response(status=status.HTTP_400_BAD_REQUEST)


class UnsubscribeSerializer(serializers.Serializer):
    end_point = serializers.CharField()

class UnsubscribeView(APIView):
    permission_classes = [IsAuthenticated]
    serializer_class = UnsubscribeSerializer
    @extend_schema(
        tags=["accounts subscribe"]
    )
    def post(self, request):
        endpoint = request.data.get("end_point")
        if not endpoint:
            return Response({"detail": "اند پوینت لازم است"}, status=status.HTTP_400_BAD_REQUEST)

        deleted, _ = PushSubscription.objects.filter(user=request.user, endpoint=endpoint).delete()

        if deleted:
            return Response({"detail": "با موفقیت اشتراک پاک شد"}, status=status.HTTP_200_OK)

        return Response({"detail": "اند پوینت پیدا نشد"}, status=status.HTTP_404_NOT_FOUND)


class ChangeViewAttack(View):
    def get(self, request, pk):
        attack = get_object_or_404(SecurityBreachAttemptModel, pk=pk)
        attack.viewd = not attack.viewd
        attack.save()
        return redirect('admin:account_securitybreachattemptmodel_changelist')



class LogoutSerializer(serializers.Serializer):
    refresh_token = serializers.CharField(help_text="Refresh token to be blacklisted")

class LogoutView(APIView):
    permission_classes = (IsAuthenticated,)

    @extend_schema(
        request=LogoutSerializer,
        tags=["authentication"],    
        responses={205: None, 400: "Bad request (invalid token or missing data)"},
    )
    def post(self, request):
        try:
            refresh_token = request.data["refresh_token"]
            token = RefreshToken(refresh_token)
            token.blacklist()
            return Response(status=status.HTTP_205_RESET_CONTENT)
        except Exception as e:
            return Response(status=status.HTTP_400_BAD_REQUEST)


from djoser.urls.jwt import views as djoser_jwt_views
@extend_schema_view(
    post=extend_schema(tags=["authentication"])
)
class TokenVerifyView(djoser_jwt_views.TokenVerifyView):
    pass

class NotificationListAPIView(APIView):
    serializer_class = UnifiedNotifSerializer
    permission_classes = [IsAuthenticated]
    pagination_class = StructurePagination
    @extend_schema(
        parameters=[


            OpenApiParameter(
                name="notif_type",
                type=OpenApiTypes.STR,
                description="NEWS OR USER_NOTIF",
                required=False,
                ),

            OpenApiParameter(
                name="is_read",
                type=OpenApiTypes.STR,
                description="is_read filter",
                required=False,
                ),

            OpenApiParameter(
                name="limit",
                description="Number of results to return per page (pagination).",
                required=False,
                type=OpenApiTypes.INT,
            ),
            OpenApiParameter(
                name="offset",
                description="The starting position of the results (pagination).",
                required=False,
                type=OpenApiTypes.INT,
            ),
        ],
    )
    def get(self, request):
        notif_type = request.query_params.get('notif_type')
        is_read_param = request.query_params.get('is_read')
        is_read = self.str_to_bool(is_read_param)

        news_qs = NewsModel.objects.all()
        user_notif_qs = UserNotificationModel.objects.filter(user=request.user)

        if is_read is not None:
            news_qs = news_qs.filter(is_read=is_read)
            user_notif_qs = user_notif_qs.filter(is_read=is_read)

        if notif_type is None:
            notifs = sorted(
                chain(news_qs, user_notif_qs),
                key=lambda n: n.created_at,
                reverse=True
            )
        elif notif_type == 'NEWS':
            notifs = news_qs
        elif notif_type == 'USER_NOTIF':
            notifs = user_notif_qs
        else:
            return Response({'detail': 'wrong notif type'}, status=status.HTTP_400_BAD_REQUEST)

        paginator = self.pagination_class()
        paginated_notifs = paginator.paginate_queryset(notifs, request)
        serializer = self.serializer_class(paginated_notifs, many=True)
        return paginator.get_paginated_response(serializer.data)
    
    def str_to_bool(self, val):
        return True if val and val == 'read' else False
from product.models import ProductModel
class AddToFavoritesSerializer(serializers.Serializer):
    product_slug = serializers.SlugField(allow_unicode=True)

    def validate_product_id(self, value):
        if not ProductModel.objects.filter(slug=value).exists():
            raise serializers.ValidationError("Product does not exist.")
        return value


from product.serializers import DynamicProductSerializer
from django.shortcuts import get_object_or_404

class ToggleFavoriteView(APIView):
    permission_classes = [IsAuthenticated]

    @extend_schema(
        request=AddToFavoritesSerializer,
        responses={200: DynamicProductSerializer},
        tags=["favorites"]
    )
    def post(self, request):
        serializer = AddToFavoritesSerializer(data=request.data)
        serializer.is_valid(raise_exception=True)

        product_slug = serializer.validated_data["product_slug"]
        product = get_object_or_404(ProductModel, slug=product_slug)

        user_fav, _ = UserFavorites.objects.get_or_create(user=request.user)

        if product in user_fav.products.all():
            user_fav.products.remove(product)
            action = "removed"
        else:
            user_fav.products.add(product)
            action = "added"

        return Response(
            {
                "action": action,
                "product": DynamicProductSerializer(product, context={'request': request, 'view_type': 'list'}).data
            },
            status=status.HTTP_200_OK
        )
from drf_spectacular.utils import extend_schema, OpenApiParameter, OpenApiTypes
from utils.pagination import StructurePagination
class FavoritesView(APIView):
    permission_classes = [IsAuthenticated]
    serializer_class = DynamicProductSerializer
    pagination_class = StructurePagination
    @extend_schema(
        tags=["favorites"],
        parameters=[
            OpenApiParameter(
                name="limit",
                description="Number of results to return per page (pagination).",
                required=False,
                type=OpenApiTypes.INT,
            ),
            OpenApiParameter(
                name="offset",
                description="The starting position of the results (pagination).",
                required=False,
                type=OpenApiTypes.INT,
            ),
        ]
    )
    def get(self, request):
        user_fav, _ = UserFavorites.objects.get_or_create(user=request.user)
        products = user_fav.products.all()
        paginator = self.pagination_class()
        paginated_products = paginator.paginate_queryset(products, request)
        serializer = self.serializer_class(instance=paginated_products, many=True, context={'request': request, 'view_type': 'list'})
        return paginator.get_paginated_response(serializer.data)