import datetime
from django.db.models import Q, Max
from payrollservice.data.response.empadvancedetailsresponse import EmployeeadvancedetailsResponse
from payrollservice.data.response.payrolltranresponse import PayrolltranResponse
from payrollservice.models import Payrolltran, Employeeadvancedetails
from payrollservice.util.payrollutil import Activestatus, get_advance_type, Advancetype, Advancestatus, \
    net_pay_calc_str, data_roundup
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, SuccessStatus, SuccessMessage
from utilityservice.service.applicationconstants import ApplicationNamespace
from utilityservice.service.payroll_api_service import Payrollcommon_Apicall
from utilityservice.service.threadlocal import NWisefinThread
from django.utils import timezone

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

    def create_payrolltran(self, tran_obj, user_id, resp_obj, ref_type):
        success_obj = NWisefinSuccess()
        if not tran_obj.get_id() is None:
            # data = Payrolltran.objects.annotate(Max(F('ref_id'))).filter(ref_id=tran_obj.get_id()).values('id').last()
            data = Payrolltran.objects.filter(ref_id=tran_obj.get_id()).values('id').last()
            if data.count() > 0:
                obj_data = Payrolltran.objects.using(self._current_app_schema()).filter(id=data['id']).update(tran_date=timezone.now(), updated_date=timezone.now(), updated_by=user_id)
                if obj_data == 1:
                    obj = Payrolltran.objects.using(self._current_app_schema()).create(ref_type=ref_type,
                                                                               ref_id=resp_obj.id,
                                                                               tran_status=resp_obj.advance_status,
                                                                               tran_from=user_id,
                                                                               tran_to=tran_obj.get_tran_to(),
                                                                               from_date=resp_obj.from_date,
                                                                               remarks=resp_obj.reason,
                                                                               created_by=user_id)
                success_obj = NWisefinSuccess()
                success_obj.set_status(SuccessStatus.SUCCESS)
                success_obj.set_message(SuccessMessage.UPDATE_MESSAGE)
                return success_obj
            else:
                error_obj = NWisefinError()
                error_obj.set_code(ErrorMessage.INVALID_DATA)
                error_obj.set_description(ErrorDescription.INVALID)
                return error_obj
        else:
            obj = Payrolltran.objects.using(self._current_app_schema()).create(ref_type=ref_type,
                                                                                        ref_id=resp_obj.id,
                                                                                        tran_status=resp_obj.advance_status,
                                                                                        tran_from=user_id,
                                                                                        tran_to=tran_obj.get_tran_to(),
                                                                                        from_date=resp_obj.from_date,
                                                                                        # tran_date=tran_obj.get_tran_date(),
                                                                                        remarks=resp_obj.reason,
                                                                                        created_by=user_id)

            success_obj.set_message(SuccessMessage.CREATE_MESSAGE)
            return success_obj


    def payrolltran_summary(self,vys_page):
        condition = Q(status=Activestatus.active)
        payroll_obj = Payrolltran.objects.using(self._current_app_schema()).filter(condition)[ vys_page.get_offset():vys_page.get_query_limit()]
        list_data = NWisefinList()
        for i in payroll_obj:
            data_resp = PayrolltranResponse()
            data_resp.set_id(i.id)
            data_resp.set_ref_id(i.ref_id)
            data_resp.set_ref_type(i.ref_type)
            data_resp.set_tran_status(i.tran_status)
            data_resp.set_tran_from(i.tran_from)
            data_resp.set_tran_to(i.tran_to)
            data_resp.set_from_date(i.from_date)
            data_resp.set_tran_date(i.tran_date)
            data_resp.set_remarks(i.remarks)
            list_data.append(data_resp)
        vpage = NWisefinPaginator(payroll_obj, vys_page.get_index(), 10)
        list_data.set_pagination(vpage)
        return list_data



    def payrolltran_get(self, id_val):
        try:
            obj = Payrolltran.objects.using(self._current_app_schema()).get(status=Activestatus.active, id=id_val)
            data_resp = PayrolltranResponse()
            data_resp.set_id(obj.id)
            data_resp.set_ref_id(obj.ref_id)
            data_resp.set_ref_type(obj.ref_type)
            data_resp.set_tran_status(obj.tran_status)
            data_resp.set_tran_from(obj.tran_from)
            data_resp.set_tran_to(obj.tran_to)
            data_resp.set_from_date(obj.from_date)
            data_resp.set_tran_date(obj.tran_date)
            data_resp.set_remarks(obj.remarks)
            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 payrolltran_inactive(self, id_val):
        obj = Payrolltran.objects.using(self._current_app_schema()).filter(id=id_val).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 tran_history_data(self, ref_id_val):
        list_data = NWisefinList()
        try:
            obj = Payrolltran.objects.using(self._current_app_schema()).filter(status=Activestatus.active,ref_id=ref_id_val)
            emp_adv_id = Employeeadvancedetails.objects.using(self._current_app_schema()).get(status=Activestatus.active,id=ref_id_val)
            apifunction = Payrollcommon_Apicall(self._scope())
            emp_obj = apifunction.emp_info(emp_adv_id.employee_id)
            for i in obj:
                data_resp = EmployeeadvancedetailsResponse()
                data_resp.advance_employee = emp_obj.get('full_name')
                data_resp.ref_type = get_advance_type(i.ref_type)
                data_resp.actual_amount = data_roundup(emp_adv_id.actual_amount)
                data_resp.payable_amount = data_roundup(emp_adv_id.payable_amount)
                data_resp.emi_amount = net_pay_calc_str(emp_adv_id.emi_amount)
                data_resp.date = str(i.created_date.date())
                obj = apifunction.emp_info(i.tran_from)
                # obj = Employee.objects.using(self._current_app_schema()).get(id=i.tran_from)
                data_resp.tran_from = obj.get('full_name')
                if i.tran_to is not None:
                    obj_emp = apifunction.emp_info(i.tran_to)
                    data_resp.tran_to = obj_emp.get('full_name')
                else:
                    data_resp.tran_to = None
                data_resp.from_date = str(i.from_date)
                data_resp.tran_date = str(i.tran_date)
                data_resp.remarks = i.remarks
                data_resp.set_advance_status(i.tran_status)
                data_resp.ref_type = i.ref_type
                list_data.append(data_resp)
            return list_data
        except:
            return list_data

    def advance_approving_level_data(self, adv_id, hr_id, tran_status,tran_to,remarks):
        Success_obj = NWisefinSuccess()
        obj = Payrolltran.objects.using(self._current_app_schema()).filter(ref_id=adv_id).aggregate(Max('id'))
        cre_pay_tran = Payrolltran.objects.using(self._current_app_schema()).create(ref_id=adv_id, tran_from=hr_id,
                                                                                    tran_to=tran_to,
                                                                                    from_date=datetime.datetime.now(),
                                                                                    ref_type=Advancetype.employeeadvance_details,
                                                                                    tran_status=tran_status, remarks=remarks)
        val = Payrolltran.objects.using(self._current_app_schema()).filter(id=obj['id__max']).update(
            tran_date=datetime.datetime.now())
        obj_val = Employeeadvancedetails.objects.using(self._current_app_schema()).filter(id=adv_id).update(
            advance_status=tran_status)

        Success_obj.set_status(SuccessStatus.SUCCESS)
        return Success_obj


    def advance_approve_data(self, user_id,data_json):
        Success_obj = NWisefinSuccess()
        if data_json['to_employee_id'] is None or data_json['to_employee_id']=="":
            tran_to = user_id
        else:
            tran_to = data_json['to_employee_id']
        obj = Payrolltran.objects.using(self._current_app_schema()).filter(ref_id=data_json['advance_id']).aggregate(Max('id'))
        cre_pay_tran = Payrolltran.objects.using(self._current_app_schema()).create(ref_id=data_json['advance_id'], tran_from=user_id,
                                                                                    tran_to=tran_to,
                                                                                    from_date=datetime.datetime.now(),
                                                                                    ref_type=Advancetype.employeeadvance_details,
                                                                                    tran_status=data_json['advance_status'], remarks=data_json['remarks'])
        val = Payrolltran.objects.using(self._current_app_schema()).filter(id=obj['id__max']).update(tran_date=datetime.datetime.now())
        obj_val = Employeeadvancedetails.objects.using(self._current_app_schema()).filter(id=data_json['advance_id']).update(advance_status=data_json['advance_status'],updated_by=user_id,updated_date=datetime.datetime.now())
        Success_obj.set_status(SuccessStatus.SUCCESS)
        return Success_obj

    def advance_level_get(self, id, status):
        tran_data = Payrolltran.objects.using(self._current_app_schema()).filter(status=Activestatus.active, ref_id=id, tran_status=status)
        return tran_data