"""
views.py

This module is used to define the method for the path in the urls
"""

import json
from collections import defaultdict
from datetime import date, datetime, timedelta
from itertools import groupby
from urllib.parse import parse_qs

import pandas as pd
import pdfkit
from django.contrib import messages
from django.db.models import ProtectedError, Q
from django.http import HttpResponse, HttpResponseRedirect, JsonResponse
from django.shortcuts import get_object_or_404, redirect, render
from django.template.loader import render_to_string
from django.urls import reverse
from django.utils import timezone
from django.utils.translation import gettext_lazy as _

from base.methods import (
    closest_numbers,
    eval_validate,
    export_data,
    generate_colors,
    generate_pdf,
    get_key_instances,
    sortby,
)
from base.models import Company
from employee.models import Employee, EmployeeWorkInformation
from horilla.decorators import (
    hx_request_required,
    login_required,
    owner_can_enter,
    permission_required,
)
from horilla.group_by import group_by_queryset
from horilla.horilla_settings import HORILLA_DATE_FORMATS
from notifications.signals import notify
from payroll.context_processors import get_active_employees
from payroll.filters import ContractFilter, ContractReGroup, PayslipFilter
from payroll.forms.component_forms import (
    ContractExportFieldForm,
    PayrollSettingsForm,
    PayslipAutoGenerateForm,
)
from payroll.methods.methods import paginator_qry, save_payslip
from payroll.models.models import (
    Contract,
    FilingStatus,
    PayrollGeneralSetting,
    Payslip,
    PayslipAutoGenerate,
    Reimbursement,
    ReimbursementFile,
    ReimbursementrequestComment,
)
from payroll.models.tax_models import PayrollSettings

# Create your views here.

status_choices = {
    "draft": _("Draft"),
    "review_ongoing": _("Review Ongoing"),
    "confirmed": _("Confirmed"),
    "paid": _("Paid"),
}


def get_language_code(request):
    scale_x_text = _("Name of Employees")
    scale_y_text = _("Amount")
    response = {"scale_x_text": scale_x_text, "scale_y_text": scale_y_text}
    return JsonResponse(response)


@login_required
@permission_required("payroll.add_contract")
def contract_create(request):
    """
    Contract create view
    """
    from payroll.forms.forms import ContractForm

    form = ContractForm()
    if request.method == "POST":
        form = ContractForm(request.POST, request.FILES)
        if form.is_valid():
            form.save()
            messages.success(request, _("Contract Created"))
            return redirect(contract_view)
    return render(request, "payroll/common/form.html", {"form": form})


@login_required
@permission_required("payroll.change_contract")
def contract_update(request, contract_id, **kwargs):
    """
    Update an existing contract.

    Args:
        request: The HTTP request object.
        contract_id: The ID of the contract to update.

    Returns:
        If the request method is POST and the form is valid, redirects to the contract view.
        Otherwise, renders the contract update form.

    """
    from payroll.forms.forms import ContractForm

    contract = Contract.objects.filter(id=contract_id).first()
    if not contract:
        messages.info(request, _("The contract could not be found."))
        return redirect(contract_view)
    contract_form = ContractForm(instance=contract)
    if request.method == "POST":
        contract_form = ContractForm(request.POST, request.FILES, instance=contract)
        if contract_form.is_valid():
            contract_form.save()
            messages.success(request, _("Contract updated"))
            return redirect(contract_view)
    return render(
        request,
        "payroll/common/form.html",
        {
            "form": contract_form,
        },
    )


@login_required
@hx_request_required
@permission_required("payroll.change_contract")
def contract_status_update(request, contract_id):
    from payroll.forms.forms import ContractForm

    previous_data = request.GET.urlencode()
    if request.method == "POST":
        contract = Contract.objects.get(id=contract_id)
        if request.POST.get("view"):
            status = request.POST.get("status")
            if status in dict(contract.CONTRACT_STATUS_CHOICES).keys():
                save = True
                if status in ["active", "draft"]:
                    active_contract = Contract.objects.filter(
                        contract_status="active", employee_id=contract.employee_id
                    ).exists()
                    draft_contract = Contract.objects.filter(
                        contract_status="draft", employee_id=contract.employee_id
                    ).exists()
                    if (status == "active" and active_contract) or (
                        status == "draft" and draft_contract
                    ):
                        save = False
                        messages.info(
                            request,
                            _("An {} contract already exists for {}").format(
                                status, contract.employee_id
                            ),
                        )
                if save:
                    contract.contract_status = status
                    contract.save()
                    messages.success(
                        request, _("The contract status has been updated successfully.")
                    )
            else:
                messages.warning(
                    request, _("You selected the wrong option for contract status.")
                )

            return redirect(f"/payroll/contract-filter?{previous_data}")

        contract_form = ContractForm(request.POST, request.FILES, instance=contract)
        if contract_form.is_valid():
            contract_form.save()
            messages.success(request, _("Contract status updated"))
        else:
            for errors in contract_form.errors.values():
                for error in errors:
                    messages.error(request, error)
        return HttpResponse("<script>$('#reloadMessagesButton').click()</script>")


@login_required
@permission_required("payroll.change_contract")
def bulk_contract_status_update(request):
    status = request.POST.get("status")
    ids = eval_validate(request.POST.get("ids"))
    all_contracts = Contract.objects.all()
    contracts = all_contracts.filter(id__in=ids)

    for contract in contracts:
        save = True
        if status in ["active", "draft"]:
            active_contract = all_contracts.filter(
                contract_status="active", employee_id=contract.employee_id
            ).exists()
            draft_contract = all_contracts.filter(
                contract_status="draft", employee_id=contract.employee_id
            ).exists()
            if (status == "active" and active_contract) or (
                status == "draft" and draft_contract
            ):
                save = False
                messages.info(
                    request,
                    _("An {} contract already exists for {}").format(
                        status, contract.employee_id
                    ),
                )
        if save:
            contract.contract_status = status
            contract.save()
            messages.success(
                request, _("The contract status has been updated successfully.")
            )
    return HttpResponse("success")


@login_required
@permission_required("payroll.change_contract")
def update_contract_filing_status(request, contract_id):
    if request.method == "POST":
        contract = get_object_or_404(Contract, id=contract_id)
        filing_status_id = request.POST.get("filing_status")
        try:
            filing_status = (
                FilingStatus.objects.get(id=int(filing_status_id))
                if filing_status_id
                else None
            )
            contract.filing_status = filing_status
            messages.success(
                request, _("The employee filing status has been updated successfully.")
            )
        except (ValueError, OverflowError, FilingStatus.DoesNotExist):
            messages.warning(
                request, _("You selected the wrong option for filing status.")
            )
        contract.save()
        return redirect(contract_filter)


