import json
from datetime import timedelta
from decimal import Decimal

from django.shortcuts import get_object_or_404
from django.utils.timezone import now
from django.contrib.auth.tokens import default_token_generator
from django.contrib.auth import get_user_model
from django.core.mail import send_mail

from rest_framework.permissions import AllowAny, IsAuthenticated
from rest_framework.views import APIView
from rest_framework.response import Response
from rest_framework import generics
from rest_framework.parsers import MultiPartParser, FormParser
from rest_framework.authentication import BaseAuthentication

from rest_framework_simplejwt.tokens import RefreshToken
from rest_framework_simplejwt.views import TokenObtainPairView
from rest_framework_simplejwt.serializers import TokenObtainPairSerializer

from asgiref.sync import async_to_sync
from channels.layers import get_channel_layer

from .models import *
from .serializers import *

User = get_user_model()

# =====================================================
# JWT LOGIN
# =====================================================
class CustomTokenObtainPairSerializer(TokenObtainPairSerializer):
    @classmethod
    def get_token(cls, user):
        token = super().get_token(user)
        token["username"] = user.username
        token["role"] = getattr(user, "role", None)
        return token


class CustomTokenObtainPairView(TokenObtainPairView):
    permission_classes = [AllowAny]
    serializer_class = CustomTokenObtainPairSerializer


# =====================================================
# NO AUTH CLASS (FOR PUBLIC CART)
# =====================================================
class NoAuth(BaseAuthentication):
    def authenticate(self, request):
        return None


# =====================================================
# ROLE CHECK
# =====================================================
def is_admin_or_superadmin(user):
    return getattr(user, "role", None) in ["admin", "superadmin", "sales"] or user.is_superuser


# =====================================================
# USER CREATION
# =====================================================
class CreateSalesUserAPIView(APIView):
    permission_classes = [IsAuthenticated]

    def post(self, request):
        if not is_admin_or_superadmin(request.user):
            return Response({"detail": "Admin required"}, status=403)

        username = request.data.get("username")
        password = request.data.get("password")

        if not username or not password:
            return Response({"detail": "Username and password required"}, status=400)

        if User.objects.filter(username=username).exists():
            return Response({"detail": "User already exists"}, status=400)

        user = User.objects.create_user(username=username, password=password, role="sales")
        refresh = RefreshToken.for_user(user)

        return Response({
            "id": user.id,
            "username": user.username,
            "role": user.role,
            "refresh": str(refresh),
            "access": str(refresh.access_token),
        }, status=201)


class CreateAdminUserAPIView(APIView):
    permission_classes = [IsAuthenticated]

    def post(self, request):
        if not is_admin_or_superadmin(request.user):
            return Response({"detail": "Not allowed"}, status=403)

        username = request.data.get("username")
        password = request.data.get("password")

        if not username or not password:
            return Response({"detail": "Username and password required"}, status=400)

        if User.objects.filter(username=username).exists():
            return Response({"detail": "User already exists"}, status=400)

        user = User.objects.create_user(username=username, password=password, role="admin")
        refresh = RefreshToken.for_user(user)

        return Response({
            "id": user.id,
            "username": user.username,
            "role": user.role,
            "refresh": str(refresh),
            "access": str(refresh.access_token),
        }, status=201)


# =====================================================
# PRODUCTS
# =====================================================
class ProductCreateAPIView(APIView):
    permission_classes = [IsAuthenticated]
    parser_classes = [MultiPartParser, FormParser]

    def post(self, request):
        if not is_admin_or_superadmin(request.user):
            return Response({"detail": "Not authorized"}, status=403)

        serializer = ProductSerializer(data=request.data, context={"request": request})
        if serializer.is_valid():
            product = serializer.save()
            return Response(ProductSerializer(product, context={"request": request}).data, status=201)

        return Response(serializer.errors, status=400)


