<?php

namespace App\Controllers;
use \App\Libraries\Complementos;
use \App\Libraries\Globales;
use \App\Libraries\Scripts;
use \App\Libraries\Error;
use \App\Libraries\Alertas;
use \App\Libraries\Pdf;

require 'vendor/autoload.php';
use PhpOffice\PhpSpreadsheet\Spreadsheet;
use PhpOffice\PhpSpreadsheet\Writer\Xlsx;
use PhpOffice\PhpSpreadsheet\IOFactory;
use PhpOffice\PhpSpreadsheet\Cell\Coordinate;

use Box\Spout\Writer\Common\Creator\WriterEntityFactory;
use Box\Spout\Common\Entity\Row;

class Metricas extends BaseController
{
	public function __construct(){
		$this->usuarioModelo = new \App\Models\UsuarioModelo();
		$this->perfilModelo = new \App\Models\PerfilModelo();
		$this->subAccionModelo = new \App\Models\SubAccionModelo();
        $this->direccionModelo = new \App\Models\DireccionModel();
        $this->ubicacionAcceso = new \App\Models\DireccionUbicacionAccesoModel();
        $this->departamentoINEI = new \App\Models\INEIDepartamentoModel();
        $this->provinciaINEI = new \App\Models\INEIProvinciaModel();
        $this->distritoINEI = new \App\Models\INEIDistritoModel();
        $this->modulo = new \App\Models\ModuloModel();
        $this->moduloAcciones = new \App\Models\ModulosAccionesModel();
        $this->moduloRutas = new \App\Models\ModulosRutasModel();
        $this->moduloCabecera = new \App\Models\ModulosCabeceraModel();
        $this->perfilPermisos = new \App\Models\PerfilPermisosModelo();
        $this->perfilRutas = new \App\Models\PerfilRutasModelo();
        
        $this->grupoTrabajo = new \App\Models\GruposTrabajoModel();
        $this->grupoTrabajoUsuarios = new \App\Models\UsuarioGruposTrabajoModel();
        $this->horarios = new \App\Models\HorariosModel();
        $this->asistencia = new \App\Models\AsistenciaModel();
        $this->planificacion = new \App\Models\PlanificacionModel();
        $this->metricasDesempeno = new \App\Models\MetricasDesempenoModel();
        $this->categoriaMetrica = new \App\Models\CategoriaMetricaModel();
        $this->kpiMetrica = new \App\Models\KpiMetricaModel();
        $this->pagosMetrica = new \App\Models\PagosMetricaModel();
        $this->tempMetricasComplementarias = new \App\Models\TempMetricasComplementariasModel();
        
        $this->sistemas = new \App\Models\SistemasModel();
		$this->departamentos = new \App\Models\DepartamentoModel();
        $this->areas = new \App\Models\AreaModel();
        $this->cargos = new \App\Models\CargosModel();
        
        
        $this->estructuraDirecciones = new \App\Models\EstructuraDireccionModel();
        $this->estructuraAreas = new \App\Models\EstructuraAreaModel();
        $this->estructuraSubareas = new \App\Models\EstructuraSubareaModel();
        $this->estructuraSubareaDelegaciones = new \App\Models\EstructuraSubareaDelegacionesModel();
        $this->estructuraDelegaciones = new \App\Models\EstructuraDelegacionModel();
	}
	