@login_required
@hx_request_required
@permission_required("payroll.delete_contract")
def contract_delete(request, contract_id):
    """
    Delete a contract.

    Args:
        contract_id: The ID of the contract to delete.

    Returns:
        Redirects to the contract view after successfully deleting the contract.

    """
    try:
        Contract.objects.get(id=contract_id).delete()
        messages.success(request, _("Contract deleted"))
        request_path = request.path.split("/")
        if "delete-contract-modal" in request_path:
            if instances_ids := request.GET.get("instances_ids"):
                get_data = request.GET.copy()
                get_data.pop("instances_ids", None)
                previous_data = get_data.urlencode()
                instances_list = json.loads(instances_ids)
                previous_instance, next_instance = closest_numbers(
                    instances_list, contract_id
                )
                if contract_id in instances_list:
                    instances_list.remove(contract_id)
                urls = f"/payroll/single-contract-view/{next_instance}/"
                params = f"?{previous_data}&instances_ids={instances_list}"
                return redirect(urls + params)
            return HttpResponse("<script>window.location.reload();</script>")
        else:
            return redirect(f"/payroll/contract-filter?{request.GET.urlencode()}")
    except Contract.DoesNotExist:
        messages.error(request, _("Contract not found."))
    except ProtectedError:
        messages.error(request, _("You cannot delete this contract."))
    return HttpResponseRedirect(request.META.get("HTTP_REFERER", "/"))


@login_required
@permission_required("payroll.view_contract")
def contract_view(request):
    """
    Contract view method
    """

    contracts = Contract.objects.all()
    if contracts.exists():
        template = "payroll/contract/contract_view.html"
    else:
        template = "payroll/contract/contract_empty.html"

    contracts = paginator_qry(contracts, request.GET.get("page"))
    contract_ids_json = json.dumps([instance.id for instance in contracts.object_list])
    filter_form = ContractFilter(request.GET)
    context = {
        "contracts": contracts,
        "f": filter_form,
        "contract_ids": contract_ids_json,
        "gp_fields": ContractReGroup.fields,
    }

    return render(request, template, context)


@login_required
# @hx_request_required         #this function is also used in payroll dashboard which uses ajax
@owner_can_enter("payroll.view_contract", Contract)
def view_single_contract(request, contract_id):
    """
    Renders a single contract view page.
    """
    get_data = request.GET.copy()
    get_data.pop("instances_ids", None)
    previous_data = get_data.urlencode()
    dashboard = request.GET.get("dashboard", "")

    HTTP_REFERERS = request.META.get("HTTP_REFERER", "").split("/")
    delete_hx_target = (
        "#personal_target"
        if "employee-view" in HTTP_REFERERS or "employee-profile" in HTTP_REFERERS
        else "#objectDetailsModalTarget"
    )

    contract = Contract.find(contract_id)

    context = {
        "contract": contract,
        "dashboard": dashboard,
        "delete_hx_target": delete_hx_target,
        "pd": previous_data,
    }

    contract_ids_json = request.GET.get("instances_ids")
    if contract_ids_json:
        contract_ids = json.loads(contract_ids_json)
        previous_id, next_id = closest_numbers(contract_ids, contract_id)
        context.update(
            {
                "previous": previous_id,
                "next": next_id,
                "contract_ids": contract_ids_json,
            }
        )
    return render(request, "payroll/contract/contract_single_view.html", context)


@login_required
@hx_request_required
@permission_required("payroll.view_contract")
def contract_filter(request):
    """
    Filter contracts based on the provided query parameters.

    Args:
        request: The HTTP request object containing the query parameters.

    Returns:
        Renders the contract list template with the filtered contracts.

    """
    query_string = request.GET.urlencode()
    contracts_filter = ContractFilter(request.GET)
    template = "payroll/contract/contract_list.html"
    contracts = contracts_filter.qs
    field = request.GET.get("field")

    if field != "" and field is not None:
        contracts = group_by_queryset(contracts, field, request.GET.get("page"), "page")
        list_values = [entry["list"] for entry in contracts]
        id_list = []
        for value in list_values:
            for instance in value.object_list:
                id_list.append(instance.id)

        contract_ids_json = json.dumps(list(id_list))
        template = "payroll/contract/group_by.html"

    else:
        contracts = sortby(request, contracts, "orderby")
        contracts = paginator_qry(contracts, request.GET.get("page"))
        contract_ids_json = json.dumps(
            [instance.id for instance in contracts.object_list]
        )

    data_dict = parse_qs(query_string)
    get_key_instances(Contract, data_dict)
    keys_to_remove = [key for key, value in data_dict.items() if value == ["unknown"]]
    for key in keys_to_remove:
        data_dict.pop(key)
    if "contract_status" in data_dict:
        status_list = data_dict["contract_status"]
        if len(status_list) > 1:
            data_dict["contract_status"] = [status_list[-1]]
    return render(
        request,
        template,
        {
            "contracts": contracts,
            "pd": query_string,
            "filter_dict": data_dict,
            "contract_ids": contract_ids_json,
            "field": field,
        },
    )


@login_required
@permission_required("payroll.view_payrollsettings")
def settings(request):
    """
    This method is used to render settings template
    """
    instance = PayrollSettings.objects.first()
    currency_form = PayrollSettingsForm(instance=instance)
    selected_company_id = request.session.get("selected_company")

    if selected_company_id == "all" or not selected_company_id:
        companies = Company.objects.all()
    else:
        companies = Company.objects.filter(id=selected_company_id)

    if request.method == "POST":

        currency_form = PayrollSettingsForm(request.POST, instance=instance)
        if currency_form.is_valid():

            currency_form.save()
            messages.success(request, _("Payroll settings updated."))
            return HttpResponseRedirect(request.META.get("HTTP_REFERER", "/"))
    return render(
        request,
        "payroll/settings/payroll_settings.html",
        {
            "currency_form": currency_form,
            "companies": companies,
            "selected_company_id": selected_company_id,
        },
    )


@login_required
@permission_required("payroll.change_payslip")
def update_payslip_status(request, payslip_id):
    """
    This method is used to update the payslip confirmation status
    """
    status = request.POST.get("status")
    view = request.POST.get("view")
    payslip = Payslip.objects.filter(id=payslip_id).first()
    if payslip:
        payslip.status = status
        payslip.save()
        messages.success(request, _("Payslip status updated"))
    else:
        messages.error(request, _("Payslip not found"))
    if view:
        from .component_views import filter_payslip

        return redirect(filter_payslip)
    data = payslip.pay_head_data
    data["employee"] = payslip.employee_id
    data["payslip"] = payslip
    data["json_data"] = data.copy()
    data["json_data"]["employee"] = payslip.employee_id.id
    data["json_data"]["payslip"] = payslip.id
    data["instance"] = payslip
    return render(request, "payroll/payslip/individual_payslip_summery.html", data)


def update_payslip_status_no_id(request):
    """
    This method is used to update the payslip confirmation status
    """
    message = {"type": "success", "message": "Payslip status updated."}
    if request.method == "POST":
        ids_json = request.POST["ids"]
        ids = json.loads(ids_json)
        status = request.POST["status"]
        slips = Payslip.objects.filter(id__in=ids)
        slips.update(status=status)
        message = {
            "type": "success",
            "message": f"{slips.count()} Payslips status updated.",
        }
    return JsonResponse(message)


