from rest_framework.views import APIView
from rest_framework.response import Response
from rest_framework import status
from rest_framework.permissions import IsAuthenticated
from django.core.exceptions import ObjectDoesNotExist
from .serializers import (
    CreditEnquiryRequestSerializer,
    CreditReportRequestSerializer,
    KYCEnquiryRequestSerializer,
    KYCReportRequestSerializer,
    CheckProfileRequestSerializer,
    CreditEnquirySerializer,
    CreditReportSerializer,
    KYCEnquirySerializer,
    KYCReportSerializer,
)
from .crb_helper import (
    crb_api_call,
    get_user_organisation,
    get_or_create_credit_enquiry_cache,
    save_credit_enquiry_cache,
    get_or_create_credit_report_cache,
    save_credit_report_cache,
    get_or_create_kyc_enquiry_cache,
    save_kyc_enquiry_cache,
    get_or_create_kyc_report_cache,
    save_kyc_report_cache,
)


class CreditEnquiryView(APIView):
    """Submit a new credit enquiry request with caching"""
    permission_classes = [IsAuthenticated]
    
    def post(self, request):
        serializer = CreditEnquiryRequestSerializer(data=request.data)
        
        if not serializer.is_valid():
            return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
        
        try:
            # Get user's organisation
            organisation = get_user_organisation(request.user)
            if not organisation:
                return Response(
                    {'message': 'User organisation not found'},
                    status=status.HTTP_403_FORBIDDEN
                )
            # Check whether organisation has CRB enabled
            if not getattr(organisation, 'is_crb_active', False):
                return Response(
                    {'message': 'CRB is not enabled for your organisation'},
                    status=status.HTTP_403_FORBIDDEN
                )
            
            payload = {
                'identifier': serializer.validated_data['identifier'],
                'entity_type': serializer.validated_data['entity_type'],
                'identification_type': serializer.validated_data['identification_type'],
                'reason': serializer.validated_data['reason'],
                'client_consented': serializer.validated_data['client_consented'],
            }
            
            if serializer.validated_data.get('sector'):
                payload['sector'] = serializer.validated_data['sector']
            if serializer.validated_data.get('format'):
                payload['format'] = serializer.validated_data['format']
            if serializer.validated_data.get('pi_code'):
                payload['pi_code'] = serializer.validated_data['pi_code']
            
            # Check cache first
            cache_obj, is_cached, cached_response = get_or_create_credit_enquiry_cache(
                organisation, payload
            )
            
            if is_cached:
                # Return cached response
                return Response(
                    {
                        'data': cached_response,
                        'cached': True,
                        'message': 'Data retrieved from cache'
                    },
                    status=status.HTTP_200_OK
                )
            
            # Call API if not cached
            result = crb_api_call(payload, '/v1/credit-enquiries/request/new')
            
            # Save to cache
            save_credit_enquiry_cache(organisation, payload, result)
            
            return Response(
                {
                    'data': result,
                    'cached': False,
                    'message': 'New data from API'
                },
                status=status.HTTP_200_OK
            )
            
        except Exception as e:
            return Response(
                {'message': str(e)},
                status=status.HTTP_500_INTERNAL_SERVER_ERROR
            )


class CreditReportView(APIView):
    """Retrieve credit report for an enquiry with caching"""
    permission_classes = [IsAuthenticated]
    
    def post(self, request):
        serializer = CreditReportRequestSerializer(data=request.data)
        
        if not serializer.is_valid():
            return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
        
        try:
            # Get user's organisation
            organisation = get_user_organisation(request.user)
            if not organisation:
                return Response(
                    {'message': 'User organisation not found'},
                    status=status.HTTP_403_FORBIDDEN
                )
            # Check whether organisation has CRB enabled
            if not getattr(organisation, 'is_crb_active', False):
                return Response(
                    {'message': 'CRB is not enabled for your organisation'},
                    status=status.HTTP_403_FORBIDDEN
                )
            
            entity_type = serializer.validated_data['entity_type']
            endpoint = (
                '/v1/credit-enquiries/individual/credit-report'
                if entity_type == 0
                else '/v1/credit-enquiries/non-individual/credit-report'
            )
            
            payload = {
                'enquiry_id': serializer.validated_data['enquiry_id'],
                'format': serializer.validated_data['format'],
                'entity_type': entity_type,
            }
            
            # Extract identifier from request to track ownership
            identifier = request.data.get('identifier', '')
            
            if entity_type == 0:
                payload['individual_id'] = serializer.validated_data.get('individual_id')
            else:
                payload['non_individual_id'] = serializer.validated_data.get('non_individual_id')
            
            # Check cache first
            cache_obj, is_cached, cached_response = get_or_create_credit_report_cache(
                organisation, payload, identifier
            )
            
            if is_cached:
                # Return cached response
                return Response(
                    {
                        'data': cached_response,
                        'cached': True,
                        'message': 'Data retrieved from cache'
                    },
                    status=status.HTTP_200_OK
                )
            
            # Call API if not cached
            result = crb_api_call(payload, endpoint)
            
            # Save to cache
            save_credit_report_cache(organisation, payload, identifier, result)
            
            return Response(
                {
                    'data': result,
                    'cached': False,
                    'message': 'New data from API'
                },
                status=status.HTTP_200_OK
            )
            
        except Exception as e:
            return Response(
                {'message': str(e)},
                status=status.HTTP_500_INTERNAL_SERVER_ERROR
            )


