<?php

namespace App\Http\Controllers;

use Illuminate\Http\Request;
use Illuminate\Support\Facades\Validator;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Carbon;

use App\Http\Controllers\EncController;
use App\Http\Controllers\CorreoController;
use App\Http\Controllers\FunctionsController;

use PDOException;

class MESMAVController extends Controller{
    public function aprobarOld(Request $request){
        $validator = Validator::make($request->all(), [
            'id_solicitud' => 'required|integer',
            'id_usuario_autoriza' => 'required|string|max:50',
            'estatus' => 'required|string|in:Aprobado,Rechazado',
            'motivo_rechazo' => 'required_if:estatus,==,Rechazado|string',
            'rfc_empresa' => 'required|string',
        ]);

        if ($validator->fails()) {
            return $this->makeResponse(
                true,
                "ERR_MCOMPV_USU_APR000: Se encontraron uno o más errores",
                $this->makeErrors($validator->errors()->messages()),
                400
            );
        }

        $solicitud = $request->all();
        //Se consulta la politica de vacaciones del usuario para saber los días disponibles de los periodos actual y anterior
        $pdo = DB::connection()->getPdo();
        $qryPoli = "SELECT USUA_FEIN, USUA_IDUS, POLI_DVAA, SOVA_NUDI, SOVA_FEIN, SOVA_FEFI FROM S001V01TUSUA INNER JOIN S001V01TPOLI ON POLI_IDPO = USUA_POLI 
        INNER JOIN S001V01TSOVA ON SOVA_IDUS = USUA_IDUS WHERE SOVA_IDSO = :idso";
        $gstPoli = $pdo->prepare($qryPoli);
        $gstPoli->bindParam(":idso", $solicitud['id_solicitud']);

        if(!$gstPoli->execute()){
            return $this->makeResponse(true, "ERR_MCOMPV_SER_APR001: No se ejecutó la consulta de la política a la base", [], 500);
        }

        $politica = $gstPoli->fetchObject();

        $diasVacacioneApli = json_decode($politica->POLI_DVAA, true);
        $diasVacF = array();
        foreach($diasVacacioneApli as $key=>$val){
            if(str_contains($key, "-")){
                $limites = explode("-", $key);
                for($i = intval($limites[0]); $i <= intval($limites[1]); $i++){
                    $diasVacF[$i] = $val;
                }
            }else{
                $diasVacF[$key] = $val;
            }
        }

        $hoy = Carbon::now()->timezone('America/Mexico_City');
        $fIng = new Carbon($politica->USUA_FEIN);

        $diff = $hoy->diffInYears($fIng);

        $diasperiodoActual = $diasVacF[$diff];
        $diasperiodoAnt = $diasVacF[$diff - 1];
        $periodoActual = "|" . $fIng->addYears($diff)->toDateString();
        $periodoActual = $fIng->subYear()->toDateString() . $periodoActual;

        $periodoAnterior = "|" . $fIng->toDateString();
        $periodoAnterior = $fIng->subYear()->toDateString() . $periodoAnterior;

        $qryDiasTomados = "SELECT PEVA_VAPE, PEVA_VAGO FROM S001V01TPEVA WHERE PEVA_PEVA = :peva AND PEVA_EMPL = :empl";
        $gstDiasTomados = $pdo->prepare($qryDiasTomados);
        
        $gstDiasTomados->bindParam(":peva", $periodoAnterior);
        $gstDiasTomados->bindParam(":empl", $politica->USUA_IDUS);

        if(!$gstDiasTomados->execute()){
            return $this->makeResponse(true, "ERR_MCOMPV_SER_APR002: No se ejecutó la consulta de las vacaciones tomadas", [], 500);
        }

        $vacacionesTomadas = $gstDiasTomados->fetchAll($pdo::FETCH_ASSOC);
        foreach($vacacionesTomadas as $vacaciones){
            $diasTomados = $vacaciones['PEVA_VAPE'] - $vacaciones['PEVA_VAGO'];
            $diasperiodoAnt = $diasperiodoAnt - $diasTomados;
        }
        
        unset($gstDiasTomados);
        $gstDiasTomados = $pdo->prepare($qryDiasTomados);
        
        $gstDiasTomados->bindParam(":peva", $periodoActual);
        $gstDiasTomados->bindParam(":empl", $politica->USUA_IDUS);

        if(!$gstDiasTomados->execute()){
            return $this->makeResponse(true, "ERR_MCOMPV_SER_APR003: No se ejecutó la consulta de las vacaciones tomadas", [], 500);
        }

        unset($vacacionesTomadas);
        $vacacionesTomadas = $gstDiasTomados->fetchAll($pdo::FETCH_ASSOC);
        foreach($vacacionesTomadas as $vacaciones){
            $diasTomados = $vacaciones['PEVA_VAPE'] - $vacaciones['PEVA_VAGO'];
            $diasperiodoActual = $diasperiodoActual - $diasTomados;
        }

        $feto = $politica->SOVA_FEIN . "|" . $politica->SOVA_FEFI;

        $vago = $solicitud['estatus'] == "Aprobado" ? $diasperiodoActual - $politica->SOVA_NUDI : $diasperiodoActual;
        $qryInsPeva = "INSERT INTO S001V01TPEVA (PEVA_IDSO, PEVA_RFCE, PEVA_EMPL, PEVA_PEVA, PEVA_FETO, PEVA_VAPE, PEVA_VAGO) 
        VALUES (:idso, :rfce, :empl, :peva, :feto, :vape, :vago)";
        $gstInsPeva = $pdo->prepare($qryInsPeva);

        $encriptacion = new EncController();
        $rfce = $encriptacion->desencriptar($solicitud['rfc_empresa']);

        $gstInsPeva->bindParam(":idso", $solicitud['id_solicitud']);
        $gstInsPeva->bindParam(":rfce", $rfce);
        $gstInsPeva->bindParam(":empl", $politica->USUA_IDUS);
        $gstInsPeva->bindParam(":peva", $periodoActual);
        $gstInsPeva->bindParam(":feto", $feto);
        $gstInsPeva->bindParam(":vape", $diasperiodoActual);
        $gstInsPeva->bindParam(":vago", $vago);

        if(!$gstInsPeva->execute()){
            return $this->makeResponse(true, "ERR_MCOMPV_SER_APR004: No se ejecutó la inserción del periodo vacacional", [], 500);
        }

        $nomPlantilla = $solicitud['estatus'] == "Aprobado" ? "Solicitud Aprobada" : "Solicitud Rechazada";
        $qryPlanCor = "SELECT COPL_ASUN, COPL_CONT FROM S001V01TCOPL WHERE COPL_PORT = 'MESMAV' AND COPL_NOPL = '$nomPlantilla'";
        $gstPlanCor = $pdo->prepare($qryPlanCor);

        if(!$gstPlanCor->execute()){
            return $this->makeResponse(true, "ERR_MCOMPV_SER_APR005: No se pudo consultar la plantilla del correo", [], 500);
        }
        
        $plantilla = $gstPlanCor->fetchObject();

        $qryCorreos = "SELECT USUA_COEL FROM S001V01TUSUA LEFT JOIN S001V01TSOVA ON SOVA_IDUS = USUA_IDUS WHERE SOVA_IDSO = :idso 
        UNION SELECT USUA_COEL FROM S001V01TUSUA WHERE USUA_PERF = 1";
        $gstCorreos = $pdo->prepare($qryCorreos);
        $gstCorreos->bindParam(":idso", $solicitud['id_solicitud']);

        if(!$gstCorreos->execute()){
            return $this->makeResponse(true, "ERR_MCOMPV_SER_APR006: No se pudieron obtener los correos de los administradores y el usuario", [], 500);
        }

        $correos = array();

        foreach($gstCorreos->fetchAll($pdo::FETCH_ASSOC) as $correo){
            $correos[] = $correo['USUA_COEL'];
        }

        $qryUpdSova = "UPDATE S001V01TSOVA SET SOVA_ESTA = :esta, SOVA_USMO = :usmo, SOVA_FEMO = :femo, SOVA_FEAR = CURRENT_TIMESTAMP, SOVA_MORE = :moca 
        WHERE SOVA_IDSO = :idso";
        $gstUpdSova = $pdo->prepare($qryUpdSova);
        $hoyStr = $hoy->toDateTimeString();

        $gstUpdSova->bindParam(":esta", $solicitud['estatus']);
        $gstUpdSova->bindParam(":usmo", $solicitud['id_usuario_autoriza']);
        $gstUpdSova->bindParam(":femo", $hoyStr);
        $gstUpdSova->bindParam(":moca", $solicitud['motivo_rechazo']);
        $gstUpdSova->bindParam(":idso", $solicitud['id_solicitud']);

        if(!$gstUpdSova->execute()){
            return $this->makeResponse(true, "ERR_MCOMPV_SER_APR007: No se pudo autorizar/rechazar la solicitud", [], 500);
        }

        $bindSubject = [
            "%idso%" => $solicitud['id_solicitud'],
        ];

        $aprobacion = Carbon::now()->timezone('America/Mexico_City')->toDateString();

        $bindBody = [
            "%idus%" => $solicitud['id_usuario_autoriza'],
            "%idso%" => $solicitud['id_solicitud'],
            "%fapr%" => $aprobacion,
            "%fini%" => $politica->SOVA_FEIN,
            "%ffin%" => $politica->SOVA_FEFI,
            "%ndias%" => $politica->SOVA_NUDI,
            "%ndres%" => $vago,
        ];

        if($solicitud['estatus'] == "Rechazado") $bindBody["%motivo%"] = $solicitud['motivo_rechazo'];

        $correoController = new CorreoController();
        return $this->makeResponse(false, $correoController->enviarCorreo($plantilla, $correos, $bindSubject, $bindBody, "EXITO: Solicitud $solicitud[estatus]"));
    }

