import json
# from masterservice.service.gradeservice import GradeService
from payrollservice.data.response.payrollmasterresponse import PaycomponentFlagmasterResponse
from payrollservice.data.response.payrolltemplateresponse import PayrollTemplateResponse
from payrollservice.models import PayrollTemplate, PaycomponentFlagmaster, Payrollmastersmapping
from payrollservice.service.paycomponentsegmentmappingservice import PayrollSegementMappingService
from payrollservice.service.payrollmastersservice import SegmentMasterService, EmployeePFService, \
    CompanyContributionService, payrollGradeService
from payrollservice.util.payrollutil import Activestatus, FlagRef_Type
from utilityservice.service.applicationconstants import ApplicationNamespace
from utilityservice.service.payroll_api_service import Payrollcommon_Apicall
from utilityservice.service.threadlocal import NWisefinThread
from utilityservice.data.response.nwisefinerror import NWisefinError
from utilityservice.data.response.nwisefinerrorconstants import ErrorDescription, ErrorMessage
from utilityservice.data.response.nwisefinsuccess import SuccessStatus,SuccessMessage,NWisefinSuccess
from django.db.models import Q
from utilityservice.data.response.nwisefinlist import NWisefinList
from utilityservice.data.response.nwisefinpaginator import NWisefinPaginator


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

    def create_payrolltemplate(self,data_obj,user_id):
        # var = PayrollTemplate.objects.using(self._current_app_schema()).filter(grade=data_obj.get_grade(),status=Activestatus.active).values_list('grade', flat=True)
        # arr1 = list(set(var))
        # if len(arr1) > 0:
        #     success_obj = NWisefinSuccess()
        #     success_obj.set_status("INVALID GRADE")
        #     success_obj.set_message("ALREADY EXISTS IN GRADE")
        #     return success_obj
        success_obj = NWisefinSuccess()
        if not data_obj.get_id() is None:
            obj = PayrollTemplate.objects.using(self._current_app_schema()).filter(id=data_obj.get_id()).update(name=data_obj.get_name(),
                                                                                                                grade=data_obj.get_grade(),created_by=user_id,
                                                                                                                glno=data_obj.get_glno())

            obj = PayrollTemplate.objects.using(self._current_app_schema()).get(id=data_obj.get_id())
            success_obj.set_message(SuccessMessage.UPDATE_MESSAGE)
            success_obj.set_status(SuccessStatus.SUCCESS)
            success_obj.id = obj.id

        else:
            obj = PayrollTemplate.objects.using(self._current_app_schema()).create(name=data_obj.get_name(),
                                                                                   grade=data_obj.get_grade(),
                                                                                   created_by=user_id,
                                                                                   entity_id=self._entity_id(),
                                                                                   glno=data_obj.get_glno())
            id_data = obj.id
            code_gen = 'TEMP'+str(id_data)
            obj.code = code_gen
            obj.save()
            success_obj.set_message(SuccessMessage.CREATE_MESSAGE)
            success_obj.set_status(SuccessStatus.SUCCESS)
            success_obj.code = code_gen
            success_obj.id = id_data

        return success_obj

    def payrolltemplate_summary(self, vys_page, request):
        condition = Q(status=Activestatus.active)
        name = request.GET.get('name')
        grade = request.GET.get('grade')
        if name is not None and name != '':
            condition &= Q(name__icontains=name)
        if grade is not None and grade != '':
            condition &= Q(grade=grade)
        obj = PayrollTemplate.objects.using(self._current_app_schema()).filter(condition)[vys_page.get_offset():vys_page.get_query_limit()]
        grade_id = [i.grade for i in obj]
        # grade_data = GradeService(self._scope()).get_grade_data_by_id(grade_id)
        grade_data = Payrollcommon_Apicall(self._scope()).get_grade_data_by_id(grade_id)
        list_data = NWisefinList()
        for i in obj:
            data_resp = PayrollTemplateResponse()
            data_resp.set_id(i.id)
            data_resp.set_name(i.name)
            # data_resp.set_grade(i.grade)
            data_resp.set_grade_data(i.grade, grade_data)
            flag_data = self.templateflagmastersummary([i.id], FlagRef_Type.PAYROLLTEMPLATE)
            data_resp.segment = flag_data
            data_resp.set_glno(i.glno)
            list_data.append(data_resp)
        v_page = NWisefinPaginator(obj, vys_page.get_index(), 10)
        list_data.set_pagination(v_page)
        return list_data

    def get_payrolltemplate_data(self, payrolltemplate_id):
        try:
            obj = PayrollTemplate.objects.using(self._current_app_schema()).get(status=Activestatus.active, id=payrolltemplate_id)
            data_resp = PayrollTemplateResponse()
            data_resp.set_id(obj.id)
            data_resp.set_name(obj.name)
            data_resp.set_glno(obj.glno)
            # grade_data = GradeService(self._scope()).get_grade(obj.grade)
            grade_data = Payrollcommon_Apicall(self._scope()).get_grade(obj.grade)
            data_resp.set_grade(grade_data)
            return data_resp
        except Exception as excep:
            obj = NWisefinError()
            obj.set_code(ErrorMessage.INVALID_DATA)
            obj.set_description(str(excep))
            return obj

    def inactive_payrolltemplate(self, payrolltemplate_id):
        obj = PayrollTemplate.objects.using(self._current_app_schema()).filter(id=payrolltemplate_id).update(status=Activestatus.inactive)
        if obj != 0:
            success = NWisefinSuccess()
            success.set_status(SuccessStatus.SUCCESS)
            success.set_message(SuccessMessage.DELETE_MESSAGE)
            return success
        else:
            error = NWisefinError()
            error.set_code(ErrorMessage.INVALID_DATA)
            error.set_description(ErrorDescription.INVALID_DATA)
            return error

    def get_multiple_template_data(self, id_data):
        obj = PayrollTemplate.objects.using(self._current_app_schema()).filter(status=Activestatus.active,id__in=id_data)
        grade = [i.grade for i in obj]
        # grade_data = GradeService(self._scope()).get_grade_data_by_id(grade)
        grade_data = Payrollcommon_Apicall(self._scope()).get_grade_data_by_id(grade)
        list_data = []
        for i in obj:
            data_resp = PayrollTemplateResponse()
            data_resp.set_id(i.id)
            data_resp.set_name(i.name)
            data_resp.set_grade(i.grade)
            data_resp.set_grade_data(i.grade, grade_data)
            data_resp.set_glno(i.glno)
            list_data.append(data_resp)
        return list_data

    def templateflagmastersummary(self, id, ref_type):
        flag_data = PaycomponentFlagmaster.objects.using(self._current_app_schema()).filter(map_id__in=id, ref_type=ref_type, status=Activestatus.active)
        resp = []
        ref_data = [i.ref_id for i in flag_data]
        ref_id_details = SegmentMasterService(self._scope()).get_multiple_segment_data(ref_data)
        for i in flag_data:
            resp_obj = PaycomponentFlagmasterResponse()
            resp_obj.set_id(i.id)
            resp_obj.set_map_id(i.map_id)
            resp_obj.set_ref_id_data(i.ref_id, ref_id_details)
            # resp_obj.set_ref_type(i.ref_type)
            resp.append(resp_obj)
        return resp

    def get_payrolletemplate(self, id_data):
        obj = PayrollTemplate.objects.using(self._current_app_schema()).filter(status=Activestatus.active, id=id_data)
        return obj

    def get_flagmaster_data(self, id_data, ref_type):
        obj = list(PaycomponentFlagmaster.objects.using(self._current_app_schema()).filter(map_id__in=id_data,
                                                                                      ref_type=ref_type,
                                                                                      status=Activestatus.active).
                                                                                      values_list('ref_id', flat=True))
        return obj

    def grade_based_segment_data(self, grade):
        obj = PayrollTemplate.objects.using(self._current_app_schema()).get(status=Activestatus.active, grade=grade)
        ref_type = FlagRef_Type.PAYROLLTEMPLATE
        id_data = [obj.id]
        segment_list = self.get_flagmaster_data(id_data, ref_type)
        ref_id = PayrollSegementMappingService(self._scope()).get_segment_data(segment_list)
        temp_arr, arr = [], []
        temp = {"template_name": obj.name, "grade": obj.grade}
        temp_arr.append(temp)
        for i in segment_list:
            fin_dta = self.segment_data(i, ref_id)
            arr.append(fin_dta)
        final_data = {"segment_details": arr, "template_details": temp}
        return final_data
    
    def segment_data(self, id, arr):
        arr_pay = []
        for i in arr:
            if i.segment_id == id:
                data = {"paycomponent": i.paycomponent, "paycomponent_name": i.paycomponent_name,
                        "paycomponent_percentage": i.paycomponent_percentage}
                arr_pay.append(data)
                fin_dta = {"component_type": i.component_type, "segment_id": i.segment_id,
                           "segment_name": i.segment_name,
                           "paycomponent_data": arr_pay}
                continue
        return fin_dta

    # template based segment
    def grade_based_segment_data1(self, grade):
        obj = PayrollTemplate.objects.using(self._current_app_schema()).get(status=Activestatus.active, grade=grade)
        ref_type = FlagRef_Type.PAYROLLTEMPLATE
        id_data = [obj.id]
        segment_list = self.get_flagmaster_data(id_data, ref_type)
        ref_id = PayrollSegementMappingService(self._scope()).get_segment_data(segment_list)
        temp_arr, arr = [], []
        temp = {"template_name": obj.name, "grade": obj.grade}
        temp_arr.append(temp)
        for i in segment_list:
            fin_dta = self.segment_data1(i, ref_id)
            arr.append(fin_dta)
        final_data = {"segment_details": arr, "template_details": temp}
        return final_data

    def segment_data1(self, id, arr):
        arr_pay = []
        for i in arr:
            if i.segment_id == id:
                emp_pf_service = EmployeePFService(self._scope()).get_employeepfstruct_details()
                arr1 = []
                for emp_pf_data in emp_pf_service:
                    emp_pf_paycom = emp_pf_data.paycomponent
                    for emp_pf_paycom_data in emp_pf_paycom:
                        if emp_pf_paycom_data == i.paycomponent:
                            emp_pf_name = emp_pf_data.name
                            arr1.append(emp_pf_name)
                data = {"paycomponent": i.paycomponent, "paycomponent_name": i.paycomponent_name,
                        "paycomponent_percentage": i.paycomponent_percentage, "paycom":arr1}
                arr_pay.append(data)
                fin_data = {"component_type": i.component_type, "segment_id": i.segment_id,
                    "segment_name": i.segment_name, "segment_percentage":i.segment_percentage,
                    "paycomponent_data": arr_pay}
        return fin_data


    #common_function_for_get_api
    def grade_based_segment_data2(self, grade,template_id):
        try:
            obj = PayrollTemplate.objects.using(self._current_app_schema()).get(status=Activestatus.active, grade=grade,
                                                                                id=template_id)
            ref_type = FlagRef_Type.PAYROLLTEMPLATE
            id_data = [obj.id]
            segment_list = self.get_flagmaster_data(id_data, ref_type)
            ref_id = PayrollSegementMappingService(self._scope()).get_segment_data(segment_list)
            temp_arr, arr = [], []
            temp = {"template_name": obj.name, "grade": obj.grade}
            temp_arr.append(temp)
            for i in segment_list:
                fin_dta = self.segment_data2(i, ref_id)
                arr.append(fin_dta)
            final_data = {"segment_details": arr, "template_details": temp}
            final_json_for_grade = self.final_Segment_details(final_data)
            return final_json_for_grade
        except:
            return {'data': []}

    def segment_data2(self, id, arr):
        condtional_flag = True
        arr_pay = []
        for i in arr:
            if i.segment_id == id:
                condtional_flag = False
                emp_pf_service = EmployeePFService(self._scope()).get_employeepfstruct_details()
                arr1 = []
                for emp_pf_data in emp_pf_service:
                    emp_pf_paycom = emp_pf_data.paycomponent
                    for emp_pf_paycom_data in emp_pf_paycom:
                        if emp_pf_paycom_data == i.paycomponent:
                            emp_pf_name = emp_pf_data.name
                            arr1.append(emp_pf_name)
                data = {"paycomponent": i.paycomponent, "paycomponent_name": i.paycomponent_name,
                        "paycomponent_percentage": i.paycomponent_percentage, "paycom": arr1}
                arr_pay.append(data)
                fin_data = {"paycomponent_type": i.component_type, "segment_id": i.segment_id,
                            "segment_name": i.segment_name, "segment_percentage": i.segment_percentage, 'component_category_type':i.component_category_type,
                            "paycomponent_data": arr_pay}
        if condtional_flag == True:
            fin_data = {"segment_name": i.segment_name, "description": "this segment_has no mapping data"}
        return fin_data

    def final_Segment_details(self, payroll_serv):
        resp_obj = PaycomponentFlagmasterResponse()
        final_data_obj = {}
        cc_service = CompanyContributionService(self._scope()).get_cc_paycom_details()
        emp_pf_service = EmployeePFService(self._scope()).get_employeepfstruct_details()
        resp_obj.company_contribution = cc_service
        resp_obj.employee_contribution = emp_pf_service
        data1 = str(resp_obj.get())
        data = json.loads(data1)
        cc_data, emp_pf_data = [], []
        for contribution in data["company_contribution"]:
            contribution.pop("paycomponent", None)
            cc_data.append(contribution)
        for emp_pf in data["employee_contribution"]:
            emp_pf.pop("paycomponent", None)
            emp_pf_data.append(emp_pf)
        final_data_obj['company_contribution'] = cc_data
        final_data_obj['employee_contribution'] = emp_pf_data
        final_data_obj['segment_details'] = payroll_serv['segment_details']
        return final_data_obj

    def payrolltemplate_upload(self,payrolltemplate_data, user_id):
        try:
            success_obj = NWisefinSuccess()
            # grade = payrollGradeService(self._scope()).get_grade_name(payrolltemplate_data['GRADE'])
            grade=Payrollcommon_Apicall(self._scope()).get_grade_name(payrolltemplate_data['GRADE'])
            obj= PayrollTemplate.objects.using(self._current_app_schema()).create(name=(payrolltemplate_data['NAME']),
                                                                                       grade=grade,
                                                                                       created_by=user_id,
                                                                                       entity_id=self._entity_id(),
                                                                                       glno=(payrolltemplate_data['GLNO']))
            id_data = obj.id
            code_gen = 'TEMP'+str(id_data)
            obj.code = code_gen
            obj.save()
            success_obj.set_message(SuccessMessage.CREATE_MESSAGE)
            success_obj.set_status(SuccessStatus.SUCCESS)
            success_obj.code = code_gen
            success_obj.id = id_data
            return success_obj
        except Exception as excep:
            obj = NWisefinError()
            obj.set_code(ErrorMessage.INVALID_DATA)
            obj.set_description(str(excep))
            obj.message = "INVALID_DATA"
            return obj


    def get_payrolltemplate_name(self, template_name):
        obj = PayrollTemplate.objects.using(self._current_app_schema()).filter(status=Activestatus.active,name__icontains=template_name)[0]
        return obj.id

    def inactive_payrolltemplate_common(self, payrolltemplate_id):
        obj = PayrollTemplate.objects.using(self._current_app_schema()).filter(id=payrolltemplate_id).update(status=Activestatus.inactive)
        obj = PaycomponentFlagmaster.objects.using(self._current_app_schema()).filter(status=Activestatus.active,
                                                                                map_id=payrolltemplate_id,
                                                                                ref_type=FlagRef_Type.PAYROLLTEMPLATE).update(status=Activestatus.inactive)
        obj = Payrollmastersmapping.objects.using(self._current_app_schema()).filter(template_id=payrolltemplate_id).update(status=Activestatus.inactive)
        if obj != 0:
            success = NWisefinSuccess()
            success.set_status(SuccessStatus.SUCCESS)
            success.set_message(SuccessMessage.DELETE_MESSAGE)
            return success
        else:
            error = NWisefinError()
            error.set_code(ErrorMessage.INVALID_DATA)
            error.set_description(ErrorDescription.INVALID_DATA)
            return error