class KYCEnquiryView(APIView):
    """Submit a new KYC enquiry request with caching"""
    permission_classes = [IsAuthenticated]
    
    def post(self, request):
        serializer = KYCEnquiryRequestSerializer(data=request.data)
        
        if not serializer.is_valid():
            return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
        
        try:
            # Get user's organisation
            organisation = get_user_organisation(request.user)
            if not organisation:
                return Response(
                    {'message': 'User organisation not found'},
                    status=status.HTTP_403_FORBIDDEN
                )
            # Check whether organisation has CRB enabled
            if not getattr(organisation, 'is_crb_active', False):
                return Response(
                    {'message': 'CRB is not enabled for your organisation'},
                    status=status.HTTP_403_FORBIDDEN
                )
            
            payload = {
                'identifier': serializer.validated_data['identifier'],
                'entity_type': serializer.validated_data['entity_type'],
                'identification_type': serializer.validated_data['identification_type'],
                'reason': serializer.validated_data['reason'],
                'client_consented': serializer.validated_data['client_consented'],
            }
            
            if serializer.validated_data.get('sector'):
                payload['sector'] = serializer.validated_data['sector']
            if serializer.validated_data.get('format'):
                payload['format'] = serializer.validated_data['format']
            if serializer.validated_data.get('pi_code'):
                payload['pi_code'] = serializer.validated_data['pi_code']
            
            # Check cache first
            cache_obj, is_cached, cached_response = get_or_create_kyc_enquiry_cache(
                organisation, payload
            )
            
            if is_cached:
                # Return cached response
                return Response(
                    {
                        'data': cached_response,
                        'cached': True,
                        'message': 'Data retrieved from cache'
                    },
                    status=status.HTTP_200_OK
                )
            
            # Call API if not cached
            result = crb_api_call(payload, '/v1/kyc-enquiries/request/new')
            
            # Save to cache
            save_kyc_enquiry_cache(organisation, payload, result)
            
            return Response(
                {
                    'data': result,
                    'cached': False,
                    'message': 'New data from API'
                },
                status=status.HTTP_200_OK
            )
            
        except Exception as e:
            return Response(
                {'message': str(e)},
                status=status.HTTP_500_INTERNAL_SERVER_ERROR
            )


class KYCReportView(APIView):
    """Retrieve KYC report for an enquiry with caching"""
    permission_classes = [IsAuthenticated]
    
    def post(self, request):
        serializer = KYCReportRequestSerializer(data=request.data)
        
        if not serializer.is_valid():
            return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
        
        try:
            # Get user's organisation
            organisation = get_user_organisation(request.user)
            if not organisation:
                return Response(
                    {'message': 'User organisation not found'},
                    status=status.HTTP_403_FORBIDDEN
                )
            # Check whether organisation has CRB enabled
            if not getattr(organisation, 'is_crb_active', False):
                return Response(
                    {'message': 'CRB is not enabled for your organisation'},
                    status=status.HTTP_403_FORBIDDEN
                )
            
            entity_type = serializer.validated_data['entity_type']
            endpoint = (
                '/v1/kyc-enquiries/individual/kyc-report'
                if entity_type == 0
                else '/v1/kyc-enquiries/non-individual/kyc-report'
            )
            
            payload = {
                'enquiry_id': serializer.validated_data['enquiry_id'],
                'format': serializer.validated_data['format'],
                'entity_type': entity_type,
            }
            
            # Extract identifier from request to track ownership
            identifier = request.data.get('identifier', '')
            
            if entity_type == 0:
                payload['individual_id'] = serializer.validated_data.get('individual_id')
            else:
                payload['non_individual_id'] = serializer.validated_data.get('non_individual_id')
            
            # Check cache first
            cache_obj, is_cached, cached_response = get_or_create_kyc_report_cache(
                organisation, payload, identifier
            )
            
            if is_cached:
                # Return cached response
                return Response(
                    {
                        'data': cached_response,
                        'cached': True,
                        'message': 'Data retrieved from cache'
                    },
                    status=status.HTTP_200_OK
                )
            
            # Call API if not cached
            result = crb_api_call(payload, endpoint)
            
            # Save to cache
            save_kyc_report_cache(organisation, payload, identifier, result)
            
            return Response(
                {
                    'data': result,
                    'cached': False,
                    'message': 'New data from API'
                },
                status=status.HTTP_200_OK
            )
            
        except Exception as e:
            return Response(
                {'message': str(e)},
                status=status.HTTP_500_INTERNAL_SERVER_ERROR
            )


class CheckProfileView(APIView):
    """Check if profile exists in CRB system"""
    permission_classes = [IsAuthenticated]
    
    def post(self, request):
        serializer = CheckProfileRequestSerializer(data=request.data)
        
        if not serializer.is_valid():
            return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
        
        try:
            payload = {
                'identifier': serializer.validated_data['identifier'],
                'entity_type': serializer.validated_data['entity_type'],
                'identification_type': serializer.validated_data['identification_type'],
                'sector': serializer.validated_data['sector'],
            }
            
            result = crb_api_call(payload, '/v1/credit-enquiries/check-profile')
            return Response(result, status=status.HTTP_200_OK)
            
        except Exception as e:
            return Response(
                {'message': str(e)},
                status=status.HTTP_500_INTERNAL_SERVER_ERROR
            )