class ProductListAPIView(generics.ListAPIView):
    serializer_class = ProductSerializer
    pagination_class = StandardPagination
    permission_classes = [AllowAny]

    def get_queryset(self):
        user = self.request.user
        if getattr(user, "role", None) in ["admin", "superadmin"] or user.is_superuser:
            return Product.objects.all().order_by("-created_at")
        return Product.objects.filter(is_active=True).order_by("-created_at")


class ProductToggleActiveAPIView(APIView):
    permission_classes = [IsAuthenticated]

    def patch(self, request, pk):
        if not is_admin_or_superadmin(request.user):
            return Response({"detail": "Not allowed"}, status=403)

        product = get_object_or_404(Product, pk=pk)
        product.is_active = not product.is_active
        product.save()
        return Response({"id": product.id, "is_active": product.is_active})


# =====================================================
# CART
# =====================================================
class CartCreateAPIView(APIView):
    permission_classes = [IsAuthenticated]

    def post(self, request):
        cart, created = Cart.objects.get_or_create(user=request.user)
        return Response({"cart_id": cart.id}, status=201)


class CartItemAddAPIView(APIView):
    permission_classes = [IsAuthenticated]

    def post(self, request):
        cart_id = request.data.get("cart_id")
        product_id = request.data.get("product_id")
        quantity = int(request.data.get("quantity", 1))
        color = request.data.get("color", "")
        size = request.data.get("size", "")

        cart = get_object_or_404(Cart, id=cart_id)
        if cart.user and cart.user != request.user:
            return Response({"detail": "Not your cart"}, status=403)

        product = get_object_or_404(Product, id=product_id)

        CartItem.objects.create(
            cart=cart,
            product=product,
            quantity=quantity,
            color=color,
            size=size
        )

        return Response({"success": True}, status=201)


from rest_framework.permissions import IsAuthenticated
from rest_framework.response import Response
from rest_framework.views import APIView

class CartDetailAPIView(APIView):
    permission_classes = [IsAuthenticated]

    def get(self, request, cart_id=None):

        # ✅ If cart_id provided
        if cart_id:
            cart = get_object_or_404(
                Cart,
                id=cart_id,
                user=request.user
            )
        else:
            # ✅ Always create cart if not exists
            cart, created = Cart.objects.get_or_create(
                user=request.user
            )

        serializer = CartSerializer(cart)
        return Response(serializer.data)


class CartItemRemoveAPIView(APIView):
    permission_classes = [IsAuthenticated]

    def post(self, request):
        item_id = request.data.get("item_id")
        if not item_id:
            return Response({"error": "item_id is required"}, status=400)

        try:
            item = CartItem.objects.get(id=item_id)
            if item.cart.user and item.cart.user != request.user:
                return Response({"error": "Not your cart"}, status=403)
            item.delete()
            return Response({"success": True}, status=200)
        except CartItem.DoesNotExist:
            return Response({"error": "Item not found"}, status=404)


# =====================================================
# ORDERS
# =====================================================
class OrderCreateAPIView(APIView):
    permission_classes = [IsAuthenticated]
    parser_classes = [MultiPartParser, FormParser]

    def post(self, request):
        cart = get_object_or_404(Cart, id=request.data.get("cart_id"))

        if cart.user and cart.user != request.user:
            return Response({"detail": "Not your cart"}, status=403)

        payment_screenshot = request.FILES.get("payment_screenshot")
        if not payment_screenshot:
            return Response({"detail": "Payment screenshot required"}, status=400)

        order = Order.objects.create(
            user=request.user,
            payment_screenshot=payment_screenshot
        )

        for item in cart.items.all():
            OrderItem.objects.create(
                order=order,
                product=item.product,
                quantity=item.quantity,
                size=item.size,
                color=item.color
            )

        Notification.objects.create(message=f"New order #{order.id}")

        channel_layer = get_channel_layer()
        async_to_sync(channel_layer.group_send)(
            "orders",
            {"type": "order_created", "data": OrderSerializer(order).data}
        )
 
        return Response( OrderSerializer(order, context={"request": request}).data, status=201)


