<?php
namespace App\Model\Table;

use App\Model\Entity\MedicalOpinionRequest;
use Cake\ORM\RulesChecker;
use Cake\ORM\Table;
use Cake\Validation\Validator;
use MedidasDispersao\MedidasDispersao;

require_once ROOT . DS . "vendor" . DS . "Zurubabel" . DS . "MedidasDispersao.php";

/**
 * MedicalOpinionRequests Model
 *
 * @property \Cake\ORM\Association\BelongsTo $RequestedSpecialties
 * @property \Cake\ORM\Association\BelongsTo $Professionals
 * @property \Cake\ORM\Association\BelongsTo $Hospitalizations
 * @property \Cake\ORM\Association\HasMany $MedicalOpinionAnswer
 */
class MedicalOpinionRequestsTable extends Table
{

    /**
     * Initialize method
     *
     * @param array $config The configuration for the Table.
     * @return void
     */
    public function initialize(array $config)
    {
        parent::initialize($config);

        $this->table('medical_opinion_requests');
        $this->displayField('id');
        $this->primaryKey('id');

        $this->addBehavior('Timestamp');
        $this->belongsTo('Specialties', [
            'foreignKey' => 'specialty_id',
            'joinType' => 'INNER',
        ]);
        $this->belongsTo('Users', [
            'foreignKey' => 'user_id',
            'joinType' => 'INNER',
        ]);
        $this->belongsTo('Hospitalizations', [
            'foreignKey' => 'hospitalization_id',
            'joinType' => 'INNER',
        ]);
        $this->belongsTo('Sectors', [
            'foreignKey' => 'sector_id',
            'joinType' => 'INNER',
        ]);
        $this->hasOne('MedicalOpinionAnswers', [
            'foreignKey' => 'medical_opinion_request_id',
        ]);
    }

