<?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 MESMCVController extends Controller{
    public function getSolicitudesAprobadas($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_MESMCV_SER_GSP000: No se ejecutó la consulta del perfil del usuario", [], 500);
        }

        $perf = $gstPerf->fetchObject();

        if(!$perf){
            return $this->makeResponse(true, "ERR_MESMCV_USU_GSP001: El usuario que hace la consulta no existe", [], 404);
        }
        
        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 SOVA_ESTA = "Aprobado" AND SOVA_FEFI > CURRENT_DATE AND ORGA_JEDI = :idus AND SOVA_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 = "Aprobado" AND SOVA_FEFI > CURRENT_DATE AND USUA_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_MESMCV_SER_GSA002: No se ejecutó la consulta de las solicitudes a la base", [], 500);
        }
        return $this->makeResponse(false, "EXITO", $gst->fetchAll($pdo::FETCH_ASSOC));
    }

    public function cancelarOld(Request $request){
        $validator = Validator::make($request->all(), [
            'id_solicitud' => 'required|integer',
            'id_usuario_cancela' => 'required|string|max:50',
            'motivo_cancelacion' => 'required|string',
        ]);

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

        $solicitud = $request->all();
        $pdo = DB::connection()->getPdo();

        $qryRFCE = "SELECT USUA_RFCE FROM S001V01TUSUA WHERE USUA_IDUS = :idus";
        $gstRFCE = $pdo->prepare($qryRFCE);
        $gstRFCE->bindParam(":idus", $solicitud['id_usuario_cancela']);

        $gstRFCE->execute();
        $rfce = $gstRFCE->fetchObject()->USUA_RFCE;

        $qryUsuario = "SELECT USUA_IDUS, USUA_COEL, SOVA_FEIN, SOVA_FEFI, SOVA_NUDI, PEVA_VAGO, PEVA_VAPE FROM S001V01TUSUA INNER JOIN S001V01TSOVA ON SOVA_IDUS = USUA_IDUS 
        INNER JOIN S001V01TPEVA ON PEVA_IDSO = SOVA_IDSO WHERE SOVA_IDSO = :idso AND USUA_RFCE = :rfce";
        $gstUsuario = $pdo->prepare($qryUsuario);
        $gstUsuario->bindParam(":idso", $solicitud['id_solicitud']);
        $gstUsuario->bindParam(":rfce", $rfce);

        if(!$gstUsuario->execute()){
            return $this->makeResponse(true, "ERR_MESMCV_SER_CAN001: No se ejecutó la consulta de la infromación del usuario a la base", [], 500);
        }

        $usuario = $gstUsuario->fetchObject();
        if(!$usuario){
            return $this->makeResponse(true, "ERR_MESMCV_USU_CAN002: La solicitud requerida no existe", [], 404);
        }

        $fechaFin = new Carbon($usuario->SOVA_FEFI);
        $fechaIni = new Carbon($usuario->SOVA_FEIN);
        $now = Carbon::now();

        $diasTomados = $fechaIni->diffInDays($now) + 1;
        $diasRepuestos = $usuario->PEVA_VAPE - ($usuario->PEVA_VAGO + $diasTomados);
        $diasRestantes = $usuario->PEVA_VAPE - $diasTomados;

        if($now->gt($fechaIni)){
            $qryEliPeriodo = "UPDATE S001V01TPEVA SET PEVA_VAGO = $diasRepuestos WHERE PEVA_IDSO = :idso AND PEVA_RFCE = :rfce";
        }else{
            $qryEliPeriodo = "UPDATE S001V01TPEVA SET PEVA_VAGO = PEVA_VAPE WHERE PEVA_IDSO = :idso AND PEVA_RFCE = :rfce";
        }
        $gstEliPeriodo = $pdo->prepare($qryEliPeriodo);
        $gstEliPeriodo->bindParam(":idso", $solicitud['id_solicitud']);
        $gstEliPeriodo->bindParam(":rfce", $rfce);

        if(!$gstEliPeriodo->execute()){
            return $this->makeResponse(true, "ERR_MESMCV_SER_CAN003: No se ejecutó la elimincación del periodo en la base", [], 500);
        }

        $qryPlanCor = "SELECT COPL_ASUN, COPL_CONT FROM S001V01TCOPL WHERE COPL_PORT = 'MESMCV' AND COPL_NOPL = 'Solicitud Cancelada'";
        $gstPlanCor = $pdo->prepare($qryPlanCor);

        if(!$gstPlanCor->execute()){
            return $this->makeResponse(true, "ERR_MESMCV_SER_CAN004: 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_RFCE = :rfce";
        $gstCorreos = $pdo->prepare($qryCorreos);
        $gstCorreos->bindParam(":idso", $solicitud['id_solicitud']);
        $gstCorreos->bindParam(":rfce", $rfce);

        if(!$gstCorreos->execute()){
            return $this->makeResponse(true, "ERR_MESMCV_SER_CAN005: 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'];
        }

        $qryCancelar = "UPDATE S001V01TSOVA SET SOVA_ESTA = 'Cancelado', SOVA_MOCA = :moca, SOVA_USMO = :usmo, SOVA_FEMO = :femo, SOVA_FEAR = CURRENT_TIMESTAMP 
        WHERE SOVA_IDSO = :idso AND SOVA_RFCE = :rfce";
        $gstCancelar = $pdo->prepare($qryCancelar);

        $hoy = Carbon::now()->timezone('America/Mexico_City')->toDateTimeString();

        $gstCancelar->bindParam(":moca", $solicitud['motivo_cancelacion']);
        $gstCancelar->bindParam(":usmo", $solicitud['id_usuario_cancela']);
        $gstCancelar->bindParam(":femo", $hoy);
        $gstCancelar->bindParam(":idso", $solicitud['id_solicitud']);
        $gstCancelar->bindParam(":rfce", $rfce);

        if(!$gstCancelar->execute()){
            return $this->makeResponse(true, "ERR_MESMCV_SER_CAN006: No se ejecutó la consulta de la infromación del usuario a la base", [], 500);
        }

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

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

        $bindBody = [
            "%idus%" => $solicitud['id_usuario_cancela'],
            "%motivo%" => $solicitud['motivo_cancelacion'],
            "%idso%" => $solicitud['id_solicitud'],
            "%fcan%" => $cancelacion,
            "%fini%" => $usuario->SOVA_FEIN,
            "%ffin%" => $usuario->SOVA_FEFI,
        ];

        if($now->gt($fechaIni)){
            $bindBody['%ndtom%'] = $diasTomados;
            $bindBody['%ndrep%'] = $diasRepuestos;
            $bindBody['%ndres%'] = $diasRestantes;
        }else{
            $bindBody['%ndtom%'] = "0";
            $bindBody['%ndrep%'] = $usuario->SOVA_NUDI;
            $bindBody['%ndres%'] = $usuario->PEVA_VAPE;
        }

        //return $this->makeResponse(false, "EXITO: Vacaciones canceladas");
        $correoController = new CorreoController();
        return $this->makeResponse(false, $correoController->enviarCorreo($plantilla, $correos, $bindSubject, $bindBody, "EXITO: Vacaciones canceladas"));
    }

    public function cancelar(Request $request){
        $validator = Validator::make($request->all(), [
            'id_solicitud' => 'required|integer',
            'id_usuario_cancela' => 'required|string|max:50',
            'motivo_cancelacion' => 'required|string',
            'rfc_empresa' => 'required|string',
        ]);

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

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

        $pdo = DB::connection()->getPdo();
        $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_MESMCV_SER_CAN001: No se pudo consultar la solicitud requerida en la base de datos.", [], 500);
        }

        $solBD = $gstGetSol->fetchObject();

        if(!$solBD){
            return $this->makeResponse(true, "ERR_MESMCV_USU_CAN002: La solicitud requerida no existe.", [], 404);
        }

        $diasRestantesPorTomar = $solBD->SOVA_NUDI;
        $fechaFin = new Carbon($solBD->SOVA_FEFI);
        $fechaIni = new Carbon($solBD->SOVA_FEIN);
        $hoy = Carbon::now()->timezone('America/Mexico_City');

        if($hoy->gt($fechaFin)){
            return $this->makeResponse(true, "ERR_MESMCV_USU_CAN002: La solicitud no puede ser cancelada porque la fecha final es mayor a la actual.", [], 401);
        }else if($hoy->gte($fechaIni)){
            $diasRestantesPorTomar = $hoy->diffInDays($fechaFin) + 1;
            $diasRestantes -= $diasRestantesPorTomar;
        }

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

        $gstGetPev->bindParam(":idso", $solBD->SOVA_IDSO);
        $gstGetPev->bindParam(":rfce", $solBD->SOVA_RFCE);
        $gstGetPev->bindParam(":empl", $solBD->SOVA_IDUS);

        try{
            $gstGetPev->execute();
        }catch(PDOException $e){
            return $this->makeResponse(true, "ERR_MESMCV_SER_CAN003: No se pudo consultar los periodos tomados por la solicitud.", [], 500);
        }

        $periodos = $gstGetPev->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_cancela']);

        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);

        $diasVacaciones = $solBD->SOVA_NUDI;
        $diasRestantes = 0;
        $index = 0;

        $fechaIngreso = new Carbon($solBD->USUA_FEIN);
        $diffYears = $hoy->diffInYears($fechaIngreso);
    
        $fechaIngreso->addYears($diffYears);
        $diffEAYG = $hoy->diffInDays($fechaIngreso);
        
        foreach ($periodos as $periodo) {
            $diasTomadosPeriodo = $periodo['PEVA_VAPE'] - $periodo['PEVA_VAGO'];
            $diasReponer = $periodo['PEVA_VAGO'] + $diasVacaciones;
            
            $diasReponer = $diasReponer > $periodo['PEVA_VAPE'] ? $periodo['PEVA_VAPE'] : $diasReponer;
            $diasVacaciones -= $diasTomadosPeriodo;
            
            $qryUpdPev = "UPDATE S001V01TPEVA SET PEVA_VAGO = :vago WHERE PEVA_IDPE = :idpe";
            $gstUpdPev = $pdo->prepare($qryUpdPev);

            $gstUpdPev->bindParam(":vago", $diasReponer);
            $gstUpdPev->bindParam(":idpe", $periodo['PEVA_IDPE']);

            if($index == 0 && $solBD->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']);
                }

                $diasRestantes += $diasEAYG;
            }else{
                $diasRestantes += $periodo['PEVA_VAPE'];
            }

            try{
                $gstUpdPev->execute();
            }catch(PDOException $e){
                return $this->makeResponse(true, "ERR_MESMCV_SER_CAN004: No se pudo actualizar los periodos vacacionales tomados por la solicitud.", [], 500);
            }

            $index++;
        }

        $qryUpdSol = "UPDATE S001V01TSOVA SET SOVA_ESTA = 'Cancelado', SOVA_MOCA = :moca WHERE SOVA_IDSO = :idso AND SOVA_RFCE = :rfce";
        $gstUpdSol = $pdo->prepare($qryUpdSol);

        $gstUpdSol->bindParam(":moca", $solicitud['motivo_cancelacion']);
        $gstUpdSol->bindParam(":idso", $solBD->SOVA_IDSO);
        $gstUpdSol->bindParam(":rfce", $solBD->SOVA_RFCE);

        try{
            $gstUpdSol->execute();
        }catch(PDOException $e){
            return $this->makeResponse(true, "ERR_MESMCV_SER_CAN005: No se pudo actualizar el estatus de la slicitud.", [], 500);
        }

        $qryPlanCor = "SELECT COPL_ASUN, COPL_CONT FROM S001V01TCOPL WHERE COPL_PORT = 'MESMCV' AND COPL_NOPL = 'Solicitud Cancelada'";
        $gstPlanCor = $pdo->prepare($qryPlanCor);

        if(!$gstPlanCor->execute()){
            return $this->makeResponse(true, "ERR_MESMCV_SER_CAN006: 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_RFCE = :rfce AND USUA_ESTA != 'Eliminado'";
        $gstCorreos = $pdo->prepare($qryCorreos);
        $gstCorreos->bindParam(":idso", $solicitud['id_solicitud']);
        $gstCorreos->bindParam(":rfce", $rfce);

        if(!$gstCorreos->execute()){
            return $this->makeResponse(true, "ERR_MESMCV_SER_CAN007: 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'];
        }

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

        $cancelacion = Carbon::now()->timezone('America/Mexico_City')->toDateString();
        $functionsController = new FunctionsController();

        $bindBody = [
            "%nous%" => $functionsController->joinName($usuario->USUA_NOMB, $usuario->USUA_APPA, $usuario->USUA_APMA),
            "%idus%" => $solicitud['id_usuario_cancela'],
            "%motivo%" => $solicitud['motivo_cancelacion'],
            "%idso%" => $solicitud['id_solicitud'],
            "%fcan%" => $functionsController->orderDate($cancelacion),
            "%fini%" => $functionsController->orderDate($solBD->SOVA_FEIN),
            "%ffin%" => $functionsController->orderDate($solBD->SOVA_FEIN),
            '%ndtom%' => $solBD->SOVA_NUDI - $diasRestantesPorTomar,
            '%ndrep%' => $solBD->SOVA_NUDI - $diasVacaciones,
            '%ndres%' => $diasRestantes - $diasVacaciones
        ];
        
        $correoController = new CorreoController();
        return $this->makeResponse(false, $correoController->enviarCorreo($plantilla, $correos, $bindSubject, $bindBody, "EXITO: Vacaciones canceladas", $empresas[$rfce]));
    }

    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;
    }
}