class OrderStatusUpdateAPIView(APIView):
    permission_classes = [IsAuthenticated]

    def patch(self, request, order_id):

        if not is_admin_or_superadmin(request.user):
            return Response({"detail": "Not allowed"}, status=403)

        order = get_object_or_404(Order, id=order_id)

        new_status = request.data.get("status")
        paid_amount = request.data.get("paid_amount")

        if new_status not in ["approved", "rejected", "delivered"]:
            return Response({"detail": "Invalid status"}, status=400)


        # ✅ RESTORE STOCK IF REJECTED
        if new_status == "rejected":

            for item in order.items.all():

                product = item.product

                product.quantity += item.quantity

                product.save(update_fields=["quantity"])


            order.status = "rejected"


        elif new_status == "approved":

            if paid_amount is None:
                return Response(
                    {"detail": "paid_amount required"},
                    status=400
                )

            order.paid_amount = Decimal(paid_amount)

            order.remaining_birr = (
                order.total_price - order.paid_amount
            )

            order.status = "approved"


        elif new_status == "delivered":

            order.status = "delivered"


        order.save()

        return Response({
            "success": True,
            "status": order.status
        })



# =====================================================
# ORDER LISTS (ADMIN ONLY)
# =====================================================
class BaseOrderListAPIView(generics.ListAPIView):
    permission_classes = [IsAuthenticated]
    serializer_class = OrderSerializer
    pagination_class = StandardPagination

    def get_queryset(self):
        if not is_admin_or_superadmin(self.request.user):
            return Order.objects.none()
        return Order.objects.all().order_by("-created_at")


class PendingOrdersAPIView(BaseOrderListAPIView):
    def get_queryset(self):
        return super().get_queryset().filter(status="pending")


class ApprovedOrdersAPIView(BaseOrderListAPIView):
    def get_queryset(self):
        return super().get_queryset().filter(status="approved")


class RejectedOrdersAPIView(BaseOrderListAPIView):
    def get_queryset(self):
        return super().get_queryset().filter(status="rejected")


class DeliveredOrdersAPIView(BaseOrderListAPIView):
    def get_queryset(self):
        return super().get_queryset().filter(status="delivered")


# =====================================================
# REPORTS
# =====================================================
class DailyReportAPIView(APIView):
    permission_classes = [IsAuthenticated]

    def get(self, request):
        if not is_admin_or_superadmin(request.user):
            return Response(status=403)

        today = now().date()
        qs = Order.objects.filter(status="delivered", created_at__date=today)
        return Response({"count": qs.count()})


class WeeklyReportAPIView(APIView):
    permission_classes = [IsAuthenticated]

    def get(self, request):
        if not is_admin_or_superadmin(request.user):
            return Response(status=403)

        qs = Order.objects.filter(
            status="delivered",
            created_at__gte=now() - timedelta(days=7)
        )
        return Response({"count": qs.count()})


class MonthlyReportAPIView(APIView):
    permission_classes = [IsAuthenticated]

    def get(self, request):
        if not is_admin_or_superadmin(request.user):
            return Response(status=403)

        today = now()
        qs = Order.objects.filter(
            status="delivered",
            created_at__year=today.year,
            created_at__month=today.month
        )
        return Response({"count": qs.count()})


# =====================================================
# NOTIFICATIONS
# =====================================================
class NotificationListAPIView(generics.ListAPIView):
    permission_classes = [IsAuthenticated]
    serializer_class = NotificationSerializer
    pagination_class = StandardPagination
    queryset = Notification.objects.all().order_by("-created_at")

    def get_queryset(self):
        if not is_admin_or_superadmin(self.request.user):
            return Notification.objects.none()
        return super().get_queryset()