@login_required
@permission_required("payroll.change_payslip")
def bulk_update_payslip_status(request):
    """
    This method is used to update payslip status when generating payslip through
    generate payslip method
    """
    json_data = request.GET["json_data"]
    pay_data = json.loads(json_data)
    status = request.GET["status"]

    for json_entry in pay_data:
        data = json.loads(json_entry)
        emp_id = data["employee"]
        employee = Employee.objects.get(id=emp_id)

        payslip_kwargs = {
            "employee_id": employee,
            "start_date": data["start_date"],
            "end_date": data["end_date"],
        }
        filtered_instance = Payslip.objects.filter(**payslip_kwargs).first()
        instance = filtered_instance if filtered_instance is not None else Payslip()

        instance.employee_id = employee
        instance.start_date = data["start_date"]
        instance.end_date = data["end_date"]
        instance.status = status
        instance.basic_pay = data["basic_pay"]
        instance.contract_wage = data["contract_wage"]
        instance.gross_pay = data["gross_pay"]
        instance.deduction = data["total_deductions"]
        instance.net_pay = data["net_pay"]
        instance.pay_head_data = data
        instance.save()

    return JsonResponse({"type": "success", "message": "Payslips status updated"})


@login_required
def view_payslip_pdf(request, payslip_id):

    from .component_views import filter_payslip

    if Payslip.objects.filter(id=payslip_id).exists():
        payslip = Payslip.objects.get(id=payslip_id)
        company = Company.objects.filter(hq=True).first()
        if (
            request.user.has_perm("payroll.view_payslip")
            or payslip.employee_id.employee_user_id == request.user
        ):
            user = request.user
            employee = user.employee_get

            # Taking the company_name of the user
            info = EmployeeWorkInformation.objects.filter(employee_id=employee)
            if info.exists():
                for data in info:
                    employee_company = data.company_id
                company_name = Company.objects.filter(company=employee_company)
                emp_company = company_name.first()

                # Access the date_format attribute directly
                date_format = (
                    emp_company.date_format
                    if emp_company and emp_company.date_format
                    else "MMM. D, YYYY"
                )
            else:
                date_format = "MMM. D, YYYY"

            data = payslip.pay_head_data
            start_date_str = data["start_date"]
            end_date_str = data["end_date"]

            # Convert the string to a datetime.date object
            start_date = datetime.strptime(start_date_str, "%Y-%m-%d").date()
            end_date = datetime.strptime(end_date_str, "%Y-%m-%d").date()

            month_start_name = start_date.strftime("%B %d, %Y")
            month_end_name = end_date.strftime("%B %d, %Y")

            # Formatted date for each format
            for format_name, format_string in HORILLA_DATE_FORMATS.items():
                if format_name == date_format:
                    formatted_start_date = start_date.strftime(format_string)

            for format_name, format_string in HORILLA_DATE_FORMATS.items():
                if format_name == date_format:
                    formatted_end_date = end_date.strftime(format_string)
            data["month_start_name"] = month_start_name
            data["month_end_name"] = month_end_name
            data["formatted_start_date"] = formatted_start_date
            data["formatted_end_date"] = formatted_end_date
            data["employee"] = payslip.employee_id
            data["payslip"] = payslip
            data["json_data"] = data.copy()
            data["json_data"]["employee"] = payslip.employee_id.id
            data["json_data"]["payslip"] = payslip.id
            data["instance"] = payslip
            data["currency"] = PayrollSettings.objects.first().currency_symbol
            data["all_deductions"] = []
            for deduction_list in [
                data["basic_pay_deductions"],
                data["gross_pay_deductions"],
                data["pretax_deductions"],
                data["post_tax_deductions"],
                data["tax_deductions"],
                data["net_deductions"],
            ]:
                data["all_deductions"].extend(deduction_list)

            data["all_allowances"] = data["allowances"].copy()
            equalize_lists_length(data["allowances"], data["all_deductions"])
            data["zipped_data"] = zip(data["allowances"], data["all_deductions"])
            data["host"] = request.get_host()
            data["protocol"] = "https" if request.is_secure() else "http"
            data["company"] = company

            return render(request, "payroll/payslip/payslip_pdf.html", context=data)
        return redirect(filter_payslip)
    return render(request, "405.html")


@login_required
# @permission_required("payroll.view_payslip")
def view_created_payslip(request, payslip_id, **kwargs):
    """
    This method is used to view the saved payslips
    """
    payslip = Payslip.objects.filter(id=payslip_id).first()
    if payslip is not None and (
        request.user.has_perm("payroll.view_payslip")
        or payslip.employee_id.employee_user_id == request.user
    ):
        # the data must be dictionary in the payslip model for the json field
        data = payslip.pay_head_data
        data["employee"] = payslip.employee_id
        data["payslip"] = payslip
        data["json_data"] = data.copy()
        data["json_data"]["employee"] = payslip.employee_id.id
        data["json_data"]["payslip"] = payslip.id
        data["instance"] = payslip
        return render(request, "payroll/payslip/individual_payslip.html", data)
    return render(request, "404.html")


@login_required
@permission_required("payroll.delete_payslip")
def delete_payslip(request, payslip_id):
    """
    This method is used to delete payslip instances
    Args:
        payslip_id (int): Payslip model instance id
    """
    from .component_views import filter_payslip

    try:
        Payslip.objects.get(id=payslip_id).delete()
        messages.success(request, _("Payslip deleted"))
    except Payslip.DoesNotExist:
        messages.error(request, _("Payslip not found."))
    except ProtectedError:
        messages.error(request, _("Something went wrong"))
    if not Payslip.objects.filter():
        return HttpResponse("<script>window.location.reload()</script>")
    return redirect(filter_payslip)


@login_required
@permission_required("payroll.add_contract")
def contract_info_initial(request):
    """
    This is an ajax method to return json response to auto fill the contract
    form fields
    """
    employee_id = request.GET["employee_id"]
    work_info = EmployeeWorkInformation.objects.filter(employee_id=employee_id).first()
    response_data = {
        "department": (
            work_info.department_id.id if work_info.department_id is not None else ""
        ),
        "job_position": (
            work_info.job_position_id.id
            if work_info.job_position_id is not None
            else ""
        ),
        "job_role": (
            work_info.job_role_id.id if work_info.job_role_id is not None else ""
        ),
        "shift": work_info.shift_id.id if work_info.shift_id is not None else "",
        "work_type": (
            work_info.work_type_id.id if work_info.work_type_id is not None else ""
        ),
        "wage": work_info.basic_salary,
        "contract_start_date": work_info.date_joining if work_info.date_joining else "",
        "contract_end_date": (
            work_info.contract_end_date if work_info.contract_end_date else ""
        ),
    }
    return JsonResponse(response_data)


@login_required
@permission_required("payroll.view_contract")
def view_payroll_dashboard(request):
    """
    Dashboard rendering views
    """
    from payroll.forms.forms import DashboardExport

    paid = Payslip.objects.filter(status="paid")
    posted = Payslip.objects.filter(status="confirmed")
    review_ongoing = Payslip.objects.filter(status="review_ongoing")
    draft = Payslip.objects.filter(status="draft")
    export_form = DashboardExport()
    context = {
        "paid": paid,
        "posted": posted,
        "review_ongoing": review_ongoing,
        "draft": draft,
        "export_form": export_form,
    }
    return render(request, "payroll/dashboard.html", context=context)