	public function listarMetrcias(){
		if(isset($this->items['id'])){
		    $idUsuarioPlanificacion = $this->items['id'];
		    
            $fechaActual = date("Y-m-d");
    		
            $whereMetrica = array('p.FechaTrabajo >=' => '2024-09-02',
                                  'p.FechaTrabajo <=' => $fechaActual);   
                                  
            $dataMetricas = $this->usuarioModelo
                ->select('
                    tblusuario.idUsuario, 
                    tblusuario.Nombres, 
                    tblusuario.Apellidos, 
                    DATEDIFF(CURDATE(), tblusuario.FechaIngreso) / 30 AS meses_en_empresa,
                    md.categoria, 
                    md.cumplimiento_procesos, md.atencion_cliente, md.tmo, md.productividad, md.wp,
                    k1.kpi_dia AS kpi_cumplimiento_procesos, k2.kpi_dia AS kpi_atencion_cliente, k3.kpi_dia AS kpi_tmo, 
                    k4.kpi_dia AS kpi_productividad, k5.kpi_dia AS kpi_wp,
                    p1.pago_above AS pago_above_cp, p1.pago_target AS pago_target_cp, p1.pago_over AS pago_over_cp,
                    p2.pago_above AS pago_above_ac, p2.pago_target AS pago_target_ac, p2.pago_over AS pago_over_ac,
                    p3.pago_above AS pago_above_tmo, p3.pago_target AS pago_target_tmo, p3.pago_over AS pago_over_tmo,
                    p4.pago_above AS pago_above_product, p4.pago_target AS pago_target_product, p4.pago_over AS pago_over_product,
                    p5.pago_above AS pago_above_wp, p5.pago_target AS pago_target_wp, p5.pago_over AS pago_over_wp,
                    
                        -- Cálculo de bonificación para Cumplimiento de Procesos
                    ROUND(
                        CASE 
                            WHEN md.cumplimiento_procesos * 100 < k1.kpi_dia * k1.porcentaje_above THEN 0
                            WHEN md.cumplimiento_procesos * 100 >= k1.kpi_dia * k1.porcentaje_above AND md.cumplimiento_procesos * 100 < k1.kpi_dia THEN (p1.pago_above * k1.peso) / 100
                            WHEN md.cumplimiento_procesos * 100 >= k1.kpi_dia AND md.cumplimiento_procesos * 100 < k1.kpi_dia * k1.porcentaje_over THEN (p1.pago_target * k1.peso) / 100
                            ELSE (p1.pago_over * k1.peso) / 100
                        END) AS bonificacion_cumplimiento_procesos,
                    
                        -- Cálculo de % de Cumplimiento de Procesos
                    ROUND(
                        CASE 
                            WHEN (md.cumplimiento_procesos * 100 / k1.kpi_dia)*100 >= 110 THEN 110
                            ELSE (md.cumplimiento_procesos * 100 / k1.kpi_dia) * 100
                        END) AS cumplimiento_cumplimiento_procesos,
                    
                        -- Cálculo de bonificación para Atención al Cliente
                    ROUND(
                        CASE 
                            WHEN md.atencion_cliente * 100 < k2.kpi_dia * k2.porcentaje_above THEN 0
                            WHEN md.atencion_cliente * 100 >= k2.kpi_dia * k2.porcentaje_above AND md.atencion_cliente * 100 < k2.kpi_dia THEN (p2.pago_above * k2.peso) / 100
                            WHEN md.atencion_cliente * 100 >= k2.kpi_dia AND md.atencion_cliente * 100 < k2.kpi_dia * k2.porcentaje_over THEN (p2.pago_target * k2.peso) / 100
                            ELSE (p2.pago_over * k2.peso) / 100
                        END) AS bonificacion_atencion_cliente,
                    
                        -- Cálculo de % de Cumplimiento de Atención al Cliente
                    ROUND(
                        CASE 
                            WHEN (md.atencion_cliente * 100 / k2.kpi_dia) >= 110 THEN 110
                            ELSE (md.atencion_cliente * 100 / k2.kpi_dia) * 100
                        END) AS cumplimiento_atencion_cliente,
                    
                        -- Cálculo de bonificación para TMO
                    ROUND(
                        CASE 
                            WHEN md.tmo * 100 < k3.kpi_dia * k3.porcentaje_above THEN 0
                            WHEN md.tmo * 100 >= k3.kpi_dia * k3.porcentaje_above AND md.tmo * 100 < k3.kpi_dia THEN (p3.pago_above * k3.peso) / 100
                            WHEN md.tmo * 100 >= k3.kpi_dia AND md.tmo * 100 < k3.kpi_dia * k3.porcentaje_over THEN (p3.pago_target * k3.peso) / 100
                            ELSE (p3.pago_over * k3.peso) / 100
                        END) AS bonificacion_tmo,
                    
                        -- Cálculo de % de Cumplimiento de TMO
                    ROUND(
                        CASE 
                            WHEN (k3.kpi_dia / md.tmo) * 100 >= 110 THEN 110
                            ELSE (k3.kpi_dia / md.tmo) * 100
                        END) AS cumplimiento_tmo,
                    
                        -- Cálculo de bonificación para Productividad
                    ROUND(
                        CASE 
                            WHEN md.productividad < k4.kpi_dia * k4.porcentaje_above THEN 0
                            WHEN md.productividad >= k4.kpi_dia * k4.porcentaje_above AND md.productividad < k4.kpi_dia THEN (p4.pago_above * k4.peso) / 100
                            WHEN md.productividad >= k4.kpi_dia AND md.productividad < k4.kpi_dia * k4.porcentaje_over THEN (p4.pago_target * k4.peso) / 100
                            ELSE (p4.pago_over * k4.peso) / 100
                        END) AS bonificacion_productividad,
                    
                        -- Cálculo de % de Cumplimiento de Productividad
                    ROUND(
                        CASE 
                            WHEN (md.productividad / k4.kpi_dia) * 100 >= 110 THEN 110
                            ELSE (md.productividad / k4.kpi_dia) * 100
                        END) AS cumplimiento_productividad,
                    
                        -- Cálculo de bonificación para WP
                    ROUND(
                        CASE 
                            WHEN md.wp < k5.kpi_dia * k5.porcentaje_above THEN 0
                            WHEN md.wp >= k5.kpi_dia * k5.porcentaje_above AND md.wp < k5.kpi_dia THEN (p5.pago_above * k5.peso) / 100
                            WHEN md.wp >= k5.kpi_dia AND md.wp < k5.kpi_dia * k5.porcentaje_over THEN (p5.pago_target * k5.peso) / 100
                            ELSE (p5.pago_over * k5.peso) / 100
                        END) AS bonificacion_wp,
                    
                        -- Cálculo de % de Cumplimiento de WP
                    ROUND(
                        CASE 
                            WHEN (k5.kpi_noche / md.wp) * 100 >= 110 THEN 110
                            ELSE (k5.kpi_noche / md.wp) * 100
                        END) AS cumplimiento_wp,
                    
                        -- Cálculo del desempeño final basado en la suma de cumplimientos
                    ROUND
                        (ROUND(
                            CASE 
                                WHEN (md.cumplimiento_procesos * 100 / k1.kpi_dia)*100 >= 110 THEN 110
                                ELSE (md.cumplimiento_procesos * 100 / k1.kpi_dia) * 100
                            END,2) * 0.30 + 
                        ROUND(
                            CASE 
                                WHEN (md.atencion_cliente * 100 / k2.kpi_dia) >= 110 THEN 110
                                ELSE (md.atencion_cliente * 100 / k2.kpi_dia) * 100
                            END,2) * 0.30 + 
                        ROUND(
                            CASE 
                                WHEN (k3.kpi_dia / md.tmo) * 100 >= 110 THEN 110
                                ELSE (k3.kpi_dia / md.tmo) * 100
                            END,2) * 0.15 + 
                        ROUND(
                            CASE 
                                WHEN (md.productividad / k4.kpi_dia) * 100 >= 110 THEN 110
                                ELSE (md.productividad / k4.kpi_dia) * 100
                            END,2) * 0.15 + 
                        ROUND(
                            CASE 
                                WHEN (k5.kpi_noche / md.wp) * 100 >= 110 THEN 110
                                ELSE (k5.kpi_noche / md.wp) * 100
                            END,2) * 0.10)  AS desempeno_final,

                    -- Horas trabajadas
                    CASE
                        -- Horarios que cruzan la medianoche
                        WHEN h.HoraFin < h.HoraInicio THEN 
                            TIME_FORMAT(SEC_TO_TIME(SUM(TIME_TO_SEC(
                                TIMEDIFF(
                                    -- Si la hora de salida es al día siguiente, ajustamos el cálculo
                                    IF(a_fin.FechaHoraRegistro < CONCAT(p.FechaTrabajo, " ", h.HoraInicio), 
                                        CONCAT(DATE_ADD(p.FechaTrabajo, INTERVAL 1 DAY), " ", h.HoraFin), 
                                        a_fin.FechaHoraRegistro), 
                                    a_inicio.FechaHoraRegistro)
                            ))), "%H:%i:%s")
                        ELSE 
                            -- Horarios normales
                            TIME_FORMAT(SEC_TO_TIME(SUM(TIME_TO_SEC(TIMEDIFF(a_fin.FechaHoraRegistro, a_inicio.FechaHoraRegistro)))), "%H:%i:%s")
                    END AS horas_trabajadas,
                    
                    -- Tardanzas
                    CASE
                        -- Horarios que cruzan la medianoche
                        WHEN h.HoraFin < h.HoraInicio THEN 
                            CASE 
                               
                                WHEN a_inicio.FechaHoraRegistro > CONCAT(p.FechaTrabajo, " ", h.HoraInicio) THEN 
                                    TIME_FORMAT(SEC_TO_TIME(SUM(TIME_TO_SEC(TIMEDIFF(a_inicio.FechaHoraRegistro, CONCAT(p.FechaTrabajo, " ", h.HoraInicio))))), "%H:%i:%s")
                                
                                WHEN a_inicio.FechaHoraRegistro > CONCAT(DATE_ADD(p.FechaTrabajo, INTERVAL 1 DAY), " ", h.HoraFin) THEN 
                                    TIME_FORMAT(SEC_TO_TIME(SUM(TIME_TO_SEC(TIMEDIFF(a_inicio.FechaHoraRegistro, CONCAT(DATE_ADD(p.FechaTrabajo, INTERVAL 1 DAY), " ", h.HoraFin))))), "%H:%i:%s")
                                ELSE "00:00:00"
                            END
                        ELSE
                            -- Horarios normales que no cruzan la medianoche
                            CASE 
                                WHEN a_inicio.FechaHoraRegistro > CONCAT(p.FechaTrabajo, " ", h.HoraInicio) THEN 
                                    TIME_FORMAT(SEC_TO_TIME(SUM(TIME_TO_SEC(TIMEDIFF(a_inicio.FechaHoraRegistro, CONCAT(p.FechaTrabajo, " ", h.HoraInicio))))), "%H:%i:%s")
                                ELSE "00:00:00"
                            END
                    END AS tardanza,
                    
                    -- Horas extras
                    CASE
                        -- Horarios que cruzan la medianoche
                        WHEN h.HoraFin < h.HoraInicio THEN
                            CASE
                                -- Si la hora de salida es mayor que la hora fin al día siguiente
                                WHEN a_fin.FechaHoraRegistro > CONCAT(DATE_ADD(p.FechaTrabajo, INTERVAL 1 DAY), " ", h.HoraFin) THEN 
                                    TIMEDIFF(a_fin.FechaHoraRegistro, CONCAT(DATE_ADD(p.FechaTrabajo, INTERVAL 1 DAY), " ", h.HoraFin))
                                ELSE "00:00:00"
                            END
                        ELSE
                            -- Horarios normales
                            CASE
                                WHEN a_fin.FechaHoraRegistro > CONCAT(p.FechaTrabajo, " ", h.HoraFin) THEN 
                                    TIMEDIFF(a_fin.FechaHoraRegistro, CONCAT(p.FechaTrabajo, " ", h.HoraFin))
                                ELSE "00:00:00"
                            END
                    END AS horas_extras,
                    
                    -- Faltas
                    COUNT(CASE 
                        -- Si no hay registro de inicio ni fin
                        WHEN a_inicio.FechaHoraRegistro IS NULL AND a_fin.FechaHoraRegistro IS NULL THEN 1
                        -- Horarios que cruzan la medianoche
                        WHEN h.HoraFin < h.HoraInicio AND 
                             a_inicio.FechaHoraRegistro IS NULL AND a_fin.FechaHoraRegistro IS NULL THEN 1
                    END) AS total_faltas
                ')
                ->join('tbl_metricas_desempeno md', 'tblusuario.idUsuario = md.idUsuario')
                
                ->join('planificacion p', 'p.IdUsuario = tblusuario.idUsuario')
                ->join('horarios h', 'p.id_horario = h.id_horario')
                ->join('asistencia a_inicio', 'p.IdUsuario = a_inicio.IdUsuario AND a_inicio.TipoRegistro = "inicio" AND a_inicio.FechaHoraRegistro LIKE CONCAT(p.FechaTrabajo, "%") AND a_inicio.id_horario = p.id_horario','left')
                ->join('asistencia a_fin', 'p.IdUsuario = a_fin.IdUsuario AND a_fin.TipoRegistro = "fin" AND a_fin.FechaHoraRegistro LIKE CONCAT(p.FechaTrabajo, "%") AND a_fin.id_horario = p.id_horario','left')
                
                ->join('tbl_categoria_metrica c', 'md.categoria = c.nombre_categoria')
                
                // -- Uniones con las métricas de cada subcriterio
                ->join('tbl_kpi_metrica k1', 'c.id_categoria = k1.id_categoria AND k1.id_subcriterio = 1')
                ->join('tbl_pagos_metrica p1', 'c.id_categoria = p1.id_categoria AND p1.id_subcriterio = 1')
                
                ->join('tbl_kpi_metrica k2', 'c.id_categoria = k2.id_categoria AND k2.id_subcriterio = 2')
                ->join('tbl_pagos_metrica p2', 'c.id_categoria = p2.id_categoria AND p2.id_subcriterio = 2')
            
                ->join('tbl_kpi_metrica k3', 'c.id_categoria = k3.id_categoria AND k3.id_subcriterio = 3')
                ->join('tbl_pagos_metrica p3', 'c.id_categoria = p3.id_categoria AND p3.id_subcriterio = 3')
            
                ->join('tbl_kpi_metrica k4', 'c.id_categoria = k4.id_categoria AND k4.id_subcriterio = 4')
                ->join('tbl_pagos_metrica p4', 'c.id_categoria = p4.id_categoria AND p4.id_subcriterio = 4')
            
                ->join('tbl_kpi_metrica k5', 'c.id_categoria = k5.id_categoria AND k5.id_subcriterio = 5')
                ->join('tbl_pagos_metrica p5', 'c.id_categoria = p5.id_categoria AND p5.id_subcriterio = 5')
                ->groupBy('tblusuario.idUsuario')
                ->where($whereMetrica)
            
                ->findAll();
                
                
                /***************************** CALCULO PARA BONO DESEMPEÑO ************************************/
                foreach ($dataMetricas as &$usuario) {
                    $bonoDesempeno = 0;
                    if ($usuario['tardanza'] > '00:10:00') {
                        $bonoDesempeno = 0; // Si hay tardanza mayor a 10 minutos, el bono es 0
                    } else {
                        
                        $whereCategoriaMetrica = array('nombre_categoria' => $usuario['categoria']);
                        $dataBono = $this->categoriaMetrica->where($whereCategoriaMetrica)->first();
                            // Dependiendo de la categoría del usuario, calculamos el bono
                        if(!empty($dataBono)){
                            switch ($usuario['categoria']) {
                                case 'Elite':
                                    if ($usuario['desempeno_final'] >= 100) {
                                        $bonoDesempeno = $dataBono['bono_100']; // Valor para categoría Elite con desempeño >= 100
                                    } elseif ($usuario['desempeno_final'] >= 90) {
                                        $bonoDesempeno = $dataBono['bono_90']; // Valor para categoría Elite con desempeño >= 90
                                    }
                                    break;
                    
                                case 'Senior':
                                    if ($usuario['desempeno_final'] >= 100) {
                                        $bonoDesempeno = $dataBono['bono_100']; 
                                    } elseif ($usuario['desempeno_final'] >= 90) {
                                        $bonoDesempeno = $dataBono['bono_90'];
                                    }
                                    break;
                    
                                case 'Junior':
                                    if ($usuario['desempeno_final'] >= 100) {
                                        $bonoDesempeno = $dataBono['bono_100'];
                                    } elseif ($usuario['desempeno_final'] >= 90) {
                                        $bonoDesempeno = $dataBono['bono_90'];
                                    }
                                    break;
                    
                                case 'Trainee':
                                    if ($usuario['desempeno_final'] >= 100) {
                                        $bonoDesempeno = $dataBono['bono_100'];
                                    } elseif ($usuario['desempeno_final'] >= 90) {
                                        $bonoDesempeno = $dataBono['bono_90'];
                                    }
                                    break;
                    
                                default:
                                    $bonoDesempeno = 0; // Si no pertenece a ninguna categoría conocida, el bono es 0
                                    break;
                            }
                        }
                    }
                    // Añadir el bono de desempeño al arreglo del usuario
                    $usuario['bono_desempeno'] = $bonoDesempeno;
                    
                    /***************************** FIN CALCULO PARA BONO DESEMPEÑO ************************************/
                    
                    
                    /***************************** COMISION TOTAL ************************************/
                    
                    if($usuario['meses_en_empresa'] < 1 and $usuario['total_faltas'] <2 and $usuario['tardanza'] < 11 ){
                        $usuario['comision_total'] = 70;
                    }else if($usuario['meses_en_empresa'] >= 4){
                        $usuario['comision_total'] = $usuario['bonificacion_cumplimiento_procesos'] + $usuario['bonificacion_atencion_cliente'] + $usuario['bonificacion_tmo'] + $usuario['bonificacion_productividad'] + $usuario['bonificacion_wp'] + $bonoDesempeno;
                    }else{
                        $usuario['comision_total'] = 0;
                    }
                    
                    /***************************** FIN COMISION TOTAL ************************************/
                    
                    /*************************** VALIDACION HORAS TRABAJADAS ******************************/
                    
                    if($usuario['horas_trabajadas'] == NULL ){
                        $usuario['horas_trabajadas'] = 0;
                    }
                    
                    /*************************** VALIDACION HORAS TRABAJADAS ******************************/
                }
            // var_dump($dataMetricas); exit();
                
                $data = array (
				'session'               => 'on',
				'titulo'                => 'Planificación | Verisure',
				'breadcrumb'            => $this->items['modulo'],
				'breadcrumb_alias'      => 'Listado de planificación',
				'idUsuarioPlanificacion'    => $idUsuarioPlanificacion,
				'dataMetricas' => $dataMetricas
    			);
    			
    			$data = array_merge($data, $this->items);
    			
    			return view('metricas/listar_metricas',$data);
    			
        	
		} else {
			return view('errors/500');	
		}
        
	}

	
	public function exportarMetricas()
	{
        /************************************************/
            $fechaActual = date("Y-m-d");
    		
            $whereMetrica = array('p.FechaTrabajo >=' => '2024-09-02',
                                  'p.FechaTrabajo <=' => $fechaActual);   
                                  
            $dataMetricas = $this->usuarioModelo
                ->select('
                    tblusuario.idUsuario, 
                    tblusuario.Nombres, 
                    tblusuario.Apellidos, 
                    DATEDIFF(CURDATE(), tblusuario.FechaIngreso) / 30 AS meses_en_empresa,
                    md.categoria, 
                    md.cumplimiento_procesos, md.atencion_cliente, md.tmo, md.productividad, md.wp,
                    k1.kpi_dia AS kpi_cumplimiento_procesos, k2.kpi_dia AS kpi_atencion_cliente, k3.kpi_dia AS kpi_tmo, 
                    k4.kpi_dia AS kpi_productividad, k5.kpi_dia AS kpi_wp,
                    p1.pago_above AS pago_above_cp, p1.pago_target AS pago_target_cp, p1.pago_over AS pago_over_cp,
                    p2.pago_above AS pago_above_ac, p2.pago_target AS pago_target_ac, p2.pago_over AS pago_over_ac,
                    p3.pago_above AS pago_above_tmo, p3.pago_target AS pago_target_tmo, p3.pago_over AS pago_over_tmo,
                    p4.pago_above AS pago_above_product, p4.pago_target AS pago_target_product, p4.pago_over AS pago_over_product,
                    p5.pago_above AS pago_above_wp, p5.pago_target AS pago_target_wp, p5.pago_over AS pago_over_wp,
                    
                        -- Cálculo de bonificación para Cumplimiento de Procesos
                    ROUND(
                        CASE 
                            WHEN md.cumplimiento_procesos * 100 < k1.kpi_dia * k1.porcentaje_above THEN 0
                            WHEN md.cumplimiento_procesos * 100 >= k1.kpi_dia * k1.porcentaje_above AND md.cumplimiento_procesos * 100 < k1.kpi_dia THEN (p1.pago_above * k1.peso) / 100
                            WHEN md.cumplimiento_procesos * 100 >= k1.kpi_dia AND md.cumplimiento_procesos * 100 < k1.kpi_dia * k1.porcentaje_over THEN (p1.pago_target * k1.peso) / 100
                            ELSE (p1.pago_over * k1.peso) / 100
                        END) AS bonificacion_cumplimiento_procesos,
                    
                        -- Cálculo de % de Cumplimiento de Procesos
                    ROUND(
                        CASE 
                            WHEN (md.cumplimiento_procesos * 100 / k1.kpi_dia)*100 >= 110 THEN 110
                            ELSE (md.cumplimiento_procesos * 100 / k1.kpi_dia) * 100
                        END) AS cumplimiento_cumplimiento_procesos,
                    
                        -- Cálculo de bonificación para Atención al Cliente
                    ROUND(
                        CASE 
                            WHEN md.atencion_cliente * 100 < k2.kpi_dia * k2.porcentaje_above THEN 0
                            WHEN md.atencion_cliente * 100 >= k2.kpi_dia * k2.porcentaje_above AND md.atencion_cliente * 100 < k2.kpi_dia THEN (p2.pago_above * k2.peso) / 100
                            WHEN md.atencion_cliente * 100 >= k2.kpi_dia AND md.atencion_cliente * 100 < k2.kpi_dia * k2.porcentaje_over THEN (p2.pago_target * k2.peso) / 100
                            ELSE (p2.pago_over * k2.peso) / 100
                        END) AS bonificacion_atencion_cliente,
                    
                        -- Cálculo de % de Cumplimiento de Atención al Cliente
                    ROUND(
                        CASE 
                            WHEN (md.atencion_cliente * 100 / k2.kpi_dia) >= 110 THEN 110
                            ELSE (md.atencion_cliente * 100 / k2.kpi_dia) * 100
                        END) AS cumplimiento_atencion_cliente,
                    
                        -- Cálculo de bonificación para TMO
                    ROUND(
                        CASE 
                            WHEN md.tmo * 100 < k3.kpi_dia * k3.porcentaje_above THEN 0
                            WHEN md.tmo * 100 >= k3.kpi_dia * k3.porcentaje_above AND md.tmo * 100 < k3.kpi_dia THEN (p3.pago_above * k3.peso) / 100
                            WHEN md.tmo * 100 >= k3.kpi_dia AND md.tmo * 100 < k3.kpi_dia * k3.porcentaje_over THEN (p3.pago_target * k3.peso) / 100
                            ELSE (p3.pago_over * k3.peso) / 100
                        END) AS bonificacion_tmo,
                    
                        -- Cálculo de % de Cumplimiento de TMO
                    ROUND(
                        CASE 
                            WHEN (k3.kpi_dia / md.tmo) * 100 >= 110 THEN 110
                            ELSE (k3.kpi_dia / md.tmo) * 100
                        END) AS cumplimiento_tmo,
                    
                        -- Cálculo de bonificación para Productividad
                    ROUND(
                        CASE 
                            WHEN md.productividad < k4.kpi_dia * k4.porcentaje_above THEN 0
                            WHEN md.productividad >= k4.kpi_dia * k4.porcentaje_above AND md.productividad < k4.kpi_dia THEN (p4.pago_above * k4.peso) / 100
                            WHEN md.productividad >= k4.kpi_dia AND md.productividad < k4.kpi_dia * k4.porcentaje_over THEN (p4.pago_target * k4.peso) / 100
                            ELSE (p4.pago_over * k4.peso) / 100
                        END) AS bonificacion_productividad,
                    
                        -- Cálculo de % de Cumplimiento de Productividad
                    ROUND(
                        CASE 
                            WHEN (md.productividad / k4.kpi_dia) * 100 >= 110 THEN 110
                            ELSE (md.productividad / k4.kpi_dia) * 100
                        END) AS cumplimiento_productividad,
                    
                        -- Cálculo de bonificación para WP
                    ROUND(
                        CASE 
                            WHEN md.wp < k5.kpi_dia * k5.porcentaje_above THEN 0
                            WHEN md.wp >= k5.kpi_dia * k5.porcentaje_above AND md.wp < k5.kpi_dia THEN (p5.pago_above * k5.peso) / 100
                            WHEN md.wp >= k5.kpi_dia AND md.wp < k5.kpi_dia * k5.porcentaje_over THEN (p5.pago_target * k5.peso) / 100
                            ELSE (p5.pago_over * k5.peso) / 100
                        END) AS bonificacion_wp,
                    
                        -- Cálculo de % de Cumplimiento de WP
                    ROUND(
                        CASE 
                            WHEN (k5.kpi_noche / md.wp) * 100 >= 110 THEN 110
                            ELSE (k5.kpi_noche / md.wp) * 100
                        END) AS cumplimiento_wp,
                    
                        -- Cálculo del desempeño final basado en la suma de cumplimientos
                    ROUND
                        (ROUND(
                            CASE 
                                WHEN (md.cumplimiento_procesos * 100 / k1.kpi_dia)*100 >= 110 THEN 110
                                ELSE (md.cumplimiento_procesos * 100 / k1.kpi_dia) * 100
                            END,2) * 0.30 + 
                        ROUND(
                            CASE 
                                WHEN (md.atencion_cliente * 100 / k2.kpi_dia) >= 110 THEN 110
                                ELSE (md.atencion_cliente * 100 / k2.kpi_dia) * 100
                            END,2) * 0.30 + 
                        ROUND(
                            CASE 
                                WHEN (k3.kpi_dia / md.tmo) * 100 >= 110 THEN 110
                                ELSE (k3.kpi_dia / md.tmo) * 100
                            END,2) * 0.15 + 
                        ROUND(
                            CASE 
                                WHEN (md.productividad / k4.kpi_dia) * 100 >= 110 THEN 110
                                ELSE (md.productividad / k4.kpi_dia) * 100
                            END,2) * 0.15 + 
                        ROUND(
                            CASE 
                                WHEN (k5.kpi_noche / md.wp) * 100 >= 110 THEN 110
                                ELSE (k5.kpi_noche / md.wp) * 100
                            END,2) * 0.10)  AS desempeno_final,

                    -- Horas trabajadas
                    CASE
                        -- Horarios que cruzan la medianoche
                        WHEN h.HoraFin < h.HoraInicio THEN 
                            TIME_FORMAT(SEC_TO_TIME(SUM(TIME_TO_SEC(
                                TIMEDIFF(
                                    -- Si la hora de salida es al día siguiente, ajustamos el cálculo
                                    IF(a_fin.FechaHoraRegistro < CONCAT(p.FechaTrabajo, " ", h.HoraInicio), 
                                        CONCAT(DATE_ADD(p.FechaTrabajo, INTERVAL 1 DAY), " ", h.HoraFin), 
                                        a_fin.FechaHoraRegistro), 
                                    a_inicio.FechaHoraRegistro)
                            ))), "%H:%i:%s")
                        ELSE 
                            -- Horarios normales
                            TIME_FORMAT(SEC_TO_TIME(SUM(TIME_TO_SEC(TIMEDIFF(a_fin.FechaHoraRegistro, a_inicio.FechaHoraRegistro)))), "%H:%i:%s")
                    END AS horas_trabajadas,
                    
                    -- Tardanzas
                    CASE
                        -- Horarios que cruzan la medianoche
                        WHEN h.HoraFin < h.HoraInicio THEN 
                            CASE 
                               
                                WHEN a_inicio.FechaHoraRegistro > CONCAT(p.FechaTrabajo, " ", h.HoraInicio) THEN 
                                    TIME_FORMAT(SEC_TO_TIME(SUM(TIME_TO_SEC(TIMEDIFF(a_inicio.FechaHoraRegistro, CONCAT(p.FechaTrabajo, " ", h.HoraInicio))))), "%H:%i:%s")
                                
                                WHEN a_inicio.FechaHoraRegistro > CONCAT(DATE_ADD(p.FechaTrabajo, INTERVAL 1 DAY), " ", h.HoraFin) THEN 
                                    TIME_FORMAT(SEC_TO_TIME(SUM(TIME_TO_SEC(TIMEDIFF(a_inicio.FechaHoraRegistro, CONCAT(DATE_ADD(p.FechaTrabajo, INTERVAL 1 DAY), " ", h.HoraFin))))), "%H:%i:%s")
                                ELSE "00:00:00"
                            END
                        ELSE
                            -- Horarios normales que no cruzan la medianoche
                            CASE 
                                WHEN a_inicio.FechaHoraRegistro > CONCAT(p.FechaTrabajo, " ", h.HoraInicio) THEN 
                                    TIME_FORMAT(SEC_TO_TIME(SUM(TIME_TO_SEC(TIMEDIFF(a_inicio.FechaHoraRegistro, CONCAT(p.FechaTrabajo, " ", h.HoraInicio))))), "%H:%i:%s")
                                ELSE "00:00:00"
                            END
                    END AS tardanza,
                    
                    -- Horas extras
                    CASE
                        -- Horarios que cruzan la medianoche
                        WHEN h.HoraFin < h.HoraInicio THEN
                            CASE
                                -- Si la hora de salida es mayor que la hora fin al día siguiente
                                WHEN a_fin.FechaHoraRegistro > CONCAT(DATE_ADD(p.FechaTrabajo, INTERVAL 1 DAY), " ", h.HoraFin) THEN 
                                    TIMEDIFF(a_fin.FechaHoraRegistro, CONCAT(DATE_ADD(p.FechaTrabajo, INTERVAL 1 DAY), " ", h.HoraFin))
                                ELSE "00:00:00"
                            END
                        ELSE
                            -- Horarios normales
                            CASE
                                WHEN a_fin.FechaHoraRegistro > CONCAT(p.FechaTrabajo, " ", h.HoraFin) THEN 
                                    TIMEDIFF(a_fin.FechaHoraRegistro, CONCAT(p.FechaTrabajo, " ", h.HoraFin))
                                ELSE "00:00:00"
                            END
                    END AS horas_extras,
                    
                    -- Faltas
                    COUNT(CASE 
                        -- Si no hay registro de inicio ni fin
                        WHEN a_inicio.FechaHoraRegistro IS NULL AND a_fin.FechaHoraRegistro IS NULL THEN 1
                        -- Horarios que cruzan la medianoche
                        WHEN h.HoraFin < h.HoraInicio AND 
                             a_inicio.FechaHoraRegistro IS NULL AND a_fin.FechaHoraRegistro IS NULL THEN 1
                    END) AS total_faltas
                ')
                ->join('tbl_metricas_desempeno md', 'tblusuario.idUsuario = md.idUsuario')
                
                ->join('planificacion p', 'p.IdUsuario = tblusuario.idUsuario')
                ->join('horarios h', 'p.id_horario = h.id_horario')
                ->join('asistencia a_inicio', 'p.IdUsuario = a_inicio.IdUsuario AND a_inicio.TipoRegistro = "inicio" AND a_inicio.FechaHoraRegistro LIKE CONCAT(p.FechaTrabajo, "%") AND a_inicio.id_horario = p.id_horario','left')
                ->join('asistencia a_fin', 'p.IdUsuario = a_fin.IdUsuario AND a_fin.TipoRegistro = "fin" AND a_fin.FechaHoraRegistro LIKE CONCAT(p.FechaTrabajo, "%") AND a_fin.id_horario = p.id_horario','left')
                
                ->join('tbl_categoria_metrica c', 'md.categoria = c.nombre_categoria')
                
                // -- Uniones con las métricas de cada subcriterio
                ->join('tbl_kpi_metrica k1', 'c.id_categoria = k1.id_categoria AND k1.id_subcriterio = 1')
                ->join('tbl_pagos_metrica p1', 'c.id_categoria = p1.id_categoria AND p1.id_subcriterio = 1')
                
                ->join('tbl_kpi_metrica k2', 'c.id_categoria = k2.id_categoria AND k2.id_subcriterio = 2')
                ->join('tbl_pagos_metrica p2', 'c.id_categoria = p2.id_categoria AND p2.id_subcriterio = 2')
            
                ->join('tbl_kpi_metrica k3', 'c.id_categoria = k3.id_categoria AND k3.id_subcriterio = 3')
                ->join('tbl_pagos_metrica p3', 'c.id_categoria = p3.id_categoria AND p3.id_subcriterio = 3')
            
                ->join('tbl_kpi_metrica k4', 'c.id_categoria = k4.id_categoria AND k4.id_subcriterio = 4')
                ->join('tbl_pagos_metrica p4', 'c.id_categoria = p4.id_categoria AND p4.id_subcriterio = 4')
            
                ->join('tbl_kpi_metrica k5', 'c.id_categoria = k5.id_categoria AND k5.id_subcriterio = 5')
                ->join('tbl_pagos_metrica p5', 'c.id_categoria = p5.id_categoria AND p5.id_subcriterio = 5')
                ->groupBy('tblusuario.idUsuario')
                ->where($whereMetrica)
            
                ->findAll();
                
                
                /***************************** CALCULO PARA BONO DESEMPEÑO ************************************/
                foreach ($dataMetricas as &$usuario) {
                    $bonoDesempeno = 0;
                    if ($usuario['tardanza'] > '00:10:00') {
                        $bonoDesempeno = 0; // Si hay tardanza mayor a 10 minutos, el bono es 0
                    } else {
                        
                        $whereCategoriaMetrica = array('nombre_categoria' => $usuario['categoria']);
                        $dataBono = $this->categoriaMetrica->where($whereCategoriaMetrica)->first();
                            // Dependiendo de la categoría del usuario, calculamos el bono
                        if(!empty($dataBono)){
                            switch ($usuario['categoria']) {
                                case 'Elite':
                                    if ($usuario['desempeno_final'] >= 100) {
                                        $bonoDesempeno = $dataBono['bono_100']; // Valor para categoría Elite con desempeño >= 100
                                    } elseif ($usuario['desempeno_final'] >= 90) {
                                        $bonoDesempeno = $dataBono['bono_90']; // Valor para categoría Elite con desempeño >= 90
                                    }
                                    break;
                    
                                case 'Senior':
                                    if ($usuario['desempeno_final'] >= 100) {
                                        $bonoDesempeno = $dataBono['bono_100']; 
                                    } elseif ($usuario['desempeno_final'] >= 90) {
                                        $bonoDesempeno = $dataBono['bono_90'];
                                    }
                                    break;
                    
                                case 'Junior':
                                    if ($usuario['desempeno_final'] >= 100) {
                                        $bonoDesempeno = $dataBono['bono_100'];
                                    } elseif ($usuario['desempeno_final'] >= 90) {
                                        $bonoDesempeno = $dataBono['bono_90'];
                                    }
                                    break;
                    
                                case 'Trainee':
                                    if ($usuario['desempeno_final'] >= 100) {
                                        $bonoDesempeno = $dataBono['bono_100'];
                                    } elseif ($usuario['desempeno_final'] >= 90) {
                                        $bonoDesempeno = $dataBono['bono_90'];
                                    }
                                    break;
                    
                                default:
                                    $bonoDesempeno = 0; // Si no pertenece a ninguna categoría conocida, el bono es 0
                                    break;
                            }
                        }
                    }
                    // Añadir el bono de desempeño al arreglo del usuario
                    $usuario['bono_desempeno'] = $bonoDesempeno;
                    
                    /***************************** FIN CALCULO PARA BONO DESEMPEÑO ************************************/
                    
                    
                    /***************************** COMISION TOTAL ************************************/
                    
                    if($usuario['meses_en_empresa'] < 1 and $usuario['total_faltas'] <2 and $usuario['tardanza'] < 11 ){
                        $usuario['comision_total'] = 70;
                    }else if($usuario['meses_en_empresa'] >= 4){
                        $usuario['comision_total'] = $usuario['bonificacion_cumplimiento_procesos'] + $usuario['bonificacion_atencion_cliente'] + $usuario['bonificacion_tmo'] + $usuario['bonificacion_productividad'] + $usuario['bonificacion_wp'] + $bonoDesempeno;
                    }else{
                        $usuario['comision_total'] = 0;
                    }
                    
                    /***************************** FIN COMISION TOTAL ************************************/
                    
                    /*************************** VALIDACION HORAS TRABAJADAS ******************************/
                    
                    if($usuario['horas_trabajadas'] == NULL ){
                        $usuario['horas_trabajadas'] = 0;
                    }
                    
                    /*************************** VALIDACION HORAS TRABAJADAS ******************************/
                }

        /***********************************************/
	   // var_dump($this->tempMetricasComplementarias->findAll()); exit;
        $filename = "reporteMetricas.xlsx";
        $writer = WriterEntityFactory::createXLSXWriter();
        //$writer->setFieldDelimiter(';');
        $writer->setShouldUseInlineStrings(true); // default (and recommended) value
        $writer->openToBrowser($filename);
        
        $cells = [
            WriterEntityFactory::createCell("Nombres"),
            WriterEntityFactory::createCell("Apellidos"),
            WriterEntityFactory::createCell("categoria"),
            WriterEntityFactory::createCell("meses_en_empresa"),
            WriterEntityFactory::createCell("cumplimiento_cumplimiento_procesos"),
            WriterEntityFactory::createCell("bonificacion_cumplimiento_procesos"),
            WriterEntityFactory::createCell("cumplimiento_atencion_cliente"),
            WriterEntityFactory::createCell("bonificacion_atencion_cliente"),
            WriterEntityFactory::createCell("cumplimiento_tmo"),
            WriterEntityFactory::createCell("bonificacion_tmo"),
            WriterEntityFactory::createCell("cumplimiento_productividad"),
            WriterEntityFactory::createCell("bonificacion_productividad"),
            WriterEntityFactory::createCell("cumplimiento_wp"),
            WriterEntityFactory::createCell("bonificacion_wp"),
            WriterEntityFactory::createCell("desempeno_final"),
            WriterEntityFactory::createCell("horas_trabajadas"),
            WriterEntityFactory::createCell("tardanza"),
            WriterEntityFactory::createCell("horas_extras"),
            WriterEntityFactory::createCell("total_faltas"),
            WriterEntityFactory::createCell("bono_desempeno"),
            WriterEntityFactory::createCell("comision_total")
            
        ];
        
        /** add a row at a time */
        $singleRow = WriterEntityFactory::createRow($cells);
        $writer->addRow($singleRow);
        
        foreach($dataMetricas as $key=>$item)
        {
            
			$cells = [
                WriterEntityFactory::createCell($item["Nombres"]),
                WriterEntityFactory::createCell($item["Apellidos"]),
                WriterEntityFactory::createCell($item["categoria"]),
                WriterEntityFactory::createCell($item["meses_en_empresa"]),
                WriterEntityFactory::createCell($item["cumplimiento_cumplimiento_procesos"]),
                WriterEntityFactory::createCell($item["bonificacion_cumplimiento_procesos"]),
                WriterEntityFactory::createCell($item["cumplimiento_atencion_cliente"]),
                WriterEntityFactory::createCell($item["bonificacion_atencion_cliente"]),
                WriterEntityFactory::createCell($item["cumplimiento_tmo"]),
                WriterEntityFactory::createCell($item["bonificacion_tmo"]),
                WriterEntityFactory::createCell($item["cumplimiento_productividad"]),
                WriterEntityFactory::createCell($item["bonificacion_productividad"]),
                WriterEntityFactory::createCell($item["cumplimiento_wp"]),
                WriterEntityFactory::createCell($item["bonificacion_wp"]),
                WriterEntityFactory::createCell($item["desempeno_final"]),
                WriterEntityFactory::createCell($item["horas_trabajadas"]),
                WriterEntityFactory::createCell($item["tardanza"]),
                WriterEntityFactory::createCell($item["horas_extras"]),
                WriterEntityFactory::createCell($item["total_faltas"]),
                WriterEntityFactory::createCell($item["bono_desempeno"]),
                WriterEntityFactory::createCell($item["comision_total"]),
            ];
            
            /** add a row at a time */
            $singleRow = WriterEntityFactory::createRow($cells);
            $writer->addRow($singleRow);

        }
        
        $writer->close();
	   
	}
}