import datetime
from datetime import  datetime
from django.shortcuts import get_object_or_404
from django.core.signing import BadSignature
from django.http import JsonResponse
from django.shortcuts import redirect
from django.contrib import messages
from visitors_app.models import user,appointment,roles,location,company,department,website_setting,appointment_reject
from visitors_app.views import date_time,generate_vms_string
from visitors_app.context_processors import my_constants
from django.template.loader import render_to_string
import base64
import os
from django.core.mail import  EmailMultiAlternatives
from django.utils.html import strip_tags
from django.shortcuts import render
from PIL import Image
import io
from django.db.models import Q
import requests
from django.core import signing
from gate_keeper_app.whatsapps_send_notification import whatsapps_send_notifications
def gate_keeper_visitor_add(request):
    constants = my_constants(request)

    username = request.session.get('gate_keeper')
    if not username:
        return redirect('gate_keeper')
    user_data = constants.get('gate_keeper_data', {})
    from_email = constants['From_Email']
    user_id = user_data.get('id')
    try:
        user_data_gate = user.objects.get(id=user_id)
        gatekeeper_location = user_data_gate.location_id  # Get gatekeeper's location
    except user.DoesNotExist:
        gatekeeper_location = None
    user_data_gate = user.objects.get(id=user_id)
    # all_employee = user.objects.filter(type__in='employee', is_active=1, location_id=gatekeeper_location)
    all_employee = user.objects.filter(Q(type__icontains='employee'), is_active=1, location_id=gatekeeper_location)
    locationes = location.objects.filter(status=1, id=gatekeeper_location)

    companyes = company.objects.filter(status=1)

    departmentes = department.objects.filter(location_id=gatekeeper_location)
    role = roles.objects.all()

    if request.method == "POST":

        user_ides = request.POST['user_id']
        if user_ides:
            user_ides_chane = int(user_ides)
            visitor_user = user.objects.filter(id=user_ides_chane).first()
            all_users = user.objects.get(id=user_ides_chane)

        employee_id = request.POST['employee']
        date = request.POST['date']
        time = request.POST['time']
        purpose = request.POST['Purpose']
        visitors_type = request.POST['visitors_type']
        detail = request.POST['detail']
        firstname = request.POST['Firstname']
        lastname = request.POST['Lastname']
        email = request.POST['Email']
        visitor_company_name = request.POST['visitor_company_name']
        address = request.POST['Address']
        mobile = request.POST['mobile']
        gender = request.POST['gender']
        company_id = request.POST['company_id']
        department_id = request.POST['department_id']
        status = request.POST['status']
        location_id = request.POST['location_id']
        image = request.POST['user_image']
        visitors_timing = request.POST['visitors_timing']
        device = request.POST['devices']
        if 'user' in image:
            filename = image

        else:
            base64_data = image.split(",")[1]
            binary_data = base64.b64decode(base64_data)
            image = Image.open(io.BytesIO(binary_data))

            save_directory = 'user/'
            if not os.path.exists(save_directory):
                os.makedirs(save_directory)
            filename = firstname.replace(' ', '_')
            file_date = generate_vms_string()
            new_file_name = file_date.replace('VMS', '')
            filename = f"{filename}_{new_file_name}.jpg"
            face_image_path = os.path.join(save_directory, filename)

            image.save(face_image_path)

        if user_ides in '':
            if email != '':
                if user.objects.filter(email=email).exists():
                    messages.error(request, 'User Email already exists.', extra_tags='danger')
                    return redirect('gate_keeper_visitor_add')
            else:
                email = None
        else:
            email = email
            pass

        created_at = date_time()
        updated_at = date_time()

        if (employee_id == '' or employee_id == 'Choose employee' or
                date == '' or time == '' or purpose == '' or
                visitors_type == 'Choose visitors type' or visitors_type == '' or
                firstname == '' or
                lastname == '' or address == '' or gender == '' or
                company_id == '' or company_id == '-- Select Company  --' or
                department_id == '' or department_id == '-- Select Department --' or
                location_id == '' or location_id == '-- Select Location --' or
                status == ''):
            messages.error(request, "All fields are required.", extra_tags="danger")
            return render(request, 'dashboard/gate_keeper_dashboard/gate_keeper_visitor_add.html', {
                'username': username, 'all_employee': all_employee, 'locationes': locationes,
                'companyes': companyes, 'departmentes': departmentes, 'roles': role
            })

        try:
            if user_ides in '':
                new_user = user.objects.create(
                    first_name=firstname,
                    last_name=lastname,
                    email=email,
                    address=address,
                    mobile=mobile,
                    gender=gender,
                    image=filename,
                    type='visitors',
                    company_id=company_id,
                    department_id=department_id,
                    location_id=location_id,
                    is_active=status,
                    created_at=created_at,
                    uni_id=generate_vms_string(),
                    created_by=user_id,
                    employee_code=0,
                    designation_id=0
                )

                new_user.save()
                new_user.save()
                new_appointment = appointment.objects.create(
                    employee_id=employee_id,
                    date=date,
                    time=time,
                    status='pending',
                    purpose=purpose,
                    visitors_type=visitors_type,
                    detail=detail,
                    visitors_id=new_user.id,  # Assuming there's a ForeignKey relationship
                    created_at=date_time(),
                    created_by=user_id,
                    visitors_timing=visitors_timing,
                    employee_approval=None,
                    visitor_company_name =visitor_company_name,
                    devices =device


                )
                new_appointment.request_id = f"{datetime.now().strftime('VMS%d%m%Y%H%M')}{new_appointment.id}"
                new_appointment.save(update_fields=['request_id'])
                # new_appointment.save()
                employee_email = user.objects.filter(id=employee_id).first()

                if employee_email != '':
                    try:
                        appointment_id = new_appointment.id
                        encrypted_appointment_id = signing.dumps(appointment_id)
                        base_url = request.build_absolute_uri('/')[:-1]
                        subject_employee = 'New Visitor Appointment'
                        context_employee = {
                            'employee_data': employee_email,
                            'visitor_data': new_user,
                            'new_appointment': new_appointment,
                            'accept_url': f"{base_url}/accept/{encrypted_appointment_id}",
                            'reject_url': f"{base_url}/reject/{encrypted_appointment_id}",
                        }

                        template_name_employee = 'dashboard/admin_dashboard/admin_notifitation/employee_notification_email.html'

                        message_employee = render_to_string(template_name_employee, context_employee)
                        plain_message_employee = strip_tags(message_employee)
                        recipient_list_employee = [employee_email]

                        mail_employee = EmailMultiAlternatives(subject_employee, plain_message_employee, from_email,
                                                               recipient_list_employee)
                        mail_employee.attach_alternative(message_employee, "text/html")
                        mail_employee.send()
                    except Exception as e:
                        print('email_send_error', e)
                        messages.error(request, f"Error: {e}", extra_tags="danger")
                        return redirect('gate_keeper_visitor_verification')
                try:
                    if employee_email.mobile != '' or new_user.mobile != '':
                        # visitor_name = new_user.first_name
                        visitor_name = new_user.first_name
                        if visitor_name == '':
                            visitor_name = '(visitor name)'
                        else:
                            visitor_name = visitor_name

                        visitor_mobile = new_user.mobile

                        if visitor_mobile == '':
                            visitor_mobile = None
                        else:
                            visitor_mobile = visitor_mobile

                        invitation_link = f"{base_url}/register/{encrypted_appointment_id}"
                        employee_mobile = employee_email.mobile
                        employee_name = employee_email.first_name
                        visitor_name = visitor_name if visitor_name else 'Default Visitor Name'
                        accept_url = f"{base_url}/accept/{encrypted_appointment_id}"
                        reject_url = f"{base_url}/reject/{encrypted_appointment_id}"
                        purpose_of_visit = new_appointment.purpose

                        company_id = user_data_gate.company_id
                        check_company = company.objects.get(id=company_id)
                        company_name = check_company.company_name

                        location_id = user_data_gate.location_id
                        check_location = location.objects.get(id=location_id)
                        company_location = check_location.location_name

                        check_in_date = datetime.today().strftime("%d-%m-%Y")
                        check_in_time = datetime.now().strftime("%H:%M")
                        website_settings = website_setting.objects.first()
                        if website_settings.whatsapp_notification == 1:
                            company_website = website_settings.company_domain
                            whatsapps_send_notifications(request, employee_mobile, employee_name, visitor_name,
                                                         accept_url, reject_url, purpose_of_visit, company_name,
                                                         company_location, check_in_date, check_in_time,
                                                         company_website, visitor_mobile, invitation_link)
                except requests.exceptions.RequestException as e:
                    messages.error(request, f"Error: {e}", extra_tags="danger")
                    return redirect('gate_keeper_visitor_verification')
                if email != '' and email != None:
                    try:
                        appointment_id = new_appointment.id
                        encrypted_appointment_id = signing.dumps(appointment_id)
                        confirmation_link = f"{base_url}/register/{encrypted_appointment_id}"
                        subject_visitor = 'Appointment Confirmation'
                        context_visitor = {
                            'visitor_data': new_user,
                            'employee_data': employee_email,
                            'new_appointment': new_appointment,
                            'confirmation_link': confirmation_link,
                            'is_link': False

                        }
                        template_name_visitor = 'dashboard/admin_dashboard/admin_notifitation/visitor_confirmation_email.html'
                        message_visitor = render_to_string(template_name_visitor, context_visitor)
                        plain_message_visitor = strip_tags(message_visitor)
                        recipient_list_visitor = [email]

                        mail_visitor = EmailMultiAlternatives(subject_visitor, plain_message_visitor, from_email,
                                                              recipient_list_visitor)
                        mail_visitor.attach_alternative(message_visitor, "text/html")
                        mail_visitor.send()

                        messages.success(request, "Appointment successfully created.", extra_tags="success")
                        return redirect('gate_keeper_visitor_verification')
                    except requests.RequestException as e:
                        print(f"API request error: {e}")
                        messages.success(request, "Appointment successfully created.", extra_tags="success")
                        messages.error(request, f"API request error: {e}", extra_tags="danger")
                        return redirect('gate_keeper_visitor_verification')
                else:
                    messages.success(request, "Appointment successfully created.", extra_tags="success")
                    return redirect('gate_keeper_visitor_verification')
            else:
                if email == '':
                    email = None
                all_users.first_name = firstname
                all_users.last_name = lastname
                all_users.email = email
                # all_users.password = password
                all_users.address = address
                all_users.mobile = mobile
                all_users.gender = gender
                all_users.image = filename
                all_users.type = 'visitors'
                all_users.company_id = company_id
                all_users.department_id = department_id
                all_users.location_id = location_id
                all_users.is_active = status
                all_users.created_at = created_at
                # all_users.uni_id = generate_vms_string()
                all_users.created_by = user_id
                all_users.employee_code = 0
                all_users.designation_id = 0
                all_users.save()

                new_appointment = appointment.objects.create(
                    employee_id=employee_id,
                    date=date,
                    time=time,
                    status='pending',
                    purpose=purpose,
                    visitors_type=visitors_type,
                    detail=detail,
                    visitors_id=user_ides,  # Assuming there's a ForeignKey relationship
                    created_at=date_time(),
                    created_by=user_id,
                    # access_card_id=employees_API,
                    visitors_timing=visitors_timing,
                    employee_approval=None,
                    visitor_company_name=visitor_company_name,
                    devices=device
                )
                new_appointment.request_id = f"{datetime.now().strftime('VMS%d%m%Y%H%M')}{new_appointment.id}"
                new_appointment.save(update_fields=['request_id'])
                # new_appointment.save()
                employee_email = user.objects.filter(id=employee_id).first()

                if employee_email != '':
                    try:
                        appointment_id = new_appointment.id
                        encrypted_appointment_id = signing.dumps(appointment_id)
                        base_url = request.build_absolute_uri('/')[:-1]
                        subject_employee = 'New Visitor Appointment'
                        context_employee = {
                            'employee_data': employee_email,
                            'visitor_data': visitor_user,
                            'new_appointment': new_appointment,
                            'accept_url': f"{base_url}/accept/{encrypted_appointment_id}",
                            'reject_url': f"{base_url}/reject/{encrypted_appointment_id}",
                        }

                        template_name_employee = 'dashboard/admin_dashboard/admin_notifitation/employee_notification_email.html'

                        message_employee = render_to_string(template_name_employee, context_employee)
                        plain_message_employee = strip_tags(message_employee)
                        recipient_list_employee = [employee_email]

                        mail_employee = EmailMultiAlternatives(subject_employee, plain_message_employee, from_email,
                                                               recipient_list_employee)
                        mail_employee.attach_alternative(message_employee, "text/html")
                        mail_employee.send()
                    except Exception as e:
                        print('eamil_send_error', e)
                        messages.success(request, "Appointment successfully created.", extra_tags="success")
                        messages.error(request, f"Error: {e}", extra_tags="danger")
                        return redirect('gate_keeper_visitor_verification')
                try:
                    if employee_email.mobile != '' or all_users.mobile != '':
                        # visitor_name = new_user.first_name
                        visitor_name = all_users.first_name
                        if visitor_name == '':
                            visitor_name = '(visitor name)'
                        else:
                            visitor_name = visitor_name

                        visitor_mobile = all_users.mobile
                        if visitor_mobile == '':
                            visitor_mobile = None
                        else:
                            visitor_mobile = visitor_mobile
                        invitation_link = f"{base_url}/register/{encrypted_appointment_id}"
                        employee_mobile = employee_email.mobile
                        employee_name = employee_email.first_name
                        visitor_name = visitor_name if visitor_name else 'Default Visitor Name'
                        accept_url = f"{base_url}/accept/{encrypted_appointment_id}"
                        reject_url = f"{base_url}/reject/{encrypted_appointment_id}"

                        purpose_of_visit = new_appointment.purpose

                        company_id = user_data_gate.company_id
                        check_company = company.objects.get(id=company_id)
                        company_name = check_company.company_name

                        location_id = user_data_gate.location_id
                        check_location = location.objects.get(id=location_id)
                        company_location = check_location.location_name

                        check_in_date = datetime.today().strftime("%d-%m-%Y")
                        check_in_time = datetime.now().strftime("%H:%M")
                        website_settings = website_setting.objects.first()
                        if website_settings.whatsapp_notification == 1:
                            company_website = website_settings.company_domain
                            whatsapps_send_notifications(request, employee_mobile, employee_name, visitor_name,
                                                         accept_url, reject_url, purpose_of_visit, company_name,
                                                         company_location, check_in_date, check_in_time,
                                                         company_website, visitor_mobile, invitation_link)
                except requests.exceptions.RequestException as e:
                    messages.error(request, f"Error: {e}", extra_tags="danger")
                    return redirect('gate_keeper_visitor_verification')
                if email != '' and email != None:
                    try:
                        appointment_id = new_appointment.id
                        encrypted_appointment_id = signing.dumps(appointment_id)
                        confirmation_link = f"{base_url}/register/{encrypted_appointment_id}"
                        subject_visitor = 'Appointment Confirmation'
                        context_visitor = {
                            'visitor_data': visitor_user,
                            'employee_data': employee_email,
                            'new_appointment': new_appointment,
                            'confirmation_link': confirmation_link,
                            'is_link': False
                        }
                        template_name_visitor = 'dashboard/admin_dashboard/admin_notifitation/visitor_confirmation_email.html'
                        message_visitor = render_to_string(template_name_visitor, context_visitor)
                        plain_message_visitor = strip_tags(message_visitor)
                        recipient_list_visitor = [email]

                        mail_visitor = EmailMultiAlternatives(subject_visitor, plain_message_visitor, from_email,
                                                              recipient_list_visitor)
                        mail_visitor.attach_alternative(message_visitor, "text/html")
                        mail_visitor.send()

                        messages.success(request, "Appointment successfully created.", extra_tags="success")
                        return redirect('gate_keeper_visitor_verification')
                    except requests.RequestException as e:
                        print(f"API request error: {e}")
                        messages.success(request, "Appointment successfully created.", extra_tags="success")
                        messages.error(request, f"API request error: {e}", extra_tags="danger")
                        return redirect('gate_keeper_visitor_verification')
                else:
                    messages.success(request, "Appointment successfully created.", extra_tags="success")
                    return redirect('gate_keeper_visitor_verification')
        except requests.RequestException as e:
            print(f"API request error: {e}")
            messages.error(request, f"API request error: {e}", extra_tags="danger")

    return render(request, 'dashboard/gate_keeper_dashboard/gate_keeper_visitor_add.html', {
        'username': username, 'all_employee': all_employee, 'locationes': locationes,
        'companyes': companyes, 'departmentes': departmentes, 'roles': role,'function_name': 'Gate Keeper'
    })