    public function aprobar(Request $request){
        $validator = Validator::make($request->all(), [
            'id_solicitud' => 'required|integer',
            'id_usuario_autoriza' => 'required|string|max:50',
            'estatus' => 'required|string|in:Aprobado,Rechazado',
            'motivo_rechazo' => 'required_if:estatus,==,Rechazado|string',
            'rfc_empresa' => 'required|string',
        ]);

        if ($validator->fails()) {
            return $this->makeResponse(
                true,
                "ERR_MCOMPV_USU_APR000: Se encontraron uno o más errores",
                $this->makeErrors($validator->errors()->messages()),
                400
            );
        }

        $solicitud = $request->all();
        $encController = new EncController();
        $pdo = DB::connection()->getPdo();
        $rfce = $encController->desencriptar($solicitud['rfc_empresa']);

        $nomPlantilla = $solicitud['estatus'] == "Aprobado" ? "Solicitud Aprobada" : "Solicitud Rechazada";
        $qryPlanCor = "SELECT COPL_ASUN, COPL_CONT FROM S001V01TCOPL WHERE COPL_PORT = 'MESMAV' AND COPL_NOPL = '$nomPlantilla' AND COPL_RFCE = :rfce";
        $gstPlanCor = $pdo->prepare($qryPlanCor);
        $gstPlanCor->bindParam(":rfce", $rfce);

        if(!$gstPlanCor->execute()){
            return $this->makeResponse(true, "ERR_MCOMPV_SER_APR001: No se pudo consultar la plantilla del correo", [], 500);
        }
        
        $plantilla = $gstPlanCor->fetchObject();

        $qryCorreos = "SELECT USUA_COEL FROM S001V01TUSUA LEFT JOIN S001V01TSOVA ON SOVA_IDUS = USUA_IDUS WHERE SOVA_IDSO = :idso 
        UNION SELECT USUA_COEL FROM S001V01TUSUA WHERE USUA_PERF = 1 AND USUA_ESTA != 'Eliminado'";
        $gstCorreos = $pdo->prepare($qryCorreos);
        $gstCorreos->bindParam(":idso", $solicitud['id_solicitud']);

        if(!$gstCorreos->execute()){
            return $this->makeResponse(true, "ERR_MCOMPV_SER_APR002: No se pudieron obtener los correos de los administradores y el usuario", [], 500);
        }

        $correos = array();

        foreach($gstCorreos->fetchAll($pdo::FETCH_ASSOC) as $correo){
            $correos[] = $correo['USUA_COEL'];
        }

        $femo = Carbon::now()->timezone('America/Mexico_City')->toDateString();

        $qryGetPer = "SELECT * FROM S001V01TPEVA WHERE PEVA_IDSO = :idso AND PEVA_RFCE = :rfce ORDER BY PEVA_IDPE DESC";
        $gstGetPer = $pdo->prepare($qryGetPer);

        $gstGetPer->bindParam(":idso", $solicitud['id_solicitud']);
        $gstGetPer->bindParam(":rfce", $rfce);

        try{
            $gstGetPer->execute();
        }catch(PDOException $e){
            return $this->makeResponse(true, "ERR_MCOMPV_USU_APR007: No se pudieron obtener los datos de los periodos vacacionales.", [], 500);
        }

        $periodos = $gstGetPer->fetchAll($pdo::FETCH_ASSOC);

        $qryGetUsu = "SELECT USUA_NOMB, USUA_APPA, USUA_APMA FROM S001V01TUSUA WHERE USUA_IDUS = :idus";
        $gstGetUsu = $pdo->prepare($qryGetUsu);

        $gstGetUsu->bindParam(":idus", $solicitud['id_usuario_autoriza']);

        try{
            $gstGetUsu->execute();
        }catch(PDOException $e){
            return $this->makeResponse(true, "ERR_MCOMPV_USU_APR007: No se pudieron obtener los datos de los periodos vacacionales.", [], 500);
        }

        $usuario = $gstGetUsu->fetchObject();

        if(!$usuario) return $this->makeResponse(true, "ERR_MCOMPV_USU_APR002: El usuario que realizó la solicitud no existe", [], 404);

        if($solicitud['estatus'] == "Aprobado"){
            $qryActSol = "UPDATE S001V01TSOVA SET SOVA_ESTA = 'Aprobado', SOVA_USMO = :usmo, SOVA_FEMO = :femo WHERE SOVA_IDSO = :idso AND SOVA_RFCE = :rfce";
            $gstActSol = $pdo->prepare($qryActSol);

            $gstActSol->bindParam(":idso", $solicitud['id_solicitud']);
            $gstActSol->bindParam(":usmo", $solicitud['id_usuario_autoriza']);
            $gstActSol->bindParam(":femo", $femo);
            $gstActSol->bindParam(":rfce", $rfce);

            try{
                $gstActSol->execute();
            }catch(PDOException $e){
                return $this->makeResponse(true, "ERR_MCOMPV_USU_APR003: No se pudo actualizar el estado de la solicitud en la base.", [], 500);
            }
        }else{
            $qryActSol = "UPDATE S001V01TSOVA SET SOVA_ESTA = 'Rechazado', SOVA_MORE = :more, SOVA_USMO = :usmo, SOVA_FEMO = :femo WHERE SOVA_IDSO = :idso AND 
            SOVA_RFCE = :rfce";
            $gstActSol = $pdo->prepare($qryActSol);

            $gstActSol->bindParam(":more", $solicitud['motivo_rechazo']);
            $gstActSol->bindParam(":usmo", $solicitud['id_usuario_autoriza']);
            $gstActSol->bindParam(":femo", $femo);
            $gstActSol->bindParam(":idso", $solicitud['id_solicitud']);
            $gstActSol->bindParam(":rfce", $rfce);

            try{
                $gstActSol->execute();
            }catch(PDOException $e){
                return $this->makeResponse(true, "ERR_MCOMPV_USU_APR004: No se pudo actualizar el estado de la solicitud en la base.", [], 500);
            }

            $qryActPev = "UPDATE S001V01TPEVA SET PEVA_VAGO = PEVA_VAPE WHERE PEVA_IDSO = :idso AND PEVA_RFCE = :rfce";
            $gstActPev = $pdo->prepare($qryActPev);

            $gstActPev->bindParam(":idso", $solicitud['id_solicitud']);
            $gstActPev->bindParam(":rfce", $rfce);

            try{
                $gstActPev->execute();
            }catch(PDOException $e){
                return $this->makeResponse(true, "ERR_MCOMPV_USU_APR005: No se pudo actualizar los periodos de la solicitud en la base.", [], 500);
            }
        }

        $bindSubject = [
            "%idso%" => $solicitud['id_solicitud'],
        ];

        $aprobacion = Carbon::now()->timezone('America/Mexico_City')->toDateString();
        $qryGetSol = "SELECT A.*, USUA_FEIN FROM S001V01TSOVA AS A INNER JOIN S001V01TUSUA ON SOVA_IDUS = USUA_IDUS WHERE SOVA_IDSO = :idso AND SOVA_RFCE = :rfce";
        $gstGetSol = $pdo->prepare($qryGetSol);

        $gstGetSol->bindParam(":idso", $solicitud['id_solicitud']);
        $gstGetSol->bindParam(":rfce", $rfce);

        try{
            $gstGetSol->execute();
        }catch(PDOException $e){
            return $this->makeResponse(true, "ERR_MCOMPV_USU_APR006: No se pudieron obtener los datos de la solicitud.", [], 500);
        }

        $sol = $gstGetSol->fetchObject();

        $hoy = Carbon::now()->timezone('America/Mexico_City');
        $fechaIngreso = new Carbon($sol->USUA_FEIN);
        $diffYears = $hoy->diffInYears($fechaIngreso);
    
        $fechaIngreso->addYears($diffYears);
        $diffEAYG = $hoy->diffInDays($fechaIngreso);

        $vago = 0;
        $index = 0;
        foreach($periodos as $periodo){
            if($solicitud['estatus'] == "Aprobado"){
                $vago += $periodo['PEVA_VAGO'];
            }else{
                if($index == 0 && $sol->SOVA_EAYG == "Si"){
                    $diasEAYG = ($periodo['PEVA_VAPE'] / 365) * $diffEAYG;
                    $diasEAYG = intval($diasEAYG);
                    $diasEAYG = $diasEAYG - ($periodo['PEVA_VAPE'] - $periodo['PEVA_VAGO']);
                    $diasCompleto = $diasEAYG + $periodo['PEVA_VAGO'];
    
                    $diasEAYG = ($periodo['PEVA_VAPE'] / 365) * $diffEAYG;
                    $diasEAYG = intval($diasEAYG);
    
                    if($diasCompleto > $periodo['PEVA_VAPE']){
                        $diasEAYG = $diasEAYG - ($diasCompleto - $periodo['PEVA_VAPE']);
                    }
    
                    $vago += $diasEAYG;
                }else{
                    $vago += $periodo['PEVA_VAPE'];
                }

                $index++;
            }
        }

        $empresas = [
            "TME700618RC7" => "TIMKEN"
        ];

        $functionsController = new FunctionsController();

        $bindBody = [
            "%nous%" => $functionsController->joinName($usuario->USUA_NOMB, $usuario->USUA_APPA, $usuario->USUA_APMA),
            "%idus%" => $solicitud['id_usuario_autoriza'],
            "%idso%" => $solicitud['id_solicitud'],
            "%fapr%" => $functionsController->orderDate($aprobacion),
            "%fini%" => $functionsController->orderDate($sol->SOVA_FEIN),
            "%ffin%" => $functionsController->orderDate($sol->SOVA_FEFI),
            "%ndias%" => $sol->SOVA_NUDI,
            "%ndres%" => $vago,
        ];

        if($solicitud['estatus'] == "Rechazado") $bindBody["%motivo%"] = $solicitud['motivo_rechazo'];

        $correoController = new CorreoController();
        return $this->makeResponse(false, $correoController->enviarCorreo($plantilla, $correos, $bindSubject, $bindBody, "EXITO: Solicitud $solicitud[estatus]", $empresas[$rfce]));
    }