    public function relatorioMedicalOpinion($hospitalizations, $date_before, $date_after, $sectors, $specialties)
    {
        $calc_obj = new MedidasDispersao();

        $data = [
            'total_de_registros' => 0,
            'pareceres_solicitados_por_dia' => 0,
            'total_de_internacoes' => 0, //yolo
            'pareceres_solicitados_por_internacoes' => 0,
            'percen_pareceres_solicitados_por_internacoes' => 0,
            'tot_dias_no_perido' => 0,
            'tab_parecer_setor' => [],
            'tab_especialidade_destino' => [],
            'tot_pareceres_nao_respondidos' => 0,
            'percen_pareceres_nao_respondidos' => 0,

            'arr_tempo_resposta_parecer' => [],
            'tot_tempo_resposta_parecer_minimo' => 0,
            'tot_tempo_resposta_parecer_medio' => 0,
            'tot_tempo_resposta_parecer_maximo' => 0,
            'tot_tempo_resposta_parecer_mediano' => 0,
            'tot_tempo_resposta_parecer_desvio_padrao' => 0,

            'setores' => [],
            'especialidade_destino' => [],
        ];

        $data['tot_dias_no_perido'] = $date_before->diff($date_after)->days;

        foreach ($specialties as $specialty)
        {
            $specialty_id = $specialty['id'];

            $data['especialidade_destino'][$specialty_id] = [
                'name' => $specialty['name'],
                'specialty_id' => $specialty['id'],
                'tot_pareceres' => 0,
                'percen_pareceres' => 0,

                'tot_pareceres_nao_respondidos' => 0,
                'percen_pareceres_nao_respondidos' => 0,

                'arr_tempo_resposta_parecer' => [],
                'tot_tempo_resposta_parecer_minimo' => 0,
                'tot_tempo_resposta_parecer_medio' => 0,
                'tot_tempo_resposta_parecer_maximo' => 0,
                'tot_tempo_resposta_parecer_mediano' => 0,
                'tot_tempo_resposta_parecer_desvio_padrao' => 0,
            ];
        }

        foreach ($sectors as $sector)
        {
            $sector_id = $sector['id'];

            $data['setores'][$sector_id] = [
                'name' => $sector['name'],

                'tot_pareceres' => 0,
                'percen_pareceres' => 0,

                'tot_pareceres_nao_respondidos' => 0,
                'percen_pareceres_nao_respondidos' => 0,

                'arr_tempo_resposta_parecer' => [],
                'tot_tempo_resposta_parecer_minimo' => 0,
                'tot_tempo_resposta_parecer_medio' => 0,
                'tot_tempo_resposta_parecer_maximo' => 0,
                'tot_tempo_resposta_parecer_mediano' => 0,
                'tot_tempo_resposta_parecer_desvio_padrao' => 0,

                'especialidade_destino' => $data['especialidade_destino'],
            ];
        }

        foreach ($hospitalizations as $hospitalization)
        {
            $data['total_de_internacoes']++;

            foreach ($hospitalization["medical_opinion_requests"] as $key_1 => $neonatal)
            {
                $data_solicitacao = new \DateTime($neonatal['created']->format('Y-m-d'));

                if (!empty($neonatal['medical_opinion_answer']))
                {
                    $data_resposta = new \DateTime($neonatal['medical_opinion_answer']['created']->format('Y-m-d'));
                    $tempo_de_resposta = $data_solicitacao->diff($data_resposta)->days;

                    array_push($data['arr_tempo_resposta_parecer'], $tempo_de_resposta);
                }
                else
                {
                    $data['tot_pareceres_nao_respondidos']++;
                }

                if (isset($neonatal['sector']))
                {
                    $name = $neonatal['sector']['name'];
                    $id = $neonatal['sector']['id'];

                    //calc tempo de resposta dos pareceres por setor
                    if (!empty($neonatal['medical_opinion_answer'])) //verifica se a solicitação foi respondida
                    {
                        $data_resposta = new \DateTime($neonatal['medical_opinion_answer']['created']->format('Y-m-d'));
                        $tempo_de_resposta = $data_solicitacao->diff($data_resposta)->days;
                        array_push($data['setores'][$id]['arr_tempo_resposta_parecer'], $tempo_de_resposta);
                    }
                    else
                    {
                        $data['setores'][$id]['tot_pareceres_nao_respondidos']++; //calc total de pareceres não respondidos por setor
                    }

                    $data['setores'][$id]['tot_pareceres']++;

                    if (isset($neonatal['specialty']))
                    {
                        $specialty_id = $neonatal['specialty']['id'];
                        $data['setores'][$id]['especialidade_destino'][$specialty_id]['tot_pareceres']++;
                    }
                }

                if (isset($neonatal['specialty']))
                {
                    $name = $neonatal['specialty']['name'];
                    $id = $neonatal['specialty']['id'];

                    $data['especialidade_destino'][$id]['tot_pareceres']++; //calc total de pareceres por especialidade
                    if (!empty($neonatal['medical_opinion_answer'])) //verifica se a solicitação foi respondida
                    {                        
                        $data_resposta = new \DateTime($neonatal['medical_opinion_answer']['created']->format('Y-m-d'));
                        $tempo_de_resposta = $data_solicitacao->diff($data_resposta)->days;

                        array_push($data['especialidade_destino'][$id]['arr_tempo_resposta_parecer'], $tempo_de_resposta);
                    }
                    else
                    {
                        $data['especialidade_destino'][$id]['tot_pareceres_nao_respondidos']++; //calc total de pareceres não respondidos por especialidade
                    }
                }

                $neonatal_arr = (array) $neonatal;
                $i = 0;

                $data['total_de_registros']++;

                foreach ($neonatal_arr as $key_2 => $value_2)
                {
                    $i++;

                    if ($i == 2) //acessa as propriades do obj
                    {
                        foreach ($value_2 as $key_3 => $value_3)
                        {
                            //$data[$key_3] = $value_3;
                            formatArr($value_3, $data, $key_3);
                        }
                    }
                }
            }
        }

        foreach ($data as $key => $value)
        {
            $marcados = 0;

            if (isset($data[$key]['arr']))
            {
                $len = count($data[$key]['arr']);

                for ($i = 0; $i < $len; $i++)
                {
                    if ($data[$key]['arr'][$i] || $data[$key]['arr'][$i] !== 0)
                    {
                        $marcados++;
                    }
                }
            }

            if (isset($data[$key]['percentual']))
            {
                $data[$key]['total'] = count($data[$key]['arr']);
                $data[$key]['percentual'] = $calc_obj->calculate_percentage($marcados, $data['total_de_registros']);
                $data[$key]['media'] = $calc_obj->calc_average($data[$key]['arr']);
                $data[$key]['mediana'] = $calc_obj->calculate_median($data[$key]['arr']);
                $data[$key]['desvio_padrao'] = $calc_obj->standard_deviation($data[$key]['arr']);
            }
        }

        if ($data['total_de_registros'] > 0 &&
            $data['tot_dias_no_perido'] > 0)
        {
            $data['pareceres_solicitados_por_dia'] = round($data['total_de_registros'] / $data['tot_dias_no_perido'], 2);
        }

        if ($data['total_de_registros'] > 0 &&
            $data['total_de_internacoes'] > 0)
        {
            $data['pareceres_solicitados_por_internacoes'] = round($data['total_de_registros'] / $data['total_de_internacoes'], 2);
            $data['percen_pareceres_solicitados_por_internacoes'] = ($data['percen_pareceres_solicitados_por_internacoes'] * 100) / $data['total_de_internacoes'];
            $data['percen_pareceres_solicitados_por_internacoes'] = round($data['percen_pareceres_solicitados_por_internacoes'], 2);
        }

        if ($data['total_de_registros'] > 0 &&
            $data['tot_pareceres_nao_respondidos'] > 0)
        {
            $data['percen_pareceres_nao_respondidos'] = ($data['tot_pareceres_nao_respondidos'] * 100) / $data['total_de_registros'];
            $data['percen_pareceres_nao_respondidos'] = round($data['percen_pareceres_nao_respondidos'], 2);
        }

        if (count($data['arr_tempo_resposta_parecer']) > 0)
        {
            $data['tot_tempo_resposta_parecer_minimo'] = min($data['arr_tempo_resposta_parecer']);
            $data['tot_tempo_resposta_parecer_maximo'] = max($data['arr_tempo_resposta_parecer']);
            $data['tot_tempo_resposta_parecer_medio'] = $calc_obj->calc_average($data['arr_tempo_resposta_parecer']);
            $data['tot_tempo_resposta_parecer_mediano'] = $calc_obj->calculate_median($data['arr_tempo_resposta_parecer']);
            $data['tot_tempo_resposta_parecer_desvio_padrao'] = $calc_obj->standard_deviation($data['arr_tempo_resposta_parecer']);
        }

        foreach ($data['setores'] as $key => $setor)
        {
            if ($setor['tot_pareceres'] > 0)
            {
                if ($setor['tot_pareceres_nao_respondidos'] > 0)
                {
                    $data['setores'][$key]['percen_pareceres_nao_respondidos'] = ($setor['tot_pareceres_nao_respondidos'] * 100) / $setor['tot_pareceres'];
                    $data['setores'][$key]['percen_pareceres_nao_respondidos'] = round($data['setores'][$key]['percen_pareceres_nao_respondidos'], 2);
                }

                $data['setores'][$key]['percen_pareceres'] = ($setor['tot_pareceres'] * 100) / $data['total_de_registros'];
                $data['setores'][$key]['percen_pareceres'] = round($data['setores'][$key]['percen_pareceres'], 2);
            }

            if (count($setor['arr_tempo_resposta_parecer']) > 0)
            {
                $data['setores'][$key]['tot_tempo_resposta_parecer_minimo'] = min($setor['arr_tempo_resposta_parecer']);
                $data['setores'][$key]['tot_tempo_resposta_parecer_maximo'] = max($setor['arr_tempo_resposta_parecer']);
                $data['setores'][$key]['tot_tempo_resposta_parecer_medio'] = $calc_obj->calc_average($setor['arr_tempo_resposta_parecer']);
                $data['setores'][$key]['tot_tempo_resposta_parecer_mediano'] = $calc_obj->calculate_median($setor['arr_tempo_resposta_parecer']);
                $data['setores'][$key]['tot_tempo_resposta_parecer_desvio_padrao'] = $calc_obj->standard_deviation($setor['arr_tempo_resposta_parecer']);
            }
        }

        foreach ($data['especialidade_destino'] as $key => $specialty)
        {
            if ($specialty['tot_pareceres'] > 0)
            {
                if ($specialty['tot_pareceres_nao_respondidos'] > 0)
                {
                    $data['especialidade_destino'][$key]['percen_pareceres_nao_respondidos'] = ($specialty['tot_pareceres_nao_respondidos'] * 100) / $specialty['tot_pareceres'];
                    $data['especialidade_destino'][$key]['percen_pareceres_nao_respondidos'] = round($data['especialidade_destino'][$key]['percen_pareceres_nao_respondidos'], 2);
                }

                $data['especialidade_destino'][$key]['percen_pareceres'] = ($specialty['tot_pareceres'] * 100) / $data['total_de_registros'];
                $data['especialidade_destino'][$key]['percen_pareceres'] = round($data['especialidade_destino'][$key]['percen_pareceres'], 2);
            }

            if (count($specialty['arr_tempo_resposta_parecer']) > 0)
            {
                $data['especialidade_destino'][$key]['tot_tempo_resposta_parecer_minimo'] = min($specialty['arr_tempo_resposta_parecer']);
                $data['especialidade_destino'][$key]['tot_tempo_resposta_parecer_maximo'] = max($specialty['arr_tempo_resposta_parecer']);
                $data['especialidade_destino'][$key]['tot_tempo_resposta_parecer_medio'] = $calc_obj->calc_average($specialty['arr_tempo_resposta_parecer']);
                $data['especialidade_destino'][$key]['tot_tempo_resposta_parecer_mediano'] = $calc_obj->calculate_median($specialty['arr_tempo_resposta_parecer']);
                $data['especialidade_destino'][$key]['tot_tempo_resposta_parecer_desvio_padrao'] = $calc_obj->standard_deviation($specialty['arr_tempo_resposta_parecer']);
            }
        }

        $data['id_pricipais_especialidades'] = [];
        $principais_especialidades = $data['especialidade_destino'];
        $principais_setores = $data['setores'];
        $count_5_setores = 0;
        $count_5_especialidades = 0;

        //ordena as principais especialdiades
        usort($principais_setores, function ($a, $b)
        {
            return $a['tot_pareceres'] < $b['tot_pareceres'];
        });

        //seleciona somente as 5 principais especialidades
        foreach ($principais_especialidades as $key => $especialidade)
        {
            $count_5_especialidades++;
            if ($count_5_especialidades > 5)
            {
                unset($principais_especialidades[$key]);
            }
            else
            {
                array_push($data['id_pricipais_especialidades'], $especialidade['specialty_id']);
            }
        }

        ///ordena os principais setores
        // usort($principais_setores, function ($a, $b)
        // {
        //     return $a['tot_pareceres'] < $b['tot_pareceres'];
        // });

        //seleciona somente os 5 principais setores
        foreach ($principais_setores as $key => $setor)
        {
            $count_5_setores++;
            if ($count_5_setores > 5)
            {
                unset($principais_setores[$key]);
            }
            else
            {
                foreach ($setor['especialidade_destino'] as $key_especialidade => $especialidade)
                {
                    //seleciona somente as especialidades principais
                    if (!in_array($especialidade['specialty_id'], $data['id_pricipais_especialidades']))
                    {
                        unset($principais_setores[$key]['especialidade_destino'][$key_especialidade]);
                    }
                    else if ($especialidade['tot_pareceres'] > 0)
                    {
                        $principais_setores[$key]['especialidade_destino'][$key_especialidade]['percen_pareceres'] = ($especialidade['tot_pareceres'] * 100) / $data['total_de_registros'];
                        $principais_setores[$key]['especialidade_destino'][$key_especialidade]['percen_pareceres'] = round($principais_setores[$key]['especialidade_destino'][$key_especialidade]['percen_pareceres'], 2);
                    }
                }
            }
        }

        $data['principais_setores'] = $principais_setores;
        $data['principais_especialidades'] = $principais_especialidades;

        return $data;
    }

    /**
     * Default validation rules.
     *
     * @param \Cake\Validation\Validator $validator Validator instance.
     * @return \Cake\Validation\Validator
     */
    public function validationDefault(Validator $validator)
    {
        $validator
            ->integer('id')
            ->allowEmpty('id', 'create');

        $validator
            ->requirePresence('motive', 'create')
            ->notEmpty('motive');

        return $validator;
    }

    /**
     * Returns a rules checker object that will be used for validating
     * application integrity.
     *
     * @param \Cake\ORM\RulesChecker $rules The rules object to be modified.
     * @return \Cake\ORM\RulesChecker
     */
    public function buildRules(RulesChecker $rules)
    {
        $rules->add($rules->existsIn(['specialty_id'], 'Specialties'));
        $rules->add($rules->existsIn(['user_id'], 'Users'));
        $rules->add($rules->existsIn(['hospitalization_id'], 'Hospitalizations'));
        return $rules;
    }
}