# =====================================================
# CUSTOMER REGISTER
# =====================================================
class CustomerRegisterAPIView(APIView):
    permission_classes = [AllowAny]

    def post(self, request):
        username = request.data.get("username")
        password = request.data.get("password")
        phone = request.data.get("phone")

        if not username or not password:
            return Response({"detail": "Username and password required"}, status=400)

        if User.objects.filter(username=username).exists():
            return Response({"detail": "Username already exists"}, status=400)

        user = User.objects.create_user(
            username=username,
            password=password,
            phone=phone,
            role="customer"
        )

        refresh = RefreshToken.for_user(user)

        return Response({
            "id": user.id,
            "username": user.username,
            "role": user.role,
            "refresh": str(refresh),
            "access": str(refresh.access_token),
        }, status=201)


# =====================================================
# PASSWORD MANAGEMENT
# =====================================================
class ForgotPasswordAPIView(APIView):
    permission_classes = [AllowAny]

    def post(self, request):
        email = request.data.get("email")
        if not email:
            return Response({"error": "Email required"}, status=400)
        try:
            user = User.objects.get(email=email)
            token = default_token_generator.make_token(user)
            send_mail(
                subject="Reset your password",
                message=f"Use this token to reset your password: {token}",
                from_email="noreply@example.com",
                recipient_list=[email],
            )
            return Response({"detail": "Check your email for reset token"}, status=200)
        except User.DoesNotExist:
            return Response({"error": "User not found"}, status=404)


class ResetPasswordAPIView(APIView):
    permission_classes = [AllowAny]

    def post(self, request):
        uid = request.data.get("uid")
        token = request.data.get("token")
        new_password = request.data.get("new_password")

        if not uid or not token or not new_password:
            return Response({"error": "All fields required"}, status=400)

        try:
            user = User.objects.get(id=uid)
            if default_token_generator.check_token(user, token):
                user.set_password(new_password)
                user.save()
                return Response({"detail": "Password reset successful"}, status=200)
            return Response({"error": "Invalid token"}, status=400)
        except User.DoesNotExist:
            return Response({"error": "User not found"}, status=404)


class ChangePasswordView(APIView):
    permission_classes = [IsAuthenticated]

    def post(self, request):
        old_password = request.data.get("old_password")
        new_password = request.data.get("new_password")

        if not old_password or not new_password:
            return Response({"error": "Both old and new password required"}, status=400)

        user = request.user
        if not user.check_password(old_password):
            return Response({"error": "Old password incorrect"}, status=400)

        user.set_password(new_password)
        user.save()
        return Response({"detail": "Password changed successfully"}, status=200)

# look this is the api for showing there order for users ok 
class MyOrdersAPIView(generics.ListAPIView):
    permission_classes = [IsAuthenticated]
    serializer_class = OrderSerializer
    pagination_class = StandardPagination

    def get_queryset(self):
        # Only return orders belonging to the logged-in customer
        return Order.objects.filter(user=self.request.user).order_by("-created_at")
from decimal import Decimal
from django.shortcuts import get_object_or_404
from rest_framework.permissions import IsAuthenticated
from rest_framework.views import APIView
from rest_framework.response import Response
from rest_framework import generics

from .models import Product, DiscountRule
from .serializers import DiscountRuleSerializer, StandardPagination
from .views import is_admin_or_superadmin  # reuse your role check

# =====================================================
# DISCOUNT RULES (ADMIN ONLY)
# =====================================================

class DiscountRuleCreateAPIView(APIView):
    permission_classes = [IsAuthenticated]

    def post(self, request):
        if not is_admin_or_superadmin(request.user):
            return Response({"detail": "Not allowed"}, status=403)

        product_id = request.data.get("product_id")
        min_quantity = request.data.get("min_quantity")
        discount_amount = request.data.get("discount_amount")

        if not product_id or not min_quantity or not discount_amount:
            return Response({"detail": "All fields required"}, status=400)

        product = get_object_or_404(Product, id=product_id)

        rule = DiscountRule.objects.create(
            product=product,
            min_quantity=min_quantity,
            discount_amount=Decimal(discount_amount)
        )

        return Response(DiscountRuleSerializer(rule).data, status=201)