    public function getSolicitudesPendientes($idus, $rfce, $nonce){
        $pdo = DB::connection()->getPdo();
        $encController = new EncController();
        $rfce = $encController->desencriptar(base64_encode($rfce . "|" . $nonce));

        $qryPerf = "SELECT USUA_PERF FROM S001V01TUSUA WHERE USUA_IDUS = :idus AND USUA_RFCE = :rfce";
        $gstPerf = $pdo->prepare($qryPerf);

        $gstPerf->bindParam(":idus", $idus);
        $gstPerf->bindParam(":rfce", $rfce);

        if(!$gstPerf->execute()){
            return $this->makeResponse(true, "ERR_MCOMPV_SER_GSP000: No se ejecutó la consulta del perfil del usuario", [], 500);
        }

        $perf = $gstPerf->fetchObject();

        if(!$perf){
            return $this->makeResponse(true, "ERR_MCOMPV_USU_GSP001: El usuario que hace la consulta no existe", [], 404);
        }

        $binds = array();
        $qry = null;
        if($perf->USUA_PERF != 1){
            $qry = 'SELECT SOVA_IDSO AS IDSOLICITUD, CONCAT(USUA_NOMB, " ", USUA_APPA, " ", IF(ISNULL(USUA_APMA), "", USUA_APMA), " (", USUA_IDUS, ")") AS NOMBREEMPLEADO, 
            SOVA_FEIN AS FECHAINICIO, SOVA_FEFI AS FECHAFIN, SOVA_NUDI AS NUMERODIAS FROM S001V01TUSUA INNER JOIN S001V01TSOVA ON SOVA_IDUS = USUA_IDUS LEFT JOIN S001V01TORGA 
            ON ORGA_IDUS = USUA_IDUS WHERE ORGA_JEDI = :jedi OR ORGA_JESU = :jesu AND SOVA_ESTA = "Pendiente" AND SOVA_RFCE = :rfce';
          
            $gst = $pdo->prepare($qry);
            $gst->bindParam(":jedi",$idus);
            $gst->bindParam(":jesu",$idus);
            $gst->bindParam(":rfce",$rfce);
        }else{
            $qry = 'SELECT SOVA_IDSO AS IDSOLICITUD, CONCAT(USUA_NOMB, " ", USUA_APPA, " ", IF(ISNULL(USUA_APMA), "", USUA_APMA), " (", USUA_IDUS, ")") AS NOMBREEMPLEADO, 
            SOVA_FEIN AS FECHAINICIO, SOVA_FEFI AS FECHAFIN, SOVA_NUDI AS NUMERODIAS FROM S001V01TUSUA INNER JOIN S001V01TSOVA ON SOVA_IDUS = USUA_IDUS WHERE 
            SOVA_ESTA = "Pendiente" AND SOVA_IDUS != :idus AND SOVA_RFCE = :rfce ' ;

            $gst = $pdo->prepare($qry);
            $gst->bindParam(":idus",$idus);
            $gst->bindParam(":rfce",$rfce);
        };

        if(!$gst->execute()){
            return $this->makeResponse(true, "ERR_MCOMPV_SER_GSP001: No se ejecutó la consulta de las solicitudes a la base", [], 500);
        }
        return $this->makeResponse(false, "EXITO", $gst->fetchAll($pdo::FETCH_ASSOC));
    }

    private function makeResponse($error, $msg, $response = [], $code = 200){
        $respuesta = json_encode([
            "error" => $error,
            "msg" => $msg,
            "response" => $response
        ]);

        return response($respuesta, $code)->header('Content-Type', 'application/json');
    }

    private function makeErrors($erroresObj){
        $erroresArr = array();

        foreach ($erroresObj as $key => $value) {
            foreach ($value as $key0 => $value0) {
                if(array_key_exists($key, $erroresArr)){
                    $val = $erroresArr[$key] . "|" . $value0;
                    $erroresArr[$key] = $val;
                }else{
                    $erroresArr[$key] = $value0;
                }
            }
        }

        return $erroresArr;
    }
}