from .models import patient, disease, Zone, District_State, employee
from django.db.models import Q, Count, Sum
from diagnoses.models import disease_details
from datetime import datetime, date, timedelta
from dateutil import relativedelta
from diagnoses.models import diagnose,condition,disease_details
from consult.models import observation,nutritional_value,blood_Pressure,History_examination,vitals,scheduling,treatment_details
from medic.models import medications,medic_inhouse,inventory_entry
from django.contrib import messages
import json, numpy
from .internal import localfunc 
from numpy import * 

list_model_patients = [diagnose, condition, disease_details, observation, nutritional_value, blood_Pressure, History_examination, vitals, treatment_details,
medications, inventory_entry, patient]

str_period = ''
list_report_IMH_group = ['children_1_5', 'children_6_12', 'male_13_25', 'male_26_40', 'male_41_60', 'male_gt_60', 'female_13_25','female_26_40', 'female_41_60','female_gt_60', 'Transgender_13_25','Transgender_26_40', 'Transgender_41_60','Transgender_gt_60']
list_report_IMH_group_name = ['children 1 to 5 ', 'children 6 to 12', 'male 13 to 25', 'male 26 to 40', 'male 41 to 60', 'male > 60', 'female 13 to 25','female 26 to 40', 'female 41 to 60','female > 60', 'Transgender 13 to 25','Transgender 26 to 40', 'Transgender 41 to 60','Transgender > 60']
list_colours =  [
      'rgba(255, 99, 132, 0.2)',
      'rgba(255, 159, 64, 0.2)',
      'rgba(75, 192, 192, 0.2)',
      'rgba(54, 162, 235, 0.2)',
      'rgba(153, 102, 255, 0.2)',
    ]
def get_headers():
    global list_report_IMH_group
    global list_report_IMH_group_name
    list_output = []
    int_count = 0 
    for str_IMH in  list_report_IMH_group:
        dic_data = {}
        dic_data['header'] = str_IMH
        dic_data['title'] = list_report_IMH_group_name[int_count]
        int_count = int_count + 1
        list_output.append(dic_data)
    return list_output
        


def lf_simplify_summary(list_radar, list_total_labels):# 23-Oct-23
    list_disease = list_total_labels
    dic_output = {}   #str_group:{'label'}
    array_data = array([list_radar[0]['data']])
    for dic_radar in     list_radar:            array_data = append(array_data,[dic_radar['data']],0) 
    obj_total = numpy.sum(array_data, axis=0)
    list_total = list(obj_total)
    int_counter = 0 
    int_matchcounter = 0 
    for int_total in list_total: # total row loop 
            if int_total == 0 :
                 
                 list_disease.pop (int_counter -int_matchcounter)
                 for dic_radar in     list_radar: dic_radar['data'].pop(int_counter-int_matchcounter)
                 int_matchcounter = int_matchcounter+ 1
            int_counter = int_counter+1
    dic_output['group_disease'] = list_disease
    list_groupdata = []
    for dic_radar in     list_radar: list_groupdata.append({'label':dic_radar['label'],  'data': dic_radar['data']}) 
    dic_output['group_data'] = list_groupdata
    
    return  dic_output


def lf_simplify_summary_main(dict_radar,LIST_DISEASE ):
    #LIST_DISEASE = list_disease
    dic_output = {}
    #print('LIST_DISEASE', len(LIST_DISEASE))
    dic_entity =   lf_simplify_summary(dict_radar[0:2], LIST_DISEASE.copy())
    dic_output['children'] = {'group_disease' : dic_entity['group_disease'], 'group_data' : json.dumps(dic_entity['group_data']).replace('"',"'").replace("{'","{").replace("':",":").replace(", '",", ")} 
    #print('list_disease', len(LIST_DISEASE))
    dic_entity =   lf_simplify_summary(dict_radar[2:6], LIST_DISEASE.copy())
    dic_output['male'] = {'group_disease' : dic_entity['group_disease'], 'group_data' : json.dumps(dic_entity['group_data']).replace('"',"'").replace("{'","{").replace("':",":").replace(", '",", ")} 
    dic_entity =   lf_simplify_summary(dict_radar[6:10], LIST_DISEASE.copy())
    dic_output['female'] = {'group_disease' : dic_entity['group_disease'], 'group_data' : json.dumps(dic_entity['group_data']).replace('"',"'").replace("{'","{").replace("':",":").replace(", '",", ")}         
    dic_entity =   lf_simplify_summary(dict_radar[10:14], LIST_DISEASE.copy())
    dic_output['transgender'] = {'group_disease' : dic_entity['group_disease'], 'group_data' : json.dumps(dic_entity['group_data']).replace('"',"'").replace("{'","{").replace("':",":").replace(", '",", ")}      
    #print('test output', dic_output)
    return dic_output