@login_required
def dashboard_employee_chart(request):
    """
    payroll dashboard employee chart data
    """

    date = request.GET.get("period")
    year = date.split("-")[0]
    month = date.split("-")[1]
    dataset = []

    is_ajax = request.headers.get("X-Requested-With") == "XMLHttpRequest"
    if is_ajax and request.method == "GET":
        employee_list = Payslip.objects.filter(
            Q(start_date__month=month) & Q(start_date__year=year)
        )
        labels = []
        for employee in employee_list:
            labels.append(employee.employee_id)

        colors = [
            "rgba(255, 99, 132, 1)",  # Red
            "rgba(255, 206, 86, 1)",  # Yellow
            "rgba(54, 162, 235, 1)",  # Blue
            "rgba(75, 242, 182, 1)",  # green
        ]

        for choice, color in zip(Payslip.status_choices, colors):
            dataset.append(
                {
                    "label": choice[0],
                    "data": [],
                    "backgroundColor": color,
                }
            )

        employees = [employee.employee_id for employee in employee_list]

        employees = list(set(employees))
        total_pay_with_status = defaultdict(lambda: defaultdict(float))

        for label in employees:
            payslips = employee_list.filter(employee_id=label)
            for payslip in payslips:
                total_pay_with_status[payslip.status][label] += round(
                    payslip.net_pay, 2
                )

        for data in dataset:
            dataset_label = data["label"]
            data["data"] = [
                total_pay_with_status[dataset_label][label] for label in employees
            ]

        employee_label = []
        for employee in employees:
            employee_label.append(
                f"{employee.employee_first_name} {employee.employee_last_name}"
            )

        for value, choice in zip(dataset, Payslip.status_choices):
            if value["label"] == choice[0]:
                value["label"] = choice[1]

        list_of_employees = list(
            Employee.objects.values_list(
                "id", "employee_first_name", "employee_last_name"
            )
        )
        response = {
            "dataset": dataset,
            "labels": employee_label,
            "employees": list_of_employees,
            "message": _("No payslips generated for this month."),
        }
        return JsonResponse(response)


def payslip_details(request):
    """
    payroll dashboard payslip details data
    """

    date = request.GET.get("period")
    year = date.split("-")[0]
    month = date.split("-")[1]
    employee_list = []
    employee_list = Payslip.objects.filter(
        Q(start_date__month=month) & Q(start_date__year=year)
    )
    total_amount = 0
    for employee in employee_list:
        total_amount += employee.net_pay

    response = {
        "no_of_emp": len(employee_list),
        "total_amount": round(total_amount, 2),
    }
    return JsonResponse(response)


@login_required
def dashboard_department_chart(request):
    """
    payroll dashboard department chart data
    """

    date = request.GET.get("period")
    year = date.split("-")[0]
    month = date.split("-")[1]
    dataset = [
        {
            "label": "",
            "data": [],
            "backgroundColor": ["#8de5b3", "#f0a8a6", "#8ed1f7", "#f8e08e", "#c2c7cc"],
        }
    ]
    department = []
    department_total = []

    is_ajax = request.headers.get("X-Requested-With") == "XMLHttpRequest"
    if is_ajax and request.method == "GET":
        employee_list = Payslip.objects.filter(
            Q(start_date__month=month) & Q(start_date__year=year)
        )

        for employee in employee_list:
            department.append(
                employee.employee_id.employee_work_info.department_id.department
            )

        department = list(set(department))
        for depart in department:
            department_total.append({"department": depart, "amount": 0})

        for employee in employee_list:
            employee_department = (
                employee.employee_id.employee_work_info.department_id.department
            )

            for depart in department_total:
                if depart["department"] == employee_department:
                    depart["amount"] += round(employee.net_pay, 2)

        colors = generate_colors(len(department))

        dataset = [
            {
                "label": "",
                "data": [],
                "backgroundColor": colors,
            }
        ]

        for depart_total, depart in zip(department_total, department):
            if depart == depart_total["department"]:
                dataset[0]["data"].append(depart_total["amount"])

        response = {
            "dataset": dataset,
            "labels": department,
            "department_total": department_total,
            "message": _("No payslips generated for this month."),
        }
        return JsonResponse(response)


def contract_ending(request):
    """
    payroll dashboard contract ending details data
    """

    date = request.GET.get("period")
    month = date.split("-")[1]
    year = date.split("-")[0]

    if request.GET.get("initialLoad") == "true":
        if month == "12":
            month = 0
            year = int(year) + 1

        contract_end = Contract.objects.filter(
            contract_end_date__month=int(month) + 1, contract_end_date__year=int(year)
        )
    else:
        contract_end = Contract.objects.filter(
            contract_end_date__month=int(month), contract_end_date__year=int(year)
        )

    ending_contract = []
    for contract in contract_end:
        ending_contract.append(
            {"contract_name": contract.contract_name, "contract_id": contract.id}
        )

    response = {
        "contract_end": ending_contract,
        "message": _("No contracts ending this month"),
    }
    return JsonResponse(response)


