from .models import Application, ApplicationRequirement
from vendor.models import Vendor
from .serializers import ApplicationRequirementSerializer, ApplicationSerializer
from application.serializers import  ApplicationSerializer, VendorSerializer, UserSerializer
from rest_framework.views import APIView
from rest_framework import status
from utils.validation import validate_required_params, ValidationError
from rest_framework import status
from utils.helper import success_response, failed_response , generate_random_text
# from account.models import User
from terms.models import TermType
from utils.exception import ValidationError
from utils.logger import record
from utils.data import logger_settings 
import requests
from dotenv import load_dotenv,dotenv_values
load_dotenv()
from utils.config import env

log_msg=logger_settings["msg"]

AUTH_SERVICE_URL = env['auth_url_users']

def check_user_exists(self, user_id):
    try:
        response = requests.get(f"{AUTH_SERVICE_URL}{user_id}")
        if response.status_code == 200:
            return True
        else:
            return False
    except requests.exceptions.RequestException as e:
        return False

class ApplicationRequirementsCRUDView(APIView):
    def get(self, request, pk=None, format=None):
        process_code = generate_random_text(6)
        record('info', f'{process_code}: {log_msg["started"]} - GET request started for ApplicationRequirement')
        try:
            if pk:
                application_requirement = ApplicationRequirement.objects.get(pk=pk)
                serializer = ApplicationRequirementSerializer(application_requirement)
                record('info', f'{process_code}: {log_msg["completed"]} - Application requirement retrieved successfully')
                return success_response(data=serializer.data, msg='Application requirement retrieved successfully')
            else:
                record('warn', f'{process_code}: {log_msg["failed"]} - Primary key needed for specific application')
                return failed_response(msg='Primary key needed for specific application')
        except ApplicationRequirement.DoesNotExist:
            record('error', f'{process_code}: {log_msg["not_found"]} - Application requirement not found')
            return failed_response(msg='Application requirement not found', code=status.HTTP_404_NOT_FOUND)
        except Exception as e:
            record('error', f'{process_code}: {log_msg["error"]} - An error occurred: {str(e)}')
            return failed_response(msg='An error occurred', code=status.HTTP_500_INTERNAL_SERVER_ERROR)
        
    def post(self, request, format=None):
        process_code = generate_random_text(6)
        record('info', f'{process_code}: {log_msg["started"]} - POST request started for ApplicationRequirement')
        try:
            validate_required_params(request, ['application', 'term_type', 'requirement'])
            application_id = request.data.get('application')
            if not Application.objects.filter(pk=application_id).exists():
                record('warn', f'{process_code}: {log_msg["not_found"]} - Application not found')
                return failed_response(msg='Application not found', code=status.HTTP_404_NOT_FOUND)
            term_type_id = request.data.get('term_type')
            if not TermType.objects.filter(pk=term_type_id).exists():
                record('warn', f'{process_code}: {log_msg["not_found"]} - Term type not found')
                return failed_response(msg='Term type not found', code=status.HTTP_404_NOT_FOUND)
            serializer = ApplicationRequirementSerializer(data=request.data)
            if serializer.is_valid():
                serializer.save()
                record('info', f'{process_code}: {log_msg["completed"]} - Application requirement created successfully')
                print(serializer.save())
                return success_response(data=serializer.data, msg='Application requirement created successfully')
            record('warn', f'{process_code}: {log_msg["validation_failed"]} - Validation failed')
            return failed_response(msg='Validation failed', code=status.HTTP_400_BAD_REQUEST)
        except ValidationError as ve:
            return failed_response(msg=f'An error occurred: {str(ve)}', code=status.HTTP_400_BAD_REQUEST)
        except Exception as e:
            record('error', f'{process_code}: {log_msg["error"]} - An error occurred: {str(e)}')
            return failed_response(msg=f'An error occurred: {str(e)}', code=status.HTTP_500_INTERNAL_SERVER_ERROR)

    def put(self, request, pk=None, format=None):
        process_code = generate_random_text(6)
        record('info', f'{process_code}: {log_msg["started"]} - PUT request started for ApplicationRequirement')
        try:
            if not pk:
                record('warn', f'{process_code}: {log_msg["failed"]} - Application requirement id is required')
                return failed_response(msg='Application requirement id is required', code=status.HTTP_400_BAD_REQUEST)
            application_requirement = ApplicationRequirement.objects.get(pk=pk)
            validate_required_params(request, ['term_type', 'application', 'requirement'])
            application_id = request.data.get('application')
            if not Application.objects.filter(pk=application_id).exists():
                record('warn', f'{process_code}: {log_msg["invalid"]} - Invalid application ID')
                return failed_response(msg='Invalid application ID', code=status.HTTP_404_NOT_FOUND)
            serializer = ApplicationRequirementSerializer(application_requirement, data=request.data)
            if serializer.is_valid():
                serializer.save()
                record('info', f'{process_code}: {log_msg["completed"]} - Application requirement updated successfully')
                return success_response(data=serializer.data, msg='Application requirement updated successfully')
            record('warn', f'{process_code}: {serializer.errors} - Validation errors during update')
            return failed_response(msg=serializer.errors, code=status.HTTP_400_BAD_REQUEST)
        except ApplicationRequirement.DoesNotExist:
            record('error', f'{process_code}: {log_msg["not_found"]} - Application requirement not found')
            return failed_response(msg='Application requirement not found', code=status.HTTP_404_NOT_FOUND)
        except ValidationError as e:
            record('error', f'{process_code}: {str(e)} - ValidationError occurred')
            return failed_response(msg=str(e), code=status.HTTP_400_BAD_REQUEST)
        except Exception as e:
            record('error', f'{process_code}: {log_msg["error"]} - An unexpected error occurred: {str(e)}')
            return failed_response(msg='An unexpected error occurred', code=status.HTTP_500_INTERNAL_SERVER_ERROR)
        
    def delete(self, request, pk=None, format=None):
        process_code = generate_random_text(6)
        record('info', f'{process_code}: {log_msg["started"]} - DELETE request started for ApplicationRequirement')
        try:
            application_requirement = ApplicationRequirement.objects.get(pk=pk)
            application_requirement.delete()
            
            record('info', f'{process_code}: {log_msg["completed"]} - Application requirement deleted successfully')
            return success_response(msg='Application requirement deleted successfully')
        except ApplicationRequirement.DoesNotExist:
            record('error', f'{process_code}: {log_msg["not_found"]} - Application requirement not found')
            return failed_response(msg='Application requirement not found', code=status.HTTP_404_NOT_FOUND)
        except Exception as e:
            record('error', f'{process_code}: {log_msg["error"]} - An unexpected error occurred: {str(e)}')
            return failed_response(msg='An unexpected error occurred', code=status.HTTP_500_INTERNAL_SERVER_ERROR)
        