def gate_keeper_ajax_load_employee(request):
    employee_id = request.GET.get('employee_id')  # Correct parameter name

    all_user = user.objects.filter(id=employee_id).first()  # Correct filter by `id`

    if all_user is not None:

        all_employee = company.objects.filter(id=all_user.company_id).values('id', 'company_name')

        all_department = department.objects.filter(id=all_user.department_id).values('id', 'department_name')

        all_location = location.objects.filter(id=all_user.location_id).values('id', 'location_name')

        response_data = {

            'company': list(all_employee),

            'departments': list(all_department),

            'location': list(all_location)

        }

        return JsonResponse(response_data, safe=False)

    else:

        return JsonResponse([], safe=False)


def gate_keeper_visitor_edit(request, id):
    constants = my_constants(request)
    user_data = constants.get('gate_keeper_data', {})
    username = request.session.get('gate_keeper')
    if not username:
        return redirect('gate_keeper')

    # Fetch the appointment based on id
    all_appointment = get_object_or_404(appointment, id=id)
    email = username['user_email']
    # Get visitors_id from the appointment object
    visitors_id = all_appointment.visitors_id

    # Fetch the user based on visitors_id
    all_user = user.objects.filter(id=visitors_id).first()
    all_mobile = all_user.mobile

    all_email = all_user.email
    gate_keeper_user = user.objects.get(email=email)
    mobile = gate_keeper_user.mobile
    # Fetch related data
    all_employee = user.objects.filter(Q(type__icontains='employee'), is_active=1)
    locationes = location.objects.filter(status=1)
    companyes = company.objects.filter(status=1)
    departmentes = department.objects.all()
    role = roles.objects.all()

    if request.method == "POST":
        all_user.first_name = request.POST['Firstname']
        all_user.last_name = request.POST['Lastname']
        emailes = request.POST['Email']
        if emailes != all_email and emailes != '':
            existing_user = user.objects.filter(email=emailes).exists()
            if existing_user:
                messages.error(request, "This Email is already in use.", extra_tags='danger')
                return redirect('gate_keeper_visitor_edit', id=id)
            else:
                all_user.email = emailes
        elif emailes == '':  # If email is empty, set email back to original or handle accordingly
            all_user.email = all_email

        all_user.company_id = request.POST['company_id']
        all_user.department_id = request.POST['department_id']
        # all_user.area_id =request.POST['area_id']
        all_user.location_id = request.POST['location_id']
        all_user.gender = request.POST['gender']
        all_user.address = request.POST['Address']
        all_user.is_active = request.POST['status']
        all_user.mobile = request.POST['mobile']
        image = request.POST['user_image']

        if image != '':
            base64_data = image.split(",")[1]  # Extract base64 part
            binary_data = base64.b64decode(base64_data)  # Decode base64 data
            image = Image.open(io.BytesIO(binary_data))  # Convert binary data to image

            # Save the image to a directory
            save_directory = 'user/'  # Ensure this directory exists or use a path within Django's MEDIA_ROOT
            if not os.path.exists(save_directory):
                os.makedirs(save_directory)
            user_img = generate_vms_string()

            user_img = user_img.split('VMS')[1]

            filename = f"user_{user_img}"

            filename = f"{filename}.jpg"
            face_image_path = os.path.join(save_directory, filename)
            image.save(face_image_path)
            all_user.image = f"user/{filename}"
        else:

            all_user.image = all_user.image

        all_user.updated_at = date_time()
        all_user.save()
        all_user.save()
        all_appointment.visitors_id = all_user.id
        all_appointment.employee_id = request.POST['employee']
        all_appointment.purpose = request.POST['Purpose']
        all_appointment.date = request.POST['date']
        all_appointment.time = request.POST['time']
        all_appointment.detail = request.POST['detail']
        all_appointment.visitors_type = request.POST['visitors_type']
        all_appointment.visitor_company_name = request.POST['visitor_company_name']
        all_appointment.visitors_timing = request.POST['visitors_timing']
        all_appointment.devices = request.POST['devices']
        all_appointment.updated_at = date_time()

        all_appointment.save()
        messages.success(request, "Employee data updated successfully.", extra_tags="success")
        return redirect('gate_keeper_visitor_verification')

    return render(request, 'dashboard/gate_keeper_dashboard/gate_keeper_visitor_edit.html', {
        'username': username,
        'all_employee': all_employee,
        'locationes': locationes,
        'companyes': companyes,
        'departmentes': departmentes,
        'roles': role,
        'appointment': all_appointment,  # Add appointment to context if needed in the template
        'user': all_user,  # Add user to context if needed in the template
        'user_data': user_data,
        'function_name': 'Gate Keeper'

    })