def payslip_export(request):
    """
    payroll dashboard exporting to excell data

    Args:
    - request (HttpRequest): The HTTP request object.
    - contract_id (int): The ID of the contract to view.

    """

    start_date = request.POST.get("start_date")
    end_date = request.POST.get("end_date")
    employee = request.POST.getlist("employees")
    status = request.POST.get("status")
    contributions = (
        request.POST.getlist("contributions")
        if request.POST.getlist("contributions")
        else get_active_employees(None)["get_active_employees"].values_list(
            "id", flat=True
        )
    )
    department = []
    total_amount = 0

    table1_data = []
    table2_data = []
    table3_data = []
    table4_data = []
    table5_data = []

    employee_payslip_list = Payslip.objects.all()

    if start_date:
        employee_payslip_list = employee_payslip_list.filter(start_date__gte=start_date)

    if end_date:
        employee_payslip_list = employee_payslip_list.filter(end_date__lte=end_date)

    if employee:
        employee_payslip_list = employee_payslip_list.filter(employee_id__in=employee)

    if status:
        employee_payslip_list = employee_payslip_list.filter(status=status)

    for employ in contributions:
        payslips = Payslip.objects.filter(employee_id__id=employ)
        if end_date:
            payslips = Payslip.objects.filter(
                employee_id__id=employ, end_date__lte=end_date
            )
        if start_date:
            payslips = Payslip.objects.filter(
                employee_id__id=employ, start_date__gte=start_date
            )
            if end_date:
                payslips = payslips.filter(end_date__lte=end_date)
        pay_heads = payslips.values_list("pay_head_data", flat=True)
        # contribution_deductions = []
        deductions = []
        for head in pay_heads:
            for deduction in head["gross_pay_deductions"]:
                if deduction.get("deduction_id"):
                    deductions.append(deduction)
            for deduction in head["basic_pay_deductions"]:
                if deduction.get("deduction_id"):
                    deductions.append(deduction)
            for deduction in head["pretax_deductions"]:
                if deduction.get("deduction_id"):
                    deductions.append(deduction)
            for deduction in head["post_tax_deductions"]:
                if deduction.get("deduction_id"):
                    deductions.append(deduction)
            for deduction in head["tax_deductions"]:
                if deduction.get("deduction_id"):
                    deductions.append(deduction)
            for deduction in head["net_deductions"]:
                deductions.append(deduction)

        deductions.sort(key=lambda x: x["deduction_id"])
        grouped_deductions = {
            key: list(group)
            for key, group in groupby(deductions, key=lambda x: x["deduction_id"])
        }

        for deduction_id, group in grouped_deductions.items():
            employee_contribution = sum(item["amount"] for item in group)
            try:
                employer_contribution = sum(
                    item["employer_contribution_amount"] for item in group
                )
            except:
                employer_contribution = 0
            if employer_contribution > 0:
                table5_data.append(
                    {
                        "Employee": Employee.objects.get(id=employ),
                        "Employer Contribution": employer_contribution,
                        "Employee Contribution": employee_contribution,
                    }
                )

    emp = request.user.employee_get
    if employee_payslip_list:
        for payslip in employee_payslip_list:
            # Taking the company_name of the user
            info = EmployeeWorkInformation.objects.filter(employee_id=emp).first()

            if info:
                employee_company = info.company_id
                company_name = Company.objects.filter(company=employee_company).first()
                date_format = (
                    company_name.date_format
                    if company_name and company_name.date_format
                    else "MMM. D, YYYY"
                )
            else:
                date_format = "MMM. D, YYYY"

            start_date_str = str(payslip.start_date)
            end_date_str = str(payslip.end_date)

            # Convert the string to a datetime.date object
            start_date = datetime.strptime(start_date_str, "%Y-%m-%d").date()
            end_date = datetime.strptime(end_date_str, "%Y-%m-%d").date()

            for format_name, format_string in HORILLA_DATE_FORMATS.items():
                if format_name == date_format:
                    formatted_start_date = start_date.strftime(format_string)

            for format_name, format_string in HORILLA_DATE_FORMATS.items():
                if format_name == date_format:
                    formatted_end_date = end_date.strftime(format_string)

            table1_data.append(
                {
                    "employee": f"{payslip.employee_id.employee_first_name} {payslip.employee_id.employee_last_name}",
                    "start_date": formatted_start_date,
                    "end_date": formatted_end_date,
                    "basic_pay": round(payslip.basic_pay, 2),
                    "deduction": round(payslip.deduction, 2),
                    "allowance": round(payslip.gross_pay - payslip.basic_pay, 2),
                    "gross_pay": round(payslip.gross_pay, 2),
                    "net_pay": round(payslip.net_pay, 2),
                    "status": status_choices.get(payslip.status),
                },
            )
    else:
        table1_data.append(
            {
                "employee": "None",
                "start_date": "None",
                "end_date": "None",
                "basic_pay": "None",
                "deduction": "None",
                "allowance": "None",
                "gross_pay": "None",
                "net_pay": "None",
                "status": "None",
            },
        )

    for employee in employee_payslip_list:
        department.append(
            employee.employee_id.employee_work_info.department_id.department
        )

    department = list(set(department))

    for depart in department:
        table2_data.append({"Department": depart, "Amount": 0})

    for employee in employee_payslip_list:
        employee_department = (
            employee.employee_id.employee_work_info.department_id.department
        )

        for depart in table2_data:
            if depart["Department"] == employee_department:
                depart["Amount"] += round(employee.net_pay, 2)

    if not employee_payslip_list:
        table2_data.append({"Department": "None", "Amount": 0})

    contract_end = Contract.objects.all()
    if not start_date and not end_date:
        contract_end = contract_end.filter(
            Q(contract_end_date__month=datetime.now().month)
            & Q(contract_end_date__year=datetime.now().year)
        )
    if end_date:
        contract_end = contract_end.filter(contract_end_date__lte=end_date)

    if start_date:
        if not end_date:
            contract_end = contract_end.filter(
                Q(contract_end_date__gte=start_date)
                & Q(contract_end_date__lte=datetime.now())
            )
        else:
            contract_end = contract_end.filter(contract_end_date__gte=start_date)

    table3_data = {"contract_ending": []}

    for contract in contract_end:
        table3_data["contract_ending"].append(contract.contract_name)

    if not contract_end:
        table3_data["contract_ending"].append("None")

    for employee in employee_payslip_list:
        total_amount += round(employee.net_pay, 2)

    table4_data = {
        "no_of_payslip_generated": len(employee_payslip_list),
        "total_amount": [total_amount],
    }

    df_table1 = pd.DataFrame(table1_data)
    df_table2 = pd.DataFrame(table2_data)
    df_table3 = pd.DataFrame(table3_data)
    df_table4 = pd.DataFrame(table4_data)
    df_table5 = pd.DataFrame(table5_data)

    df_table1 = df_table1.rename(
        columns={
            "employee": "Employee",
            "start_date": "Start Date",
            "end_date": "End Date",
            "deduction": "Deduction",
            "allowance": "Allowance",
            "gross_pay": "Gross Pay",
            "net_pay": "Net Pay",
            "status": "Status",
        }
    )

    df_table3 = df_table3.rename(
        columns={
            "contract_ending": (
                f"Contract Ending {start_date} to {end_date}"
                if start_date and end_date
                else f"Contract Ending"
            ),
        }
    )

    df_table4 = df_table4.rename(
        columns={
            "no_of_payslip_generated": "Number of payslips generated",
            "total_amount": "Total Amount",
        }
    )

    df_table5 = df_table5.rename(
        columns={
            "contract_ending": (
                f"Employee - Employer Contributions {start_date} to {end_date}"
                if start_date and end_date
                else f"Contract Ending"
            ),
        }
    )

    response = HttpResponse(
        content_type="application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"
    )
    response["Content-Disposition"] = "attachment; filename=payslip.xlsx"

    writer = pd.ExcelWriter(response, engine="xlsxwriter")
    df_table1.to_excel(
        writer, sheet_name="Payroll Dashboard details", index=False, startrow=3
    )
    df_table2.to_excel(
        writer,
        sheet_name="Payroll Dashboard details",
        index=False,
        startrow=len(df_table1) + 3 + 3,
    )
    df_table3.to_excel(
        writer,
        sheet_name="Payroll Dashboard details",
        index=False,
        startrow=len(df_table1) + 3 + len(df_table2) + 6,
    )
    df_table5.to_excel(
        writer,
        sheet_name="Payroll Dashboard details",
        index=False,
        startrow=len(df_table1) + 3 + len(df_table2) + len(df_table3) + 9,
    )
    df_table4.to_excel(
        writer,
        sheet_name="Payroll Dashboard details",
        index=False,
        startrow=len(df_table1)
        + 3
        + len(df_table2)
        + len(df_table3)
        + len(df_table5)
        + 12,
    )

    workbook = writer.book
    worksheet = writer.sheets["Payroll Dashboard details"]
    max_columns = max(
        len(df_table1.columns),
        len(df_table2.columns),
        len(df_table3.columns),
        len(df_table4.columns),
        len(df_table5.columns),
    )

    heading_format = workbook.add_format(
        {
            "bold": True,
            "font_size": 14,
            "align": "center",
            "valign": "vcenter",
            "bg_color": "#eb7968",
            "font_size": 20,
        }
    )

    worksheet.set_row(0, 30)
    worksheet.merge_range(
        0,
        0,
        0,
        max_columns - 1,
        (
            f"Payroll details {start_date} to {end_date}"
            if start_date and end_date
            else f"Payroll details"
        ),
        heading_format,
    )

    header_format = workbook.add_format(
        {"bg_color": "#eb7968", "bold": True, "text_wrap": True}
    )

    for col_num, value in enumerate(df_table1.columns.values):
        worksheet.write(3, col_num, value, header_format)
        col_letter = chr(65 + col_num)

        header_width = max(len(value) + 2, len(df_table1[value].astype(str).max()) + 2)
        worksheet.set_column(f"{col_letter}:{col_letter}", header_width)

    for col_num, value in enumerate(df_table2.columns.values):
        worksheet.write(len(df_table1) + 3 + 3, col_num, value, header_format)
        col_letter = chr(65 + col_num)

        header_width = max(len(value) + 2, len(df_table2[value].astype(str).max()) + 2)
        worksheet.set_column(f"{col_letter}:{col_letter}", header_width)

    for col_num, value in enumerate(df_table3.columns.values):
        worksheet.write(
            len(df_table1) + 3 + len(df_table2) + 6, col_num, value, header_format
        )
        col_letter = chr(65 + col_num)

        header_width = max(len(value) + 2, len(df_table3[value].astype(str).max()) + 2)
        worksheet.set_column(f"{col_letter}:{col_letter}", header_width)

    for col_num, value in enumerate(df_table5.columns.values):
        worksheet.write(
            len(df_table1) + 3 + len(df_table2) + len(df_table3) + 9,
            col_num,
            value,
            header_format,
        )
        col_letter = chr(65 + col_num)

    for col_num, value in enumerate(df_table4.columns.values):
        worksheet.write(
            len(df_table1) + 3 + len(df_table2) + len(df_table3) + len(df_table5) + 12,
            col_num,
            value,
            header_format,
        )
        col_letter = chr(65 + col_num)

        header_width = max(len(value) + 2, len(df_table4[value].astype(str).max()) + 2)
        worksheet.set_column(f"{col_letter}:{col_letter}", header_width)

    worksheet.set_row(len(df_table1) + len(df_table2) + 9, 30)

    writer.close()

    return response


@login_required
@permission_required("payroll.delete_payslip")
def payslip_bulk_delete(request):
    """
    This method is used to bulk delete for Payslip
    """
    ids = request.POST["ids"]
    ids = json.loads(ids)
    for id in ids:
        try:
            payslip = Payslip.objects.get(id=id)
            period = f"{payslip.start_date} to {payslip.end_date}"
            payslip.delete()
            messages.success(
                request,
                _("{employee} {period} payslip deleted.").format(
                    employee=payslip.employee_id, period=period
                ),
            )
        except Payslip.DoesNotExist:
            messages.error(request, _("Payslip not found."))
        except ProtectedError:
            messages.error(
                request,
                _("You cannot delete {payslip}").format(payslip=payslip),
            )
    return JsonResponse({"message": "Success"})


@login_required
@permission_required("payroll.change_payslip")
def slip_group_name_update(request):
    """
    This method is used to update the group of the payslip
    """
    new_name = request.POST["newName"]
    group_name = request.POST["previousName"]
    Payslip.objects.filter(group_name=group_name).update(group_name=new_name)
    return JsonResponse(
        {"type": "success", "message": "Batch name updated.", "new_name": new_name}
    )


@login_required
@permission_required("payroll.add_contract")
def contract_export(request):
    hx_request = request.META.get("HTTP_HX_REQUEST")
    if hx_request:
        export_filter = ContractFilter()
        export_column = ContractExportFieldForm()
        content = {
            "export_filter": export_filter,
            "export_column": export_column,
        }
        return render(
            request,
            "payroll/contract/contract_export_filter.html",
            context=content,
        )
    return export_data(
        request=request,
        model=Contract,
        filter_class=ContractFilter,
        form_class=ContractExportFieldForm,
        file_name="Contract_export",
    )


@login_required
@permission_required("payroll.delete_contract")
def contract_bulk_delete(request):
    """
    This method is used to bulk delete Contract
    """
    ids = request.POST["ids"]
    ids = json.loads(ids)
    for id in ids:
        try:
            contract = Contract.objects.get(id=id)
            name = f"{contract.contract_name}"
            contract.delete()
            messages.success(
                request,
                _("{name} deleted.").format(name=name),
            )
        except Payslip.DoesNotExist:
            messages.error(request, _("Contract not found."))
        except ProtectedError:
            messages.error(
                request,
                _("You cannot delete {contract}").format(contract=contract),
            )
    return JsonResponse({"message": "Success"})


def equalize_lists_length(allowances, deductions):
    """
    Equalize the lengths of two lists by appending empty dictionaries to the shorter list.

    Args:
    deductions (list): List of dictionaries representing deductions.
    allowances (list): List of dictionaries representing allowances.

    Returns:
    tuple: Tuple containing two lists with equal lengths.
    """
    num_deductions = len(deductions)
    num_allowances = len(allowances)

    while num_deductions < num_allowances:
        deductions.append({"title": "", "amount": ""})
        num_deductions += 1

    while num_allowances < num_deductions:
        allowances.append({"title": "", "amount": ""})
        num_allowances += 1

    return deductions, allowances


def generate_payslip_pdf(template_path, context, html=False):
    """
    Generate a PDF file from an HTML template and context data.

    Args:
        template_path (str): The path to the HTML template.
        context (dict): The context data to render the template.
        html (bool): If True, return raw HTML instead of a PDF.

    Returns:
        HttpResponse: A response with the generated PDF file or raw HTML.
    """
    try:
        # Render the HTML content from the template and context
        html_content = render_to_string(template_path, context)

        # Return raw HTML if requested
        if html:
            return HttpResponse(html_content, content_type="text/html")

        # PDF options for pdfkit
        pdf_options = {
            "page-size": "A4",
            "margin-top": "10mm",
            "margin-bottom": "10mm",
            "margin-left": "10mm",
            "margin-right": "10mm",
            "encoding": "UTF-8",
            "enable-local-file-access": None,  # Required to load local CSS/images
        }

        # Generate the PDF as binary content
        pdf = pdfkit.from_string(html_content, False, options=pdf_options)

        # Return an HttpResponse containing the PDF content
        response = HttpResponse(pdf, content_type="application/pdf")
        response["Content-Disposition"] = "inline; filename=payslip.pdf"
        return response
    except Exception as e:
        # Handle errors gracefully
        return HttpResponse(f"Error generating PDF: {str(e)}", status=500)


def payslip_pdf(request, id):
    """
    Generate the payslip as a PDF and return it in an HttpResponse.

    Args:
        request (HttpRequest): The request object.
        id (int): The ID of the payslip to generate.

    Returns:
        HttpResponse: A response containing the PDF content.
    """

    from .component_views import filter_payslip

    if Payslip.objects.filter(id=id).exists():
        payslip = Payslip.objects.get(id=id)
        company = Company.objects.filter(hq=True).first()
        if (
            request.user.has_perm("payroll.view_payslip")
            or payslip.employee_id.employee_user_id == request.user
        ):
            user = request.user
            employee = user.employee_get

            # Taking the company_name of the user
            info = EmployeeWorkInformation.objects.filter(employee_id=employee)
            if info.exists():
                for data in info:
                    employee_company = data.company_id
                company_name = Company.objects.filter(company=employee_company)
                emp_company = company_name.first()

                # Access the date_format attribute directly
                date_format = (
                    emp_company.date_format
                    if emp_company and emp_company.date_format
                    else "MMM. D, YYYY"
                )

            data = payslip.pay_head_data
            start_date_str = data["start_date"]
            end_date_str = data["end_date"]

            # Convert the string to a datetime.date object
            start_date = datetime.strptime(start_date_str, "%Y-%m-%d").date()
            end_date = datetime.strptime(end_date_str, "%Y-%m-%d").date()

            # Format the start and end dates
            for format_name, format_string in HORILLA_DATE_FORMATS.items():
                if format_name == date_format:
                    formatted_start_date = start_date.strftime(format_string)
                    formatted_end_date = end_date.strftime(format_string)

            # Prepare context for the template
            data.update(
                {
                    "month_start_name": start_date.strftime("%B %d, %Y"),
                    "month_end_name": end_date.strftime("%B %d, %Y"),
                    "formatted_start_date": formatted_start_date,
                    "formatted_end_date": formatted_end_date,
                    "employee": payslip.employee_id,
                    "payslip": payslip,
                    "json_data": data.copy(),
                    "currency": PayrollSettings.objects.first().currency_symbol,
                    "all_deductions": [],
                    "all_allowances": data["allowances"].copy(),
                    "host": request.get_host(),
                    "protocol": "https" if request.is_secure() else "http",
                    "company": company,
                }
            )

            # Merge deductions and allowances for display
            for deduction_list in [
                data["basic_pay_deductions"],
                data["gross_pay_deductions"],
                data["pretax_deductions"],
                data["post_tax_deductions"],
                data["tax_deductions"],
                data["net_deductions"],
            ]:
                data["all_deductions"].extend(deduction_list)

            equalize_lists_length(data["allowances"], data["all_deductions"])
            data["zipped_data"] = zip(data["allowances"], data["all_deductions"])
            template_path = "payroll/payslip/payslip_pdf.html"

            return generate_payslip_pdf(template_path, context=data, html=False)
        return redirect(filter_payslip)
    return render(request, "405.html")


@login_required
@permission_required("payroll.view_contract")
def contract_select(request):
    page_number = request.GET.get("page")

    if page_number == "all":
        employees = Contract.objects.all()

    contract_ids = [str(emp.id) for emp in employees]
    total_count = employees.count()

    context = {"contract_ids": contract_ids, "total_count": total_count}

    return JsonResponse(context, safe=False)


@login_required
def contract_select_filter(request):
    page_number = request.GET.get("page")
    filtered = request.GET.get("filter")
    filters = json.loads(filtered) if filtered else {}

    if page_number == "all":
        contract_filter = ContractFilter(filters, queryset=Contract.objects.all())

        # Get the filtered queryset
        filtered_employees = contract_filter.qs

        contract_ids = [str(emp.id) for emp in filtered_employees]
        total_count = filtered_employees.count()

        context = {"contract_ids": contract_ids, "total_count": total_count}

        return JsonResponse(context)


@login_required
def payslip_select(request):
    page_number = request.GET.get("page")

    if page_number == "all":
        if request.user.has_perm("payroll.view_payslip"):
            employees = Payslip.objects.all()
        else:
            employees = Payslip.objects.filter(
                employee_id__employee_user_id=request.user
            )

    payslip_ids = [str(emp.id) for emp in employees]
    total_count = employees.count()

    context = {"payslip_ids": payslip_ids, "total_count": total_count}

    return JsonResponse(context, safe=False)


@login_required
def payslip_select_filter(request):
    page_number = request.GET.get("page")
    filtered = request.GET.get("filter")
    filters = json.loads(filtered) if filtered else {}

    if page_number == "all":
        payslip_filter = PayslipFilter(filters, queryset=Payslip.objects.all())

        # Get the filtered queryset
        filtered_employees = payslip_filter.qs

        payslip_ids = [str(emp.id) for emp in filtered_employees]
        total_count = filtered_employees.count()

        context = {"payslip_ids": payslip_ids, "total_count": total_count}

        return JsonResponse(context)


@login_required
def create_payrollrequest_comment(request, payroll_id):
    """
    This method renders form and template to create Reimbursement request comments
    """
    from payroll.forms.forms import ReimbursementRequestCommentForm

    payroll = Reimbursement.objects.filter(id=payroll_id).first()
    emp = request.user.employee_get
    form = ReimbursementRequestCommentForm(
        initial={"employee_id": emp.id, "request_id": payroll_id}
    )

    if request.method == "POST":
        form = ReimbursementRequestCommentForm(request.POST)
        if form.is_valid():
            form.instance.employee_id = emp
            form.instance.request_id = payroll
            form.save()
            comments = ReimbursementrequestComment.objects.filter(
                request_id=payroll_id
            ).order_by("-created_at")
            no_comments = False
            if not comments.exists():
                no_comments = True
            form = ReimbursementRequestCommentForm(
                initial={"employee_id": emp.id, "request_id": payroll_id}
            )
            messages.success(request, _("Comment added successfully!"))

            if payroll.employee_id.employee_work_info.reporting_manager_id is not None:

                if request.user.employee_get.id == payroll.employee_id.id:
                    rec = (
                        payroll.employee_id.employee_work_info.reporting_manager_id.employee_user_id
                    )
                    notify.send(
                        request.user.employee_get,
                        recipient=rec,
                        verb=f"{payroll.employee_id}'s reimbursement request has received a comment.",
                        verb_ar=f"تلقى طلب استرداد نفقات {payroll.employee_id} تعليقًا.",
                        verb_de=f"{payroll.employee_id}s Rückerstattungsantrag hat einen Kommentar erhalten.",
                        verb_es=f"La solicitud de reembolso de gastos de {payroll.employee_id} ha recibido un comentario.",
                        verb_fr=f"La demande de remboursement de frais de {payroll.employee_id} a reçu un commentaire.",
                        redirect=reverse("view-reimbursement"),
                        icon="chatbox-ellipses",
                    )
                elif (
                    request.user.employee_get.id
                    == payroll.employee_id.employee_work_info.reporting_manager_id.id
                ):
                    rec = payroll.employee_id.employee_user_id
                    notify.send(
                        request.user.employee_get,
                        recipient=rec,
                        verb="Your reimbursement request has received a comment.",
                        verb_ar="تلقى طلب استرداد نفقاتك تعليقًا.",
                        verb_de="Ihr Rückerstattungsantrag hat einen Kommentar erhalten.",
                        verb_es="Tu solicitud de reembolso ha recibido un comentario.",
                        verb_fr="Votre demande de remboursement a reçu un commentaire.",
                        redirect=reverse("view-reimbursement"),
                        icon="chatbox-ellipses",
                    )
                else:
                    rec = [
                        payroll.employee_id.employee_user_id,
                        payroll.employee_id.employee_work_info.reporting_manager_id.employee_user_id,
                    ]
                    notify.send(
                        request.user.employee_get,
                        recipient=rec,
                        verb=f"{payroll.employee_id}'s reimbursement request has received a comment.",
                        verb_ar=f"تلقى طلب استرداد نفقات {payroll.employee_id} تعليقًا.",
                        verb_de=f"{payroll.employee_id}s Rückerstattungsantrag hat einen Kommentar erhalten.",
                        verb_es=f"La solicitud de reembolso de gastos de {payroll.employee_id} ha recibido un comentario.",
                        verb_fr=f"La demande de remboursement de frais de {payroll.employee_id} a reçu un commentaire.",
                        redirect=reverse("view-reimbursement"),
                        icon="chatbox-ellipses",
                    )
            else:
                rec = payroll.employee_id.employee_user_id
                notify.send(
                    request.user.employee_get,
                    recipient=rec,
                    verb="Your reimbursement request has received a comment.",
                    verb_ar="تلقى طلب استرداد نفقاتك تعليقًا.",
                    verb_de="Ihr Rückerstattungsantrag hat einen Kommentar erhalten.",
                    verb_es="Tu solicitud de reembolso ha recibido un comentario.",
                    verb_fr="Votre demande de remboursement a reçu un commentaire.",
                    redirect=reverse("view-reimbursement"),
                    icon="chatbox-ellipses",
                )

            return render(
                request,
                "payroll/reimbursement/reimbursement_comment.html",
                {
                    "comments": comments,
                    "no_comments": no_comments,
                    "request_id": payroll_id,
                },
            )
    return render(
        request,
        "payroll/reimbursement/reimbursement_comment.html",
        {"form": form, "request_id": payroll_id},
    )