class DiscountRuleUpdateAPIView(APIView):
    permission_classes = [IsAuthenticated]

    def patch(self, request, rule_id):
        if not is_admin_or_superadmin(request.user):
            return Response({"detail": "Not allowed"}, status=403)

        rule = get_object_or_404(DiscountRule, id=rule_id)

        min_quantity = request.data.get("min_quantity", rule.min_quantity)
        discount_amount = request.data.get("discount_amount", rule.discount_amount)

        rule.min_quantity = min_quantity
        rule.discount_amount = Decimal(discount_amount)
        rule.save()

        return Response(DiscountRuleSerializer(rule).data, status=200)


class DiscountRuleDeleteAPIView(APIView):
    permission_classes = [IsAuthenticated]

    def delete(self, request, rule_id):
        if not is_admin_or_superadmin(request.user):
            return Response({"detail": "Not allowed"}, status=403)

        rule = get_object_or_404(DiscountRule, id=rule_id)
        rule.delete()
        return Response({"detail": "Discount rule deleted"}, status=204)


class DiscountRuleListAPIView(generics.ListAPIView):
    permission_classes = [IsAuthenticated]
    serializer_class = DiscountRuleSerializer
    pagination_class = StandardPagination

    def get_queryset(self):
        if not is_admin_or_superadmin(self.request.user):
            return DiscountRule.objects.none()
        return DiscountRule.objects.all().order_by("-id")



class CartItemUpdateAPIView(APIView):
    permission_classes = [IsAuthenticated]

    def post(self, request):
        item_id = request.data.get("item_id")
        quantity = int(request.data.get("quantity", 1))

        if quantity < 1:
            return Response({"error": "Quantity must be at least 1"}, status=400)

        try:
            item = CartItem.objects.get(id=item_id)

            if item.cart.user != request.user:
                return Response({"error": "Not allowed"}, status=403)

            if quantity > item.product.quantity:
                return Response({"error": "Not enough stock"}, status=400)

            item.quantity = quantity
            item.save()

            return Response({"success": True})

        except CartItem.DoesNotExist:
            return Response({"error": "Item not found"}, status=404)


            # ================= CURRENT USER =================
class CurrentUserAPIView(APIView):
    permission_classes = [IsAuthenticated]

    def get(self, request):
        user = request.user

        return Response({
            "id": user.id,
            "username": user.username,
            "phone": user.phone,
            "role": user.role,
        })

    class MyCartAPIView(APIView):
       permission_classes = [IsAuthenticated]

    def get(self, request):
        cart, created = Cart.objects.get_or_create(
            user=request.user
        )

        serializer = CartSerializer(cart)

        return Response(serializer.data)


from rest_framework.decorators import action
from rest_framework.response import Response
from rest_framework import status, viewsets
from .models import Product
from .serializers import ProductSerializer

class ProductViewSet(viewsets.ModelViewSet):
    queryset = Product.objects.all()
    serializer_class = ProductSerializer

    @action(detail=True, methods=['patch'], url_path='update-quantity')
    def update_quantity(self, request, pk=None):
        product = self.get_object()
        quantity = request.data.get('quantity')
        # Validate 'quantity' is provided AND is a number
        if quantity is None:
            return Response({'error': 'No quantity provided'}, status=status.HTTP_400_BAD_REQUEST)
        try:
            quantity = int(quantity)
            if quantity < 0:
                return Response({'error': 'Quantity must be >= 0'}, status=status.HTTP_400_BAD_REQUEST)
        except ValueError:
            return Response({'error': 'Quantity must be an integer'}, status=status.HTTP_400_BAD_REQUEST)

        product.quantity = quantity
        product.save()
        return Response({'status': 'quantity updated', 'quantity': product.quantity}, status=status.HTTP_200_OK)