from django.shortcuts import render, get_object_or_404
from rest_framework import generics, permissions
from rest_framework.permissions import IsAuthenticated
from rest_framework.response import Response
from rest_framework import status
from order.models import *
from product.models import *
from ..serializers import *
from ..models import *
from django.db import transaction
from suscription.custom_pagination import CustomPagination
from Help_Support.decorators import cache_response
from rest_framework.exceptions import ValidationError
from rest_framework.decorators import action
from django.db.models import Q, Sum
from login_signup.custom_permissions import IsCustomAdmin
from rest_framework.generics import UpdateAPIView
import requests 
import logging
from vendor_listing.tasks import send_payout_status_email
from datetime import datetime, timedelta, time
from login_signup.custom_permissions import IsCustomAdmin
from rest_framework.views import APIView
from notification.tasks import notify_vendor_payout_status


logger = logging.getLogger(__name__)

class PayoutListViewSet(generics.ListAPIView):
    permission_classes = [IsAuthenticated, IsCustomAdmin]
    serializer_class = AdminPayoutRequestSerializer
    pagination_class = CustomPagination

    def get_queryset(self):
        status = self.request.query_params.get('status')

        if status == 'history':
            queryset = PayoutRequest.objects.exclude(payment_status='pending', status='pending').order_by('-updated_at')

            start_date = self.request.query_params.get('start_date')
            end_date = self.request.query_params.get('end_date')

            if start_date and end_date:
                start_date_obj = datetime.strptime(start_date, "%Y-%m-%d")
                end_date_obj = datetime.combine(datetime.strptime(end_date, "%Y-%m-%d"), time.max)  
                queryset = queryset.filter(
                    Q(requested_date__range=[start_date_obj, end_date_obj]) |
                    Q(approval_date__range=[start_date_obj, end_date_obj])
                )
            elif start_date:
                start_date_obj = datetime.strptime(start_date, "%Y-%m-%d")
                queryset = queryset.filter(
                    Q(requested_date__gte=start_date_obj) |
                    Q(approval_date__gte=start_date_obj)
                )
            elif end_date:
                end_date_obj = datetime.combine(datetime.strptime(end_date, "%Y-%m-%d"), time.max)
                queryset = queryset.filter(
                    Q(requested_date__lte=end_date_obj) |
                    Q(approval_date__lte=end_date_obj)
                )

            search_query = self.request.query_params.get('search')
            if search_query:
                queryset = queryset.filter(
                    Q(transaction_id__icontains=search_query) |
                    Q(vendor__full_name__icontains=search_query)
                )

            return queryset
            # return PayoutRequest.objects.filter(payment_status='successful', status='approved').order_by('-approval_date')
            # return PayoutRequest.objects.filter(payment_status='paid', status='approved').order_by('-approval_date')
        
        else :
            return PayoutRequest.objects.filter(payment_status='pending', status='pending').order_by('requested_date')
        
    def get_serializer_class(self):
        status = self.request.query_params.get('status')
        if status is not None and status == 'history':
            return AdminPayoutHistorySerializer
        return self.serializer_class


    def list(self, request, *args, **kwargs):
        queryset = self.get_queryset()

       
        page = self.paginate_queryset(queryset)  
        if page is not None:
            serializer = self.get_serializer(page, many=True, context={'request': request})
            paginated_response = self.get_paginated_response(serializer.data)  
            
            return Response({
                "status": True,
                "message": "Payout request fetched successfully",
                "data": paginated_response.data 
            })

        serializer = self.get_serializer(queryset, many=True, context={'request': request})
        return Response({
            "status": True,
            "message": "Payout request fetched successfully",
            "data": serializer.data
        })
    

