from rest_framework import viewsets, views, status, permissions
from rest_framework.response import Response
from rest_framework.decorators import action
from django.conf import settings
from .models import Member, BankDetail, CardTemplate, OTPLog
from .serializers import MemberSerializer, BankDetailSerializer, CardTemplateSerializer, OTPLogSerializer
from django.contrib.auth.hashers import make_password, check_password
from django.utils import timezone
import requests
import random

# Aakash SMS Integration
def send_otp_sms(phone, otp):
    # Aakash SMS API requires 'auth_token', 'to', 'text'
    # Base URL: https://sms.aakashsms.com/sms/v3/send
    url = "https://sms.aakashsms.com/sms/v3/send"
    payload = {
        'auth_token': settings.AAKASH_SMS_TOKEN,
        'to': phone,
        'text': f"Your PLP Membership tracking OTP is: {otp}. Do not share this code."
    }
    try:
        response = requests.post(url, data=payload)
        print("Aakash SMS Response:", response.text)
        res_data = response.json()
        if res_data.get('error'):
            print("Aakash SMS API Error:", res_data)
            return False, str(res_data.get('message', res_data))
        return True, "Success"
    except Exception as e:
        print("SMS Error:", e)
        return False, str(e)

# ----- PUBLIC APIS -----

class SubmitFormView(views.APIView):
    permission_classes = [permissions.AllowAny]

    def post(self, request):
        import json
        data = request.data
        
        # Helper to parse JSON fields from form-data if needed
        def get_json(key, default):
            val = data.get(key)
            if isinstance(val, str):
                try:
                    return json.loads(val)
                except:
                    return default
            return val if val is not None else default

        member = Member.objects.create(
            name_nepali=data.get('nameNepali', ''),
            name_english=data.get('nameEnglish', ''),
            father_name=data.get('fatherName', ''),
            mother_name=data.get('motherName', ''),
            gender=data.get('gender', ''),
            dob=data.get('dob') if data.get('dob') else None,
            dob_bs=data.get('dobBS', ''),
            jaati=data.get('jaati', ''),
            marital=data.get('marital', ''),
            blood_group=data.get('bloodGroup', ''),
            education=data.get('education', ''),
            profession=data.get('profession', ''),
            organization=data.get('organization', ''),
            phones=get_json('phones', []),
            emails=get_json('emails', []),
            citizenship_no=data.get('citizenshipNo', ''),
            citizenship_issued_district=data.get('citizenshipIssuedDistrict', ''),
            voter_id=data.get('voterId', ''),
            membership_type=data.get('membershipType', ''),
            referred_by=data.get('referredBy', ''),
            motivation=data.get('motivation', ''),
            address=get_json('address', {}),
            # File Uploads
            profile_photo=request.FILES.get('profile_photo'),
            citizenship_document=request.FILES.get('citizenship_document'),
            voter_id_document=request.FILES.get('voter_id_document')
        )
        return Response({'membershipId': member.membership_id}, status=status.HTTP_201_CREATED)

class RequestOTPView(views.APIView):
    permission_classes = [permissions.AllowAny]

    def post(self, request):
        membership_id = request.data.get('membership_id')
        try:
            member = Member.objects.get(membership_id=membership_id)
            
            # Check if user already has a PIN
            if member.pin:
                return Response({"has_pin": True, "message": "User has a PIN set. Please verify PIN."})
                
            # Find primary phone
            primary_phone = None
            for p in member.phones:
                if p.get('isPrimary'):
                    primary_phone = p.get('number')
                    break
            
            if not primary_phone and member.phones:
                primary_phone = member.phones[0].get('number')
                
            if not primary_phone:
                return Response({"error": "No phone number found for this member."}, status=status.HTTP_400_BAD_REQUEST)
                
            otp = str(random.randint(100000, 999999))
            
            # Send SMS
            sent, debug_msg = send_otp_sms(primary_phone, otp)
            if not sent:
                return Response({'error': f'Failed to send SMS OTP. Debug: {debug_msg}'}, status=status.HTTP_500_INTERNAL_SERVER_ERROR)
                
            OTPLog.objects.create(phone_number=primary_phone, otp_code=otp)
            
            # Mask phone for response
            masked_phone = f"******{primary_phone[-4:]}" if len(primary_phone) >= 4 else primary_phone
            return Response({"has_pin": False, "message": f"OTP sent to {masked_phone}"})
        except Member.DoesNotExist:
            return Response({"error": "Membership ID not found."}, status=status.HTTP_404_NOT_FOUND)

class VerifyOTPView(views.APIView):
    permission_classes = [permissions.AllowAny]

    def post(self, request):
        membership_id = request.data.get('membership_id')
        otp = request.data.get('otp')
        
        try:
            member = Member.objects.get(membership_id=membership_id)
            # Fetch primary phone
            primary_phone = next((p.get('number') for p in member.phones if p.get('isPrimary')), None)
            if not primary_phone and member.phones:
                primary_phone = member.phones[0].get('number')
                
            log = OTPLog.objects.filter(phone_number=primary_phone, otp_code=otp, is_used=False).order_by('-created_at').first()
            if log:
                # Check expiry (e.g. 10 mins)
                if (timezone.now() - log.created_at).seconds > 600:
                    return Response({"error": "OTP Expired"}, status=status.HTTP_400_BAD_REQUEST)
                log.is_used = True
                log.save()
                return Response({"success": True, "message": "OTP Verified"})
            else:
                return Response({"error": "Invalid OTP"}, status=status.HTTP_400_BAD_REQUEST)
                
        except Member.DoesNotExist:
            return Response({"error": "Member not found."}, status=status.HTTP_404_NOT_FOUND)