def get_disease_report(obj_model, int_start, int_end):
    dt_start = datetime(datetime.today().year - int_start , datetime.today().month, datetime.today().day)
    dt_end = datetime(datetime.today().year - int_end , datetime.today().month, datetime.today().day)
    
    obj_model = obj_model.filter(fk_patient__DoB__gte=dt_end) # Greater than or equal to (in days)
    obj_model = obj_model.filter(fk_patient__DoB__lte=dt_start) # less than (in days)    
    # print(obj_model)  # for debugging only 
    #for obj_mod in obj_model:   print(obj_mod.fk_patient.id, int_start, int_end) # getting patient details
    return obj_model


def get_disease_radar_data(list_data):
    global list_report_IMH_group
    # list_report = []
    # list_report.append({'disease': []})
    list_report = {} # {'disease': []}
    list_output = []
    list_disease = []
    int_counter = 0 
    for dict_data in list_data: list_disease.append(dict_data['disease'])
    for str_agegroup in list_report_IMH_group:
         
       # list_report.append({str_agegroup: []})
        list_report[str_agegroup] =  []
        #dict_output = {'label': str_agegroup }  # with general label
        dict_output = {'label': list_report_IMH_group_name[int_counter] } # with user friendly label
        for dict_data in list_data: list_report[str_agegroup].append(dict_data[str_agegroup])#list_report['disease'].append(dict_data['disease'])
        dict_output['data'] = list_report[str_agegroup] 
        list_output.append(dict_output)
        int_counter = int_counter +1     
    #print('get_disease_radar_data', list_output)
    return list_output, list_disease #list_report


def tuplelist_to_str(list_tupl):
    str_output = ''
    for tupl_obj in list_tupl:
        if len(tupl_obj) ==2 : str_output = str(tupl_obj[1]) + ' - '+ str_output 
        str_output = str_output   + tupl_obj[0] + ','
        
    return str_output
def list_str_toint(list_input):
    list_output = []
    for str_num in list_input: list_output.append(int(str_num))
    return list_output