class PayoutStatusUpdateViewSet(UpdateAPIView) :
    serializer_class = PayoutStatusUpdateSerializer
    permission_classes = [IsAuthenticated, IsCustomAdmin]

    def partial_update(self, request, *args, **kwargs):
        try:
            payout_id = kwargs.get("pk")
            
            payout_req = PayoutRequest.objects.get(id=payout_id)

            if not payout_req:
                return Response({"status":False,"message": "Payout request not found"}, status=status.HTTP_400_BAD_REQUEST)
            
            if payout_req.status != 'pending' :
                return Response({"status":False,"message": "Payout request already modified"}, status=status.HTTP_400_BAD_REQUEST)

            payout_status = request.data.get("status")
            amount = request.data.get("amount")
            transaction_id = request.data.get("transaction_id")

            if not payout_status :
                return Response({"status":False,"message": "status is not null"}, status=status.HTTP_400_BAD_REQUEST)

            if payout_status == 'approved':
                if not amount :
                    return Response({"status":False,"message": "Amount is not null"}, status=status.HTTP_400_BAD_REQUEST)

                bank_detail = VendorBankDetail.objects.get(vendor=payout_req.vendor)

                if not bank_detail :
                    return Response({"status":False,"message": "Bank details not found"}, status=status.HTTP_400_BAD_REQUEST)
                
               
                # php_api_url = "http://13.247.37.178/payout_api.php"  # Change as needed
                # payload = {
                #     "id": 2,
                #     "key": "662da0da729461b15225db6d188b694f54ef70bff683fc5c7897eef74e35df5e"
                # }
                # try:
                #     response = requests.post(php_api_url, json=payload)
                #     try:
                #         data = response.json()
                #     except ValueError as e:
                #     if response.status_code == 200:
                #         data = response.json()
                #         return Response({"status": True, "php_data": data})
                #     else:
                #         return Response({"status": False, "message": "PHP API error", "response": response.text}, status=response.status_code)
                # except Exception as e:
                #     return Response({"status": False, "message": "Request failed", "error": str(e)}, status=status. HTTP_500_INTERNAL_SERVER_ERROR)            

                reference = f"txpayout_{payout_req.id}"

                if payout_req.failed_count is not None :
                    reference = f"txpayout_{payout_req.id}_{payout_req.failed_count}"

                payout_request = payout_req.payment_method

                logger.info(f"Payout Method using payout data: {payout_request}")


                if not payout_request :
                    payout_request = bank_detail.payout_method
                    logger.info(f"Payout Method using bank data: {payout_request}")

                                
                if payout_request == VendorBankDetail.PayoutMethod.BANK_ACCOUNT:
                    account_bank = bank_detail.bank_code
                    account_number = bank_detail.bank_account_number
                elif payout_request == VendorBankDetail.PayoutMethod.MOBILE_MONEY:
                    # account_bank =  "TZN"
                    account_bank = bank_detail.mobile_account_bank
                    account_number = bank_detail.mobile_account_number
                else:
                    return Response({"status": False,"message": "Invalid payout method. Expected 'BANK_ACCOUNT' or 'MOBILE_MONEY'." },
                        status=status.HTTP_400_BAD_REQUEST)
                
                logger.info(f"Payout API: Vendor  {payout_req.vendor} with payment Metod {payout_req.payment_method}")

                if not account_bank:
                    return Response(
                        {"status": False,"message": "Bank Account is missing for the provided payout method."},
                        status=status.HTTP_400_BAD_REQUEST )

                if not account_number:
                    return Response(
                        {"status": False,"message": "Account number is missing for the provided payout method."},
                        status=status.HTTP_400_BAD_REQUEST)

                payout_data = {
                    "account_bank": account_bank,
                    "account_number": account_number,
                    "amount": amount,
                    "narration": f"Payout from wallet for transfer to  {payout_request}",
                    "currency": "TZS",
                    "beneficiary_name": bank_detail.vendor.full_name,
                    "reference": reference
                    # "callback_url": "https://e360mart.nyusoft.in/API/api/webhook/flutterwave/"
                }

                headers = {
                    "Authorization": f"Bearer {settings.FLUTTERWAVE_SECRET_KEY}",
                    "Content-Type": "application/json"
                }

                flutterwave_url = "https://api.flutterwave.com/v3/transfers"

                try:
                    response = requests.post(flutterwave_url, json=payout_data, headers=headers)
                    response_data = response.json()

                    if response.status_code == 200 and response_data.get('status') == "success":
                        logger.info('--response_data:%s', response_data['data'])
                        transaction_id = response_data['data'].get('id')
                        py_status = response_data['data'].get('status')
                        payout_payment_status = py_status.lower() 
                        reference_id = response_data['data'].get('reference')

                        logger.info('--payout_payment_status:%s', payout_payment_status)

                        if payout_payment_status == 'new':
                            payout_payment_status = 'pending'

                        payout_req.approval_date = now()
                        payout_req.approved_by = request.user
                        payout_req.transaction_id = transaction_id
                        payout_req.payment_status = payout_payment_status
                        payout_req.payment_method = payout_request
                        payout_req.status = payout_status
                        payout_req.reference_id = reference_id
                        payout_req.save()

                        logger.info(f"Payout API: Transaction ID {transaction_id} for Reference ID {reference_id} and Payout ID {payout_req.id}")

                        try:
                            payout_amount = amount if payout_status == "approved" else None
                            send_payout_status_email.delay(
                                vendor_id=payout_req.vendor_id,
                                payout_amount=payout_amount,
                                status="approved"
                            )
                            logger.info(f"Payout email task triggered for vendor {payout_req.vendor} with status '{payout_status}'")

                        except Exception as e:
                            logger.exception(f"Failed to trigger payout email for vendor {payout_req.vendor_id}: {str(e)}")
                            
                        try:
                            notify_vendor_payout_status(vendor=payout_req.vendor.id, payout_amount=payout_amount, approved=True)
                            logger.info(f"[NOTIFICATION SENT] Vendor ID {payout_req.vendor.id} - Payout Approved - TZS  {payout_amount}")
                        except Exception as e:
                            logger.exception(f"[NOTIFICATION FAILED] Vendor ID {payout_req.vendor.id} - Error sending payout approval notification: {str(e)}")


                        return Response({
                            "status": True,
                            "message": "Payout request approved and transferred successfully.",
                            "data": {
                                "payout_details": PayoutStatusUpdateSerializer(payout_req).data,
                                "transaction_id": transaction_id
                            }
                        }, status=status.HTTP_200_OK)

                    else:
                        error_message = response_data.get('message', 'Unknown error occurred')
                        logger.error(f"Flutterwave API responded with error for payout ID {payout_req.id}: {error_message}")

                        payout_req.failed_count += 1
                        payout_req.save()

                        return Response({
                            "status": False,
                            "message": error_message,
                            "error": "Payout transfer failed."
                        }, status=status.HTTP_400_BAD_REQUEST)

                except requests.exceptions.RequestException as e:
                    logger.exception(f"Flutterwave request exception for payout ID {payout_req.id}: {str(e)}")

                    return Response({
                        "status": False,
                        "message": "Failed to connect to Flutterwave.",
                        "error": str(e)
                    }, status=status.HTTP_500_INTERNAL_SERVER_ERROR)

                except Exception as e:
                    logger.exception(f"Unexpected error during Flutterwave payout for payout ID {payout_req.id}: {str(e)}")

                    return Response({
                        "status": False,
                        "message": "An unexpected error occurred while processing payout.",
                        "error": str(e)
                    }, status=status.HTTP_500_INTERNAL_SERVER_ERROR)

          
            elif payout_status == 'rejected':
                current_balance = WalletBalance.objects.filter(
                    vendor=payout_req.vendor
                ).values_list('balance', flat=True).first() or Decimal('0.00')

                added_amount = payout_req.amount or Decimal('0.00')
                new_balance = current_balance + added_amount

                logger.info(f"[Wallet Update] Vendor ID: {payout_req.vendor}")
                logger.info(f"Current Balance: {current_balance}")
                logger.info(f"Added Amount: {added_amount}")
                logger.info(f"New Balance: {new_balance}")


                WalletBalance.objects.update_or_create(
                    vendor=payout_req.vendor,
                    defaults={'balance': new_balance}
                )
                #    if payout_req.wallet_ids: 
                #         wallet_ids = list(payout_req.wallet_ids or [])
                #         if wallet_ids:
                #             WalletTransaction.objects.filter(id__in=wallet_ids).update(is_withdraw=False)


            payout_req.status = payout_status
            payout_req.save()
            try:
                # payout_amount = amount if payout_status == "approved" else None
                send_payout_status_email.delay(
                    vendor_id=payout_req.vendor_id,
                    payout_amount=payout_req.amount,
                    status=payout_status
                )
                logger.info(f"Payout email task triggered for vendor {payout_req.vendor.email} with status '{payout_status}'")

            except Exception as e:
                logger.exception(f"Failed to trigger payout email for vendor {payout_req.vendor.email}: {str(e)}")

           
            try:
                notify_vendor_payout_status(vendor=payout_req.vendor.id, payout_amount=payout_req.amount, approved=False)
                logger.info(f"[NOTIFICATION SENT] Vendor ID  {payout_req.vendor.id} - Payout Rejected - TZS {payout_req.amount}")
            except Exception as e:
                logger.exception(f"[NOTIFICATION FAILED] Vendor ID  {payout_req.vendor.id} - Error sending payout rejection notification: {str(e)}")


            return Response({
                "status":True,
                "message": "Payout request status updated successfully",
                "data": PayoutStatusUpdateSerializer(payout_req).data
            }, status=status.HTTP_200_OK)

        except PayoutRequest.DoesNotExist:
            return Response({"status":False,"message": "Payout Request not found"}, status=status.HTTP_404_NOT_FOUND)

        except Exception as e:
            print('admin payout error', str(e))
            return Response({"status":False,"message": str(e)}, status=status.HTTP_500_INTERNAL_SERVER_ERROR)
  

   
class VendorWalletBalance(APIView) :
    permission_classes = [IsAuthenticated, IsCustomAdmin]

    def post(self, request) :

        vendors = User.objects.filter(is_vendor=True,is_active=True)

        for vendor in vendors:
            credit_total = WalletTransaction.objects.filter(
                vendor=vendor,
                status='completed',
                is_withdraw=False,
                transaction_type='credit'
            ).aggregate(total=Sum('vendor_total_amount'))['total'] or 0

            # withdraw_total = WalletTransaction.objects.filter(
            #     vendor=vendor,
            #     status='completed',
            #     is_withdraw=True,
            #     transaction_type='withdraw'
            # ).aggregate(total=Sum('amount'))['total'] or 0

            balance = credit_total

            logger.info(f"[Wallet Update] Vendor ID: {vendor.id}, "
                        f"Credits: {credit_total}, "
                        f"Final Balance: {balance}")

            WalletBalance.objects.update_or_create(
                vendor=vendor,
                defaults={'balance': balance}
            )

        return Response({"detail": "Wallet balances updated successfully."})