class ApplicationCRUDView(APIView):
    def get(self, request, pk=None, format=None):
        process_code = generate_random_text(6)
        record('info', f'{process_code}: {log_msg["started"]} - GET request started for Application')
        try:
            if pk:
                application = Application.objects.get(pk=pk)
                serializer = ApplicationSerializer(application)
                record('info', f'{process_code}: {log_msg["completed"]} - Application retrieved successfully')
                return success_response(data=serializer.data, msg='Application retrieved successfully')
            else:
                applications = Application.objects.all()
                serializer = ApplicationSerializer(applications, many=True)
                record('info', f'{process_code}: {log_msg["completed"]} - Applications retrieved successfully')
                return success_response(data=serializer.data, msg='Applications retrieved successfully')
        except Application.DoesNotExist:
            record('error', f'{process_code}: {log_msg["not_found"]} - Application not found')
            return failed_response(msg='Application not found', code=status.HTTP_404_NOT_FOUND)
        except Exception as e:
            record('error', f'{process_code}: {log_msg["error"]} - An unexpected error occurred: {str(e)}')
            return failed_response(msg=f"An unexpected error occurred: {str(e)}", code=status.HTTP_500_INTERNAL_SERVER_ERROR)

    def post(self, request, format=None):
        process_code = generate_random_text(6)
        record('info', f'{process_code}: {log_msg["started"]} - POST request started for Application')
        try:
            validate_required_params(request, ['user_id', 'listing_id'])
            user_id = request.data.get('user_id')
            if not check_user_exists(user_id):
                record('warn', f'{process_code}: {log_msg["invalid"]} - Invalid user ID')
                return failed_response(msg="Invalid user ID", code=status.HTTP_400_BAD_REQUEST)
            listing_id = request.data.get('listing_id')
            if not Vendor.objects.filter(pk=listing_id).exists():
                record('warn', f'{process_code}: {log_msg["invalid"]} - Invalid listing ID')
                return failed_response(msg="Invalid listing ID", code=status.HTTP_400_BAD_REQUEST)
            serializer = ApplicationSerializer(data=request.data)
            if serializer.is_valid():
                serializer.save()
                record('info', f'{process_code}: {log_msg["completed"]} - Application created successfully')
                return success_response(data=serializer.data, msg='Application created successfully')
            record('warn', f'{process_code}: {log_msg["invalid"]} - Validation errors during Application creation')
            return failed_response(msg=serializer.errors, code=status.HTTP_400_BAD_REQUEST)
        except ValidationError as e:
            record('error', f'{process_code}: {str(e)} - ValidationError occurred')
            return failed_response(msg=str(e), code=status.HTTP_400_BAD_REQUEST)
        except Exception as e:
            record('error', f'{process_code}: {log_msg["error"]} - An unexpected error occurred: {str(e)}')
            return failed_response(msg=f"An unexpected error occurred: {str(e)}", code=status.HTTP_500_INTERNAL_SERVER_ERROR)

    def put(self, request, pk=None, format=None):
        process_code = generate_random_text(6)
        record('info', f'{process_code}: {log_msg["started"]} - PUT request started for Application')
        try:
            if not pk:
                record('warn', f'{process_code}: {log_msg["failed"]} - Application ID is required')
                return failed_response(msg='Application ID is required', code=status.HTTP_400_BAD_REQUEST)
            application = Application.objects.get(pk=pk)
            validate_required_params(request, ['user_id','listing_id'])
            user_id = request.data.get('user_id')
            if not check_user_exists(user_id):
                record('warn', f'{process_code}: {log_msg["invalid"]} - Invalid user ID')
                return failed_response(msg="Invalid user ID", code=status.HTTP_400_BAD_REQUEST)
            listing_id = request.data.get('listing_id')
            if not Vendor.objects.filter(pk=listing_id).exists():
                record('warn', f'{process_code}: {log_msg["invalid"]} - Invalid listing ID')
                return failed_response(msg="Invalid listing ID", code=status.HTTP_400_BAD_REQUEST)
            serializer = ApplicationSerializer(application, data=request.data)
            if serializer.is_valid():
                serializer.save()
                record('info', f'{process_code}: {log_msg["completed"]} - Application updated successfully')
                return success_response(data=serializer.data, msg='Application updated successfully')
            return failed_response(msg=serializer.errors, code=status.HTTP_400_BAD_REQUEST)
        except Application.DoesNotExist:
            record('error', f'{process_code}: {log_msg["not_found"]} - Application not found')
            return failed_response(msg='Application not found', code=status.HTTP_404_NOT_FOUND)
        except ValidationError as e:
            record('error', f'{process_code}: {str(e)} - ValidationError occurred')
            return failed_response(msg=str(e), code=status.HTTP_400_BAD_REQUEST)
        except Exception as e:
            record('error', f'{process_code}: {log_msg["error"]} - An unexpected error occurred: {str(e)}')
            return failed_response(msg=f"An unexpected error occurred: {str(e)}", code=status.HTTP_500_INTERNAL_SERVER_ERROR)

    def delete(self, request, pk=None, format=None):
        process_code = generate_random_text(6)
        record('info', f'{process_code}: {log_msg["started"]} - DELETE request started for Application')
        try:
            application = Application.objects.get(pk=pk)
            application.delete()
            record('info', f'{process_code}: {log_msg["completed"]} - Application deleted successfully')
            return success_response(msg='Application deleted successfully')
        except Application.DoesNotExist:
            record('error', f'{process_code}: {log_msg["not_found"]} - Application not found')
            return failed_response(msg='Application not found', code=status.HTTP_404_NOT_FOUND)
        except Exception as e:
            record('error', f'{process_code}: {log_msg["error"]} - An unexpected error occurred: {str(e)}')
            return failed_response(msg=f"An unexpected error occurred: {str(e)}", code=status.HTTP_500_INTERNAL_SERVER_ERROR)
        

