import pandas as pd
from django.db.models import Q
from payrollservice.data.response.empadvancepaymentresponse import EmployeeadvancepaymentResponse
from payrollservice.models import Employeeadvancepayment
from payrollservice.service.auditservice import AudtiService
from payrollservice.util.payrollutil import Activestatus, ModifyStatus, Advancetype
from utilityservice.data.response.nwisefinerror import NWisefinError
from utilityservice.data.response.nwisefinerrorconstants import ErrorMessage, ErrorDescription
from utilityservice.data.response.nwisefinlist import NWisefinList
from utilityservice.data.response.nwisefinpaginator import NWisefinPaginator
from utilityservice.data.response.nwisefinsuccess import NWisefinSuccess, SuccessMessage, SuccessStatus
from utilityservice.service.applicationconstants import ApplicationNamespace
from utilityservice.service.threadlocal import NWisefinThread
from django.utils import timezone

class EmployeeadvancepaymentService(NWisefinThread):
    def __init__(self, scope):
        super().__init__(scope)
        self._set_namespace(ApplicationNamespace.PAYROLL_SERVICE)

    def create_employeeadvance_payment(self, pay_obj, user_id):
        success_obj = NWisefinSuccess()
        if not pay_obj.get_id() is None:
            obj = Employeeadvancepayment.objects.using(self._current_app_schema()).filter(id=pay_obj.get_id()).update(
                                                                                    advance_id=pay_obj.get_advance_id(),
                                                                                    paid_date=pay_obj.get_paid_date(),
                                                                                    balance_amount=pay_obj.get_balance_amount(),
                                                                                    paid_amount=pay_obj.get_paid_amount(),
                                                                                    updated_date=timezone.now(),
                                                                                    updated_by=user_id)

            obj = Employeeadvancepayment.objects.using(self._current_app_schema()).get(id=pay_obj.get_id())
            audit_insert_data = AudtiService(self._scope()).audit_function(obj, obj.id,
                                                                           user_id,
                                                                           Advancetype.employeeadvance_payment,
                                                                           ModifyStatus.UPDATE)
            success_obj.set_message(SuccessMessage.UPDATE_MESSAGE)

        else:
            obj = Employeeadvancepayment.objects.using(self._current_app_schema()).create(advance_id=pay_obj.get_advance_id(),
                                                                                paid_date=pay_obj.get_paid_date(),
                                                                                balance_amount=pay_obj.get_balance_amount(),
                                                                                paid_amount=pay_obj.get_paid_amount(),
                                                                                created_by=user_id)
            audit_insert_data = AudtiService(self._scope()).audit_function(obj, obj.id, user_id,
                                                                           Advancetype.employeeadvance_payment,
                                                                           ModifyStatus.CREATE)

            success_obj.set_message(SuccessMessage.CREATE_MESSAGE)
        return success_obj


    def employeeadvance_payment_summary(self, vys_page):
        condition = Q(status=Activestatus.active)
        empadv_obj = Employeeadvancepayment.objects.using(self._current_app_schema()).filter(condition)[vys_page.get_offset():vys_page.get_query_limit()]
        list_data = NWisefinList()
        for i in empadv_obj:
            data_resp = EmployeeadvancepaymentResponse()
            data_resp.set_id(i.id)
            data_resp.set_advance_id(i.advance_id)
            data_resp.set_balance_amount(i.balance_amount)
            data_resp.set_paid_date(i.paid_date)
            data_resp.set_paid_amount(i.paid_amount)
            list_data.append(data_resp)
        vpage = NWisefinPaginator(empadv_obj, vys_page.get_index(), 10)
        list_data.set_pagination(vpage)
        return list_data


    def employeeadvance_payment_get(self, id):
        try:
            obj = Employeeadvancepayment.objects.using(self._current_app_schema()).get(status=Activestatus.active,id=id)
            data_resp = EmployeeadvancepaymentResponse()
            data_resp.set_id(obj.id)
            data_resp.set_advance_id(obj.advance_id)
            data_resp.set_balance_amount(obj.balance_amount)
            data_resp.set_paid_date(obj.paid_date)
            data_resp.set_paid_amount(obj.paid_amount)
            return data_resp
        except:
            error_obj = NWisefinError()
            error_obj.set_code(ErrorMessage.INVALID_ID)
            error_obj.set_description(ErrorDescription.INVALID_DATA)
            return error_obj


    def employeeadvance_payment_inactive(self, id):
        obj = Employeeadvancepayment.objects.using(self._current_app_schema()).filter(id=id).update(status=Activestatus.inactive)
        if obj == 0:
            error_obj = NWisefinError()
            error_obj.set_code(ErrorMessage.INVALID_ID)
            error_obj.set_description(ErrorDescription.INVALID)
            return error_obj
        else:
            success_obj = NWisefinSuccess()
            success_obj.set_status(SuccessStatus.SUCCESS)
            success_obj.set_message(SuccessMessage.DELETE_MESSAGE)
            return success_obj


    def employeeadvance_payment_history(self,advance_id):
        condition = Q(status=Activestatus.active)
        empadv_obj = Employeeadvancepayment.objects.using(self._current_app_schema()).filter(condition, advance_id__in=[advance_id])
        list_data = NWisefinList()
        for i in empadv_obj:
            data_resp = EmployeeadvancepaymentResponse()
            data_resp.set_id(i.id)
            data_resp.set_advance_id(i.advance_id)
            data_resp.set_balance_amount(i.balance_amount)
            data_resp.set_paid_date(i.paid_date)
            data_resp.set_paid_amount(i.paid_amount)
            list_data.append(data_resp)
        return list_data

      
    def employee_amount_arr(self,emp_arr):
        obj = Employeeadvancepayment.objects.using(self._current_app_schema()).filter(advance_id__in=emp_arr)
        list_data = []
        for i in obj:
            data_resp = EmployeeadvancepaymentResponse()
            data_resp.set_id(i.id)
            data_resp.set_advance_id(i.advance_id)
            data_resp.set_balance_amount(i.balance_amount)
            data_resp.set_paid_date(i.paid_date)
            data_resp.set_paid_amount(i.paid_amount)
            list_data.append(data_resp)
        return list_data



    def balance_old_advance(self, advance_id):
        advan_obj = Employeeadvancepayment.objects.using(self._current_app_schema()).filter(status=Activestatus.active, advance_id=advance_id).values('balance_amount').last()
        return advan_obj

    def emi_old_advance(self, advance_id):
        advan_obj = Employeeadvancepayment.objects.using(self._current_app_schema()).filter(status=Activestatus.active, advance_id=advance_id).values('paid_amount').first()
        return advan_obj

    def balance_old_advance1(self, id_data):
        advan_obj = Employeeadvancepayment.objects.using(self._current_app_schema()).filter(status=Activestatus.active, advance_id__in=id_data)
        if advan_obj.count() > 0:
            advan_df = pd.DataFrame(advan_obj.values('advance_id','balance_amount','paid_amount'))
            # last_balances = advan_df.groupby('advance_id')['balance_amount','paid_amount'].last()
            last_balances=advan_df.groupby('advance_id').agg({'balance_amount': 'last', 'paid_amount': 'last'})
            # Calculate the sum of the last balance_amount for each advance_id
            sum_last_balances = last_balances.sum()
            return sum_last_balances

    def emi_close(self,data_json, user_id):
        success_obj = NWisefinSuccess()
        advan_obj = Employeeadvancepayment.objects.using(self._current_app_schema()).filter(status=Activestatus.active, advance_id=data_json['id'])
        if advan_obj.count()>0:
            last_advance = advan_obj.last()
            update = Employeeadvancepayment.objects.using(self._current_app_schema()).filter(id=last_advance.id).update(paid_amount=data_json['emi_paid'],balance_amount=data_json['emi_balance'],updated_by=user_id,updated_date=timezone.now())
            if update == 0:
                success_obj.code = 500
            else:
                success_obj.code = 200
                success_obj.set_status(SuccessStatus.SUCCESS)
                success_obj.set_message(SuccessMessage.UPDATE_MESSAGE)
        else:
            success_obj.code = 500
        return success_obj