def handle_appointment(request, encrypted_appointment_id, status):
    """
    Common function to handle both accepting and rejecting appointments.
    `status` should be 'accepted' or 'rejected'.
    """
    constants = my_constants(request)
    user_data = constants.get('employee_data', {})
    username = request.session.get('employee')

    if not username:
        request.session['pending_appointment'] = encrypted_appointment_id
        request.session['pending_action'] = status  # Save the pending action in the session (accepted or rejected)
        return redirect('employee')

    try:
        decrypted_appointment_id = signing.loads(encrypted_appointment_id)
        appointment_instance = get_object_or_404(appointment, id=decrypted_appointment_id)

        if appointment_instance.employee_id != user_data.get('id'):
            messages.error(request, f"You are not authorized to {status} this appointment.", extra_tags="danger")
            return redirect('employee_dashboard')

        # Check if the current status matches the desired action
        if appointment_instance.status == status:
            messages.error(request, f"Appointment is already {status}.", extra_tags="danger")
            return redirect('employee_dashboard')

        # Handle conflicting status changes
        if (status == 'rejected' and appointment_instance.status == 'accepted') or \
                (status == 'accepted' and appointment_instance.status == 'rejected'):
            messages.error(request,
                           f"You cannot change the appointment from {appointment_instance.status} to {status}.",
                           extra_tags="danger")
            return redirect('employee_dashboard')

        # Proceed to update the appointment status
        appointment_instance.status = status
        appointment_instance.employee_approval = status
        if status == 'rejected':
            # Create a new record in the AppointmentReject table
            appointment_reject.objects.create(
                appointment_id=decrypted_appointment_id,
                reason='',
                date='',
                time='',
                created_at=date_time()
            )

        appointment_instance.save()
        messages.success(request, f"Appointment {status} successfully.", extra_tags="success")

        return redirect('employee_dashboard')

    except BadSignature:
        messages.error(request, "Invalid appointment link.")
        return redirect('employee')


def accept_appointment(request, encrypted_appointment_id):
    return handle_appointment(request, encrypted_appointment_id, 'accepted')


def reject_appointment(request, encrypted_appointment_id):
    return handle_appointment(request, encrypted_appointment_id, 'rejected')