def get_disease_IMH_report_main(request, dic_req):

    global list_colours 
    str_reportlevel =''
    if 'report_period' in dic_req.keys():       
            int_period =int(dic_req.get('report_period')[0].split('_')[0])
            int_year =int(dic_req.get('report_period')[0].split('_')[1])
    else:   
            int_period= int(datetime.today().month)
            int_year = int(datetime.today().year)
 

    dt_start = datetime(int_year , int_period, 1)
    dt_end = datetime(int_year , int_period+ 1, 1) - timedelta(days=1)
    str_period = dt_start.strftime('%B') + ' - '+ str(int_year)
    #print('start and End Date', dt_start,dt_end)
    obj_output = []      
    #obj_disease = disease_details.objects.all()
    obj_disease = disease_details.objects.filter(date_modified__range=(dt_start,dt_end)) #.all() # need to apply current month as filter.
    # it is valid report request or not 
    if 'district'  in dic_req.keys() :             
        str_reportlevel = 'District Level - '  +  tuplelist_to_str(District_State.objects.filter(id__in = list_str_toint(dic_req.get('district'))).values_list("District")  )
        obj_disease = obj_disease.filter(fk_patient__fk_zone__in = list_str_toint(dic_req.get('district'))) # Zone level
    elif 'zone' in dic_req.keys():                   
        #print('test in zone setup', tuplelist_to_str(Zone.objects.filter(id__in = list_str_toint(dic_req.get('zone'))).values_list("center")  )    )
        str_reportlevel = 'Zone/Center Level - '   +  tuplelist_to_str(Zone.objects.filter(id__in = list_str_toint(dic_req.get('zone'))).values_list("center")  )    
        obj_disease = obj_disease.filter(fk_patient__fk_zone__in = list_str_toint(dic_req.get('zone'))) # Zone level
    elif 'zone' in dic_req.keys(): 
        if employee.objects.filter(str_username = request.user.username).exists(): 
            obj_emply = employee.objects.filter(str_username = request.user.username)[0]
            str_reportlevel =  'Current Center - ' +  obj_emply.fk_zone.center
            obj_disease = obj_disease.filter(fk_patient__fk_zone = obj_emply.fk_zone) # Zone level
    else: str_reportlevel =  'Total Summary - All PHC' #+ str(obj_disease.count())
            #children
    obj_output =  list(get_disease_report(obj_disease,1, 5).values('fk_disease__disease_name').annotate(children_1_5 = Count('fk_disease__disease_name')) )
    obj_output =  obj_output + list(get_disease_report(obj_disease,6, 12).values('fk_disease__disease_name').annotate(children_6_12 = Count('fk_disease__disease_name')) )
            # Male
    obj_output =  obj_output + list(get_disease_report(obj_disease.filter(fk_patient__fk_gender__gender_name= 'Male'),12, 25).values('fk_disease__disease_name').annotate(male_12_25 = Count('fk_disease__disease_name')) )
    obj_output =  obj_output + list(get_disease_report(obj_disease.filter(fk_patient__fk_gender__gender_name= 'Male'),26, 41).values('fk_disease__disease_name').annotate(male_26_40 = Count('fk_disease__disease_name')))
    obj_output =  obj_output + list(get_disease_report(obj_disease.filter(fk_patient__fk_gender__gender_name= 'Male'),41, 60).values('fk_disease__disease_name').annotate(male_41_60 = Count('fk_disease__disease_name')))

    dt_maxage = datetime(datetime.today().year - 60 , datetime.today().month, datetime.today().day)
    obj_model_max =  obj_disease.filter(fk_patient__fk_gender__gender_name= 'Male').filter( fk_patient__DoB__lte=dt_maxage)
    #for obj_mod in obj_model_max:   print(obj_mod.fk_patient.id, 60) # for debugging
    obj_output =  obj_output + list(obj_model_max.values('fk_disease__disease_name').annotate(male_gt_60 = Count('fk_disease__disease_name')))

            # FeMale
    obj_output =  obj_output + list(get_disease_report(obj_disease.filter(fk_patient__fk_gender__gender_name= 'Female'),12  , 25).values('fk_disease__disease_name').annotate(female_12_25 = Count('fk_disease__disease_name')) )
    #print('before female_26_40', obj_output)
    obj_output =  obj_output + list(get_disease_report(obj_disease.filter(fk_patient__fk_gender__gender_name= 'Female'),26, 40).values('fk_disease__disease_name').annotate(female_26_40 = Count('fk_disease__disease_name')))
    #print('after female_26_40', obj_output)
    obj_output =  obj_output + list(get_disease_report(obj_disease.filter(fk_patient__fk_gender__gender_name= 'Female'),41, 60).values('fk_disease__disease_name').annotate(female_41_60 = Count('fk_disease__disease_name')))


    dt_maxage = datetime(datetime.today().year - 60 , datetime.today().month, datetime.today().day)
    obj_model_max =  obj_disease.filter(fk_patient__fk_gender__gender_name= 'Female').filter( fk_patient__DoB__lte=dt_maxage)
    #for obj_mod in obj_model_max:   print(obj_mod.fk_patient.id, 60) # for debugging
    obj_output =  obj_output + list(obj_model_max.values('fk_disease__disease_name').annotate(female_gt_60 = Count('fk_disease__disease_name')))

        # Transgender

    obj_output =  obj_output + list(get_disease_report(obj_disease.filter(fk_patient__fk_gender__gender_name= 'Transgender'),12  , 25).values('fk_disease__disease_name').annotate(Transgender_12_25 = Count('fk_disease__disease_name')) )
    obj_output =  obj_output + list(get_disease_report(obj_disease.filter(fk_patient__fk_gender__gender_name= 'Transgender'),26, 40).values('fk_disease__disease_name').annotate(Transgender_26_40 = Count('fk_disease__disease_name')))
    obj_output =  obj_output + list(get_disease_report(obj_disease.filter(fk_patient__fk_gender__gender_name= 'Transgender'),41, 60).values('fk_disease__disease_name').annotate(Transgender_41_60 = Count('fk_disease__disease_name')))


    dt_maxage = datetime(datetime.today().year - 60 , datetime.today().month, datetime.today().day)
    obj_model_max =  obj_disease.filter(fk_patient__fk_gender__gender_name= 'Transgender').filter( fk_patient__DoB__lte=dt_maxage)
    #for obj_mod in obj_model_max:   print(obj_mod.fk_patient.id, 60) # for debugging
    obj_output =  obj_output + list(obj_model_max.values('fk_disease__disease_name').annotate(Transgender_gt_60 = Count('fk_disease__disease_name')))

    #print('Final output', obj_output)
                # total calculation
    obj_temp = obj_disease.values('fk_disease__disease_name').annotate(total = Count('fk_disease__disease_name')).order_by('fk_disease__disease_name')
    list_total_labels = localfunc.get_list_from_dict( list(obj_temp.values('fk_disease__disease_name') ), 'fk_disease__disease_name')
    list_total_value =  localfunc.get_list_from_dict( list(obj_temp.values('total') ), 'total') # for total number of records
    dict_total =  list(obj_temp )
    #print(list_total_labels,list_total_value, dict_total ) # 

    list_colors = localfunc.get_random_list_from_choice(list_colours,len(list_total_value))
    dict_radar, list_disease = get_disease_radar_data(group_report_IMH(obj_output))
    #print( 'Radar data', dict_radar)
    #lf_simplify_summary(dict_radar[0:2], list_disease)
    radar_data = lf_simplify_summary_main(dict_radar,list_disease)
    # str_radar_children = json.dumps(dict_radar[0:2]).replace('"',"'").replace("{'","{").replace("':",":").replace(", '",", ")
    # str_radar_male = json.dumps(dict_radar[2:6]).replace('"',"'").replace("{'","{").replace("':",":").replace(", '",", ")
    # str_radar_female = json.dumps(dict_radar[6:10]).replace('"',"'").replace("{'","{").replace("':",":").replace(", '",", ")
    # str_radar_Transgender = json.dumps(dict_radar[10:14]).replace('"',"'").replace("{'","{").replace("':",":").replace(", '",", ")
    #'str_radar_children': str_radar_children, 'str_radar_male' : str_radar_male, 'str_radar_female': str_radar_female, 'str_radar_Transgender': str_radar_Transgender,
#'dict_total': dict_total,


    list_colors_border = [] 
    for str_rgb in list_colors: list_colors_border.append(str_rgb.replace(', 0.2',''))

    dict_output = { 'radar_data': radar_data,  'rows': group_report_IMH(obj_output),                   
                    'list_total_labels': list_total_labels, 'list_total_totals' : list_total_value,  'str_period': str_period, 'reportlevel': str_reportlevel,'headers' : get_headers()} #'str_querypath': str_querypath, #+ str(sum(list_total_value))
    #print(dict_output)
    return dict_output # group_report_IMH(obj_output)


def group_report_IMH(list_data, is_alldata = True):
    list_output = []
    for obj_disease in disease.objects.all():
        bln_check = False
        dic_output = {'disease': obj_disease.disease_name }
        for dic_data in list_data:
            if is_alldata:  str_datakey = list(dic_data.keys())[1]
            if  dic_data['fk_disease__disease_name'] == obj_disease.disease_name:  #list_output.append({'disease': obj_disease.disease_name, str_datakey :  dic_data[str_datakey] })
                bln_check = True
                if is_alldata :  dic_output.update({ str_datakey :  dic_data[str_datakey] })    # for all data send as dictionary
                else: dic_output = obj_disease.disease_name # for total send only list of data
        if bln_check: 
            if is_alldata: 
                   list_output.append(udpate_data_labels(list_report_IMH_group, dic_output))
            else:  list_output.append(dic_output)
    #print('group_report_IMH', list_output, 'Input parameter', list_data, is_alldata)
    return list_output




def udpate_data_labels(list_labels, dict_data):
    for str_label in list_labels:
        if str_label in dict_data:
            pass # do nothing
        else:    
            dict_data[str_label] = 0
    return dict_data





def obj_query_filter(obj_filter, dic_req):
     # employee list of perfomance 
    global str_period 
    if 'report_period' in dic_req.keys():       
            int_period =int(dic_req.get('report_period')[0].split('_')[0])
            int_year =int(dic_req.get('report_period')[0].split('_')[1])
    else:   
            int_period= int(datetime.today().month)
            int_year = int(datetime.today().year)
 

    dt_start = datetime(int_year , int_period, 1)
    dt_end = datetime(int_year , int_period+ 1, 1) - timedelta(days=1)
    str_period = dt_start.strftime('%B') + ' - '+ str(int_year)  + ' - Month Report - '   
    return obj_filter.objects.filter(date_modified__range=(dt_start,dt_end))  # need to apply current month as filter.




def employee_perfomance(request, dic_req):
    global str_period 
     # filter by zone , District, year and period
     # employee list of perfomance 
    list_GW_KPI = [medications.__name__, inventory_entry.__name__, patient.__name__] 
    if 'district'  in dic_req.keys() :   str_reportlevel = 'District Level - '  +  tuplelist_to_str(District_State.objects.filter(id__in = list_str_toint(dic_req.get('district'))).values_list("District")  )
    elif 'zone' in dic_req.keys():         str_reportlevel = 'Zone/Center Level - '   +  tuplelist_to_str(Zone.objects.filter(id__in = list_str_toint(dic_req.get('zone'))).values_list("center")  )    
    elif 'employee' in dic_req.keys():         str_reportlevel = 'Employee Level - '   +  tuplelist_to_str(employee.objects.filter(id__in = list_str_toint(dic_req.get('employee'))).values_list("str_username")  )    
    else: str_reportlevel =  'Total Summary - All PHC'  
    list_perfomance = []     
    #print(dic_req.get('employee'))
    for model_patient in list_model_patients:   
        obj_Patient =   obj_query_filter(model_patient, dic_req)
        if 'district'  in dic_req.keys() :        obj_Patient = obj_Patient.filter(fk_employee__fk_zone__fk_District__in = list_str_toint(dic_req.get('district'))) # District level
        elif 'zone' in dic_req.keys():            obj_Patient = obj_Patient.filter(fk_employee__fk_zone__in = list_str_toint(dic_req.get('zone'))) # Zone level
        elif 'employee' in dic_req.keys():            obj_Patient = obj_Patient.filter(fk_employee__in = list_str_toint(dic_req.get('employee'))) # Employee level
        list_perfomance.append(obj_Patient)
    if 'employee' in dic_req.keys():   obj_emply = employee.objects.filter(id__in = dic_req.get('employee') )  #list_str_toint(dic_req.get('employee'))).values_list("str_username")     )[0])      #obj_emply = employee.objects.filter(str_username__in = dic_req.get('employee'))
    else:             messages.info(request, 'Note, Employee Level filter is not applied.')
    if 'employee' in dic_req.keys() and obj_emply is None : messages.error(request, 'The filtered Employee Details not available, please check again.', 'danger')
    #print('employee', obj_emply)
    list_label = [];    list_value = []
    list_label_gw = [];    list_value_gw = []
    for performance in list_perfomance:
        int_count =  performance.count()
        if 'employee' in dic_req.keys() and obj_emply is not None:   int_count =  performance.filter(fk_employee__in = obj_emply).count()
        if str(performance.model.__name__) in list_GW_KPI: 
            list_label_gw.append(str(performance.model.__name__))
            list_value_gw.append(int_count)            
        else:
            list_label.append(str(performance.model.__name__))
            list_value.append(int_count)
    return {'reportlevel': str_reportlevel,'list_label_AMO':list_label, 'list_value_AMO':list_value, 'list_label_MP': list_label_gw, 'list_value_MP': list_value_gw, 'str_period': str_period}
            
            
def stock_review_api(request, dic_req): # stock by list
    global str_period  # filter by zone , District, year and period
    print('dic_req  api',dic_req)
    
    if 'district'  in dic_req.keys() :   str_reportlevel = 'District Level - '  +  tuplelist_to_str(District_State.objects.filter(id__in = list_str_toint(dic_req.get('district'))).values_list("District")  )
    elif 'zone' in dic_req.keys():         str_reportlevel = 'Zone/Center Level - '   +  tuplelist_to_str(Zone.objects.filter(id__in = list_str_toint(dic_req.get('zone'))).values_list("center")  )    
    else: str_reportlevel =  'Total Summary - All PHC'  
    if 'report_period' in dic_req.keys():    obj_Stock =   obj_query_filter(inventory_entry, dic_req)     # filter by year and period/month (starting to End)fk_employee__fk_zone__fk_District__in   
    else :   obj_Stock =  inventory_entry.objects.all()
    print(str_period, 'from API view')
    if 'district'  in dic_req.keys() :        obj_Stock = obj_Stock.filter(fk_employee__fk_dist__in = list_str_toint(dic_req.get('district'))) # Zone level
    elif 'zone' in dic_req.keys():            obj_Stock = obj_Stock.filter(fk_employee__fk_zone__in = list_str_toint(dic_req.get('zone'))) # Zone level #.aggregate(total=Sum('dosage_unit')))#
    list_output =  list(obj_Stock.all().values('fk_med__id','fk_med__drug_name', 'fk_med__drug_tamil', 'fk_med__fk_system__System','fk_med__packaging').order_by('fk_med__drug_name').annotate(  TotalEntry = Count('fk_med__id'), Available= Sum('dosage_unit')))
    list_tbl_header =  [{ 'header': 'fk_med__id', 'title': 'Prod ID'}, { 'header': 'fk_med__drug_name', 'title': 'Drug Name'},{ 'header': 'fk_med__drug_tamil', 'title': 'In Tamil'},{ 'header': 'fk_med__fk_system__System', 'title': 'System'},{ 'header': 'TotalEntry', 'title': 'Total Entry'},{ 'header': 'Available', 'title': 'Available'}]
    return {'rows':list_output, 'list_tbl_header': list_tbl_header}

def stock_review(request, dic_req, viewtype = ''):
    global str_period 
     # filter by zone , District, year and period
     # stock by list
    if viewtype =='tbl': messages.warning(request, 'Note, This page shows only Stock Movement for a specific Period NOT STOCK AVAILABILITY.') 
    if viewtype =='tbl2': messages.warning(request, 'Note, This is a Summarized page, it is NOT reffering to Stock Movement.') 
    if 'district'  in dic_req.keys() :   str_reportlevel = 'District Level - '  +  tuplelist_to_str(District_State.objects.filter(id__in = list_str_toint(dic_req.get('district'))).values_list("District")  )
    elif 'zone' in dic_req.keys():         str_reportlevel = 'Zone/Center Level - '   +  tuplelist_to_str(Zone.objects.filter(id__in = list_str_toint(dic_req.get('zone'))).values_list("center", 'id')  )    
    else: str_reportlevel =  'Total Summary - All PHC'      
    if 'report_period' in dic_req.keys():      obj_Stock =  obj_query_filter(inventory_entry, dic_req)     # filter by year and period/month (starting to End)fk_employee__fk_zone__fk_District__in
    elif viewtype =='tbl': 
        str_period = '! Not Filtered, Please Apply Filter ! -'
        messages.info(request, 'Note, Filter is not applied. Hence, All Data is showing.')
    else : str_period = '! Current Stock ! -'
    # if obj_Stock is None : obj_Stock =  inventory_entry.objects.all()
    # if 'district'  in dic_req.keys() :        obj_Stock = obj_Stock.filter(fk_employee__fk_zone__fk_District__in = list_str_toint(dic_req.get('district'))) # Zone level
    # elif 'zone' in dic_req.keys():            obj_Stock = obj_Stock.filter(fk_employee__fk_zone__in = list_str_toint(dic_req.get('zone'))) # Zone level
    
    # list_label_Siddha = []; list_value_Siddha= []
    # list_label_YN = []; list_value_YN= []
    # list_label_Homoeopathy = []; list_value_Homoeopathy = []
    # list_label_Unani = []; list_value_Unani= []
    # list_label_Ayurveda = []; list_value_Ayurveda= []
    # list_label_Others = []; list_value_Others= []
    return {'str_period': str_period, 'reportlevel': str_reportlevel}
    
    