class FullApplicantDetail(APIView):
     def get(self, request, application_id, format=None):
        process_code = generate_random_text(6)
        record('info', f'{process_code}: {log_msg["started"]} - GET request started for FullApplicantDetail')
        try:
            application = Application.objects.get(pk=application_id)
            user_id = application.user_id.id 
            # users = User.objects.filter(id=user_id)
            if not check_user_exists(user_id):
                record('warn', f'{process_code}: {log_msg["invalid"]} - Invalid user ID')
                return failed_response(msg='Invalid user ID', code=status.HTTP_400_BAD_REQUEST)
            vendors = Vendor.objects.filter(user_id=user_id)
            user_serializer = UserSerializer([application.user_id], many=False)
            vendor_serializer = VendorSerializer(vendors, many=True)
            data = {
                'users': user_serializer.data,
                'vendors': vendor_serializer.data
            }
            record('info', f'{process_code}: {log_msg["completed"]} - Data retrieved successfully')
            return success_response(data=data, msg='Data retrieved successfully')
        except Application.DoesNotExist:
            record('error', f'{process_code}: {log_msg["not_found"]} - Application not found')
            return failed_response(msg='Application not found', code=status.HTTP_404_NOT_FOUND)
        except Exception as e:
            record('error', f'{process_code}: {log_msg["error"]} - An unexpected error occurred: {str(e)}')
            return failed_response(msg=f"An unexpected error occurred: {str(e)}", code=status.HTTP_500_INTERNAL_SERVER_ERROR)
        