@login_required
@hx_request_required
def view_payrollrequest_comment(request, payroll_id):
    """
    This method is used to show Reimbursement request comments
    """
    comments = ReimbursementrequestComment.objects.filter(
        request_id=payroll_id
    ).order_by("-created_at")

    req = Reimbursement.objects.get(id=payroll_id)
    no_comments = False
    if not comments.exists():
        no_comments = True

    if request.FILES:
        files = request.FILES.getlist("files")
        comment_id = request.GET["comment_id"]
        comment = ReimbursementrequestComment.objects.get(id=comment_id)
        attachments = []
        for file in files:
            file_instance = ReimbursementFile()
            file_instance.file = file
            file_instance.save()
            attachments.append(file_instance)
        comment.files.add(*attachments)
    return render(
        request,
        "payroll/reimbursement/reimbursement_comment.html",
        {
            "comments": comments,
            "no_comments": no_comments,
            "request_id": payroll_id,
            "req": req,
        },
    )


@login_required
def delete_payrollrequest_comment(request, comment_id):
    """
    This method is used to delete Reimbursement request comments
    """
    script = ""
    comment = ReimbursementrequestComment.objects.filter(id=comment_id)
    comment.delete()
    messages.success(request, _("Comment deleted successfully!"))
    return HttpResponse(script)


@login_required
def delete_reimbursement_comment_file(request):
    """
    Used to delete attachment
    """
    script = ""
    ids = request.GET.getlist("ids")
    records = ReimbursementFile.objects.filter(id__in=ids)
    if not request.user.has_perm("payroll.delete_reimbursmentfile"):
        records = records.filter(employee_id__employee_user_id=request.user)
    records.delete()
    messages.success(request, _("File deleted successfully"))
    return HttpResponse(script)


@login_required
@permission_required("payroll.add_payrollgeneralsetting")
def initial_notice_period(request):
    """
    This method is used to set initial value notice period
    """
    notice_period = eval_validate(request.GET["notice_period"])
    settings = PayrollGeneralSetting.objects.first()
    settings = settings if settings else PayrollGeneralSetting()
    settings.notice_period = max(notice_period, 0)
    settings.save()
    messages.success(
        request, _("The initial notice period has been successfully updated.")
    )
    if request.META.get("HTTP_HX_REQUEST"):
        return HttpResponse()
    return HttpResponseRedirect(request.META.get("HTTP_REFERER", "/"))


# ===========================Auto payslip generate================================


@login_required
@permission_required("payroll.view_PayslipAutoGenerate")
def auto_payslip_settings_view(request):
    payslip_auto_generate = PayslipAutoGenerate.objects.all()

    context = {"payslip_auto_generate": payslip_auto_generate}
    return render(request, "payroll/settings/auto_payslip_settings.html", context)


@login_required
@hx_request_required
@permission_required("payroll.change_PayslipAutoGenerate")
def create_or_update_auto_payslip(request, auto_id=None):
    auto_payslip = None
    if auto_id:
        auto_payslip = PayslipAutoGenerate.objects.get(id=auto_id)
    form = PayslipAutoGenerateForm(instance=auto_payslip)
    if request.method == "POST":
        form = PayslipAutoGenerateForm(request.POST, instance=auto_payslip)
        if form.is_valid():
            auto_payslip = form.save()
            company = (
                auto_payslip.company_id if auto_payslip.company_id else "All company"
            )
            messages.success(
                request, _(f"Payslip Auto generate for {company} created successfully ")
            )
            return HttpResponse("<script>window.location.reload()</script>")
    return render(
        request, "payroll/settings/auto_payslip_create_or_update.html", {"form": form}
    )


@login_required
@permission_required("payroll.change_PayslipAutoGenerate")
def activate_auto_payslip_generate(request):
    """
    ajax function to update is active field in PayslipAutoGenerate.
    Args:
    - isChecked: Boolean value representing the state of PayslipAutoGenerate,
    - autoId: Id of PayslipAutoGenerate object
    """
    isChecked = request.POST.get("isChecked")
    autoId = request.POST.get("autoId")
    payslip_auto = PayslipAutoGenerate.objects.get(id=autoId)
    if isChecked == "true":
        payslip_auto.auto_generate = True
        response = {
            "type": "success",
            "message": _("Auto paslip generate activated successfully."),
        }
    else:
        payslip_auto.auto_generate = False
        response = {
            "type": "success",
            "message": _("Auto paslip generate deactivated successfully."),
        }
    payslip_auto.save()
    return JsonResponse(response)


@login_required
@hx_request_required
@permission_required("payroll.delete_PayslipAutoGenerate")
def delete_auto_payslip(request, auto_id):
    """
    Delete a PayslipAutoGenerate object.

    Args:
        auto_id: The ID of PayslipAutoGenerate object to delete.

    Returns:
        Redirects to the contract view after successfully deleting the contract.

    """
    try:
        auto_payslip = PayslipAutoGenerate.objects.get(id=auto_id)
        if not auto_payslip.auto_generate:
            company = (
                auto_payslip.company_id if auto_payslip.company_id else "All company"
            )
            auto_payslip.delete()
            messages.success(
                request, _(f"Payslip auto generate for {company} deleted successfully.")
            )
        else:
            messages.info(request, _(f"Active 'Payslip auto generate' cannot delete."))
        return HttpResponse("<script>window.location.reload();</script>")
    except PayslipAutoGenerate.DoesNotExist:
        messages.error(request, _("Payslip auto generate not found."))
    return HttpResponseRedirect(request.META.get("HTTP_REFERER", "/"))