class CreatePINView(views.APIView):
    permission_classes = [permissions.AllowAny]

    def post(self, request):
        membership_id = request.data.get('membership_id')
        pin = request.data.get('pin')
        
        try:
            member = Member.objects.get(membership_id=membership_id)
            member.pin = make_password(pin)
            member.save()
            # Return member data for timeline
            return Response(MemberSerializer(member).data)
        except Member.DoesNotExist:
            return Response({"error": "Member not found."}, status=status.HTTP_404_NOT_FOUND)

class VerifyPINView(views.APIView):
    permission_classes = [permissions.AllowAny]

    def post(self, request):
        membership_id = request.data.get('membership_id')
        pin = request.data.get('pin')
        
        try:
            member = Member.objects.get(membership_id=membership_id)
            if not member.pin:
                return Response({"error": "PIN not set for this member."}, status=status.HTTP_400_BAD_REQUEST)
            
            if check_password(pin, member.pin):
                return Response(MemberSerializer(member).data)
            else:
                return Response({"error": "Incorrect PIN."}, status=status.HTTP_401_UNAUTHORIZED)
        except Member.DoesNotExist:
            return Response({"error": "Member not found."}, status=status.HTTP_404_NOT_FOUND)

class ActiveBankDetailsView(views.APIView):
    permission_classes = [permissions.AllowAny]

    def get(self, request):
        banks = BankDetail.objects.filter(is_active=True)
        return Response(BankDetailSerializer(banks, many=True).data)


# ----- PROTECTED ADMIN APIS -----

class MemberViewSet(viewsets.ModelViewSet):
    permission_classes = [permissions.IsAuthenticated]
    queryset = Member.objects.all().order_by('-created_at')
    serializer_class = MemberSerializer

    def get_object(self):
        lookup_url_kwarg = self.lookup_url_kwarg or self.lookup_field
        lookup = self.kwargs.get(lookup_url_kwarg)
        if isinstance(lookup, str) and lookup.startswith('PLP'):
            from django.shortcuts import get_object_or_404
            obj = get_object_or_404(self.get_queryset(), membership_id=lookup)
            self.check_object_permissions(self.request, obj)
            return obj
        return super().get_object()

    def get_client_ip(self, request):
        x_forwarded_for = request.META.get('HTTP_X_FORWARDED_FOR')
        if x_forwarded_for:
            ip = x_forwarded_for.split(',')[0]
        else:
            ip = request.META.get('REMOTE_ADDR')
        return ip

    def perform_create(self, serializer):
        instance = serializer.save()
        from .models import MemberAuditLog
        MemberAuditLog.objects.create(
            member=instance,
            admin_user=self.request.user,
            action="Created Member",
            ip_address=self.get_client_ip(self.request)
        )

    def perform_update(self, serializer):
        instance = serializer.save()
        from .models import MemberAuditLog
        
        action_text = "Updated Member details"
        if 'generated_card' in serializer.validated_data:
            action_text = "Generated and Saved Membership Card"
        elif 'status' in serializer.validated_data and serializer.validated_data['status'] == 'membership_issued':
            action_text = "Issued Membership"
            
        MemberAuditLog.objects.create(
            member=instance,
            admin_user=self.request.user,
            action=action_text,
            ip_address=self.get_client_ip(self.request)
        )
    
    @action(detail=True, methods=['post'])
    def reset_pin(self, request, pk=None):
        member = self.get_object()
        member.pin = None
        member.save()
        from .models import MemberAuditLog
        MemberAuditLog.objects.create(
            member=member,
            admin_user=self.request.user,
            action="Force Reset PIN",
            ip_address=self.get_client_ip(self.request)
        )
        return Response({"status": "PIN reset successfully"})

class BankDetailViewSet(viewsets.ModelViewSet):
    permission_classes = [permissions.IsAuthenticated]
    queryset = BankDetail.objects.all()
    serializer_class = BankDetailSerializer

class CardTemplateViewSet(viewsets.ModelViewSet):
    permission_classes = [permissions.IsAuthenticatedOrReadOnly]
    queryset = CardTemplate.objects.all()
    serializer_class = CardTemplateSerializer

class OTPLogViewSet(viewsets.ReadOnlyModelViewSet):
    permission_classes = [permissions.IsAuthenticated]
    queryset = OTPLog.objects.all().order_by('-created_at')
    serializer_class = OTPLogSerializer

class MemberProfileUpdateView(views.APIView):
    permission_classes = [permissions.AllowAny]

    def patch(self, request):
        membership_id = request.data.get('membership_id')
        pin = request.data.get('pin')
        
        try:
            member = Member.objects.get(membership_id=membership_id)
            if not member.pin or not check_password(pin, member.pin):
                return Response({"error": "Unauthorized. Invalid PIN."}, status=status.HTTP_401_UNAUTHORIZED)
            
            import json
            def get_json(key, default):
                val = request.data.get(key)
                if isinstance(val, str):
                    try:
                        return json.loads(val)
                    except:
                        return default
                return val if val is not None else default
            
            # Update Social Links
            if 'social_media_links' in request.data:
                member.social_media_links = get_json('social_media_links', member.social_media_links)
            
            # Update files (if provided)
            if 'profile_photo' in request.FILES:
                member.profile_photo = request.FILES['profile_photo']
                member.profile_photo_approved = False  # requires re-approval
            if 'citizenship_document' in request.FILES:
                member.citizenship_document = request.FILES['citizenship_document']
                member.citizenship_approved = False
            if 'voter_id_document' in request.FILES:
                member.voter_id_document = request.FILES['voter_id_document']
                member.voter_id_approved = False
                
            member.save()
            return Response(MemberSerializer(member).data)
            
        except Member.DoesNotExist:
            return Response({"error": "Member not found."}, status=status.HTTP_404_NOT_FOUND)
