<?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 ErrorException;
use PDOException;

class MESMPRController extends Controller{
    public function getVacacionesOld($idusuario, $rfce){
        $pdo = DB::connection()->getPdo();
        $encController = new EncController();
        $rfce = $encController->desencriptar($rfce);
        //Primero se consulta la fecha de ingreso laboral del usuario para saber cuanto tiempo lleva trabajando junto con su política
        $qryUsrPol = "SELECT A.*, B.* FROM S001V01TUSUA AS A INNER JOIN S001V01TPOLI AS B ON A.USUA_POLI = B.POLI_IDPO WHERE A.USUA_IDUS = :idus AND A.USUA_RFCE = :rfce";
        $gstUsrPol = $pdo->prepare($qryUsrPol);
        $gstUsrPol->bindParam(":idus", $idusuario);
        $gstUsrPol->bindParam(":rfce", $rfce);

        if(!$gstUsrPol->execute()){
            return $this->makeResponse(true, "ERR_MESMPR_SER_GVS000: No se ejecutó la consulta del usuario", [], 500);
        }
        $usuario = $gstUsrPol->fetchObject();
        if(!$usuario){
            return $this->makeResponse(true, "ERR_MESMPR_SER_GVS001: El usuario solicitado no existe", [], 404);
        }
        //Hacemos el cálculo de los periodos disponibles
        $usrFEIN = new Carbon($usuario->USUA_FEIN);
        $hoy = Carbon::now()->timezone('America/Mexico_City');
        if($hoy->lt($usrFEIN)){
            return $this->makeResponse(true, "ERR_MESMPR_SER_GVS001: El usuario tiene un error en su registro, contacte al departamento de TI para solucionarlo", [], 500);
        }
        //Obtenemos el tiempo trabajado del usuario
        $diffYears = $usrFEIN->diffInYears($hoy);
        $anioSiguiente = new Carbon($usuario->USUA_FEIN);
        $anioSiguiente->addYears($diffYears);
        //Se calcula el número de días trabajados en el periodo actual
        $eaygSig = $hoy->diffInDays($anioSiguiente);
        $eaygSigDisp = 0;
        //Si los días trabajados del perodo actual son mayores a 90 entonces se realiza el cálculo de los días que puede gozar
        if($diffYears < 1 && $eaygSig > 90){
            $diasVacApli = json_decode($usuario->POLI_DVAA, true);
            $diasPrimerAnio = intval($diasVacApli[1]);

            $eaygSigDisp = ($diasPrimerAnio / 365) * $eaygSig;
            $eaygSigDisp = intval($eaygSigDisp);
        }
        //Parseamos el json de su política de vacaciones
        $diasVacApli = json_decode($usuario->POLI_DVAA, true);
        //Creamos un arreglo que contendrá todos los posibles dias aplicables
        $arrayDias = array();
        //Recorremos el json de la política del usuario
        foreach($diasVacApli as $key=>$val){
            if(str_contains($key, "-")){
                $lapso = explode("-", $key);
                $aIni = intval($lapso[0]);
                $aFin = intval($lapso[1]);
                for($i = $aIni; $i <= $aFin; $i++){
                    $arrayDias[$i] = $val;
                }
            }else{
                $arrayDias[$key] = $val;
            }
        }
        //Una vez que obtengamos el arreglo de la política iteramos el tiempo trabajando en la empresa para saber cuantas vacaciones tiene disponibles en cada periodo
        $periodos = array();
        for($i = 1; $i <= $diffYears; $i++){
            $vacacionesAplicables = intval($arrayDias[$i]);
            $feIni = $usrFEIN->isoFormat('YYYY-MM-DD');
            $feFin = $usrFEIN->addYear()->isoFormat('YYYY-MM-DD');
            $periodoStr = "$feIni|$feFin";

            $qryPeriodoVacaciones = "SELECT PEVA_VAPE, PEVA_VAGO, PEVA_FETO FROM S001V01TPEVA WHERE PEVA_PEVA = :peva AND PEVA_EMPL = :empl AND PEVA_RFCE = :rfce";
            $gstPeriodoVacaciones = $pdo->prepare($qryPeriodoVacaciones);

            $gstPeriodoVacaciones->bindParam(":peva", $periodoStr);
            $gstPeriodoVacaciones->bindParam(":empl", $idusuario);
            $gstPeriodoVacaciones->bindParam(":rfce", $rfce);

            if(!$gstPeriodoVacaciones->execute()){
                return $this->makeResponse(true, "ERR_MESMPR_SER_GVS002: No se pudieron consultar los periodos vacacionales tomados por el usuario", [], 500);
            }

            $periodoVacaciones = $gstPeriodoVacaciones->fetchAll($pdo::FETCH_ASSOC);
            if(count($periodoVacaciones) == 0){
                $periodo = (object) [
                    "PERIODO" => $periodoStr,
                    "VACACIONESDISPONIBLES" => $vacacionesAplicables,
                    "DIASEAYGDISPONIBLES" => 0,
                    "DETALLES" => []
                ];
                $periodos[] = $periodo;
            }else{
                $detalles = array();
                foreach($periodoVacaciones as $pVac){
                    $vacacionesGozadas = $pVac['PEVA_VAPE'] - $pVac['PEVA_VAGO'];
                    $vacacionesAplicables = $vacacionesAplicables - $vacacionesGozadas;
                    $detalles[] = [
                        "FECHASVACACIONES" => $pVac['PEVA_FETO'],
                        "DIASTOMADOS" => $vacacionesGozadas
                    ];
                }
                $periodo = (object) [
                    "PERIODO" => $periodoStr,
                    "VACACIONESDISPONIBLES" => $vacacionesAplicables,
                    "DIASEAYGDISPONIBLES" => 0,
                    "DETALLES" => $detalles
                ];
                $periodos[] = $periodo;
            }
        }

        if($eaygSigDisp > 0){
            $feIni = $usrFEIN->isoFormat('YYYY-MM-DD');
            $feFin = $usrFEIN->addYear()->isoFormat('YYYY-MM-DD');
            $periodoStr = "$feIni|$feFin";

            $periodo = (object) [
                "PERIODO" => $periodoStr,
                "VACACIONESDISPONIBLES" => 0,
                "DIASEAYGDISPONIBLES" => $eaygSigDisp,
                "DETALLES" => []
            ];
            $periodos[] = $periodo;
        }
        
        return $this->makeResponse(false, "EXITO", $periodos);
    }

    public function getVacaciones($idus, $rfce, $nonce){
        $pdo = DB::connection()->getPdo();
        $encController = new EncController();

        try{
            $rfce = $encController->desencriptar(base64_encode($rfce . "|" . $nonce));
        }catch(ErrorException $e){
            return $this->makeResponse(true, "ERR_MESMPR_SER_GVS000: El RFC enviado no está codificado correctamente.", [], 400);
        }

        //Se consulta la infromación del usuario y su política
        $qryUsuaPoli = "SELECT A.*, B.* FROM S001V01TUSUA AS A INNER JOIN S001V01TPOLI AS B ON USUA_POLI = POLI_IDPO WHERE USUA_IDUS = :idus AND USUA_RFCE = :rfce";
        $gstUsuaPoli = $pdo->prepare($qryUsuaPoli);

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

        try{
            $gstUsuaPoli->execute();
        }catch(PDOException $e){
            return $this->makeResponse(true, "ERR_MESMPR_SER_GVS001: No se pudo obtener información de la base.", [], 500);
        }

        $usuario = $gstUsuaPoli->fetchObject();

        if(!$usuario){
            return $this->makeResponse(true, "ERR_MESMPR_SER_GVS002: El usuario solicitado no existe.", [], 404);
        }

        //Se obtienen los días aplicables de la politica del usuario
        $dvaa = json_decode($usuario->POLI_DVAA, true);
        $arrDVAA = array();

        foreach($dvaa as $key=>$val){
            if(str_contains($key, "-")){
                $limites = explode("-", $key);
                for($i = intval($limites[0]); $i <= intval($limites[1]); $i++){
                    $arrDVAA[$i] = intval($val);
                }
            }else{
                $arrDVAA[$key] = intval($val);
            }
        }

        $hoy = Carbon::now()->timezone('America/Mexico_City');
        $fechaIngreso = new Carbon($usuario->USUA_FEIN);
        
        if($fechaIngreso->gt($hoy)){
            return $this->makeResponse(true, "ERR_MESMPR_SER_GVS003: El usuario consultado tiene un error en su registro, por favor contacte al departamento de TI.", [], 500);
        }

        $diffYears = $hoy->diffInYears($fechaIngreso);
        $fechaEAYG = new Carbon($usuario->USUA_FEIN);
        $fechaEAYG->addYears($diffYears);
        $diffEAYG = $hoy->diffInDays($fechaEAYG);
        
        $periodosF = array();
        for($i = 1; $i <= $diffYears + 1; $i++){
            $diasAnio = $arrDVAA[$i];
            $periodo = $fechaIngreso->toDateString() . "|" . $fechaIngreso->addYear()->toDateString();
            $qryGetPer = "SELECT * FROM S001V01TPEVA WHERE PEVA_EMPL = :empl AND PEVA_PEVA = :peva AND PEVA_RFCE = :rfce";
            $gstGetPer = $pdo->prepare($qryGetPer);

            $gstGetPer->bindParam(":empl", $idus);
            $gstGetPer->bindParam(":peva", $periodo);
            $gstGetPer->bindParam(":rfce", $rfce);

            try{
                $gstGetPer->execute();
            }catch(PDOException $e){
                return $this->makeResponse(true, "ERR_MESMPR_SER_GVS004: No se pudieron consultar los periodos tomados por el usuarios.", [], 500);
            }

            $periodosAnio = $gstGetPer->fetchAll($pdo::FETCH_ASSOC);
            $detalles = array();
            $diasTomados = 0;
            foreach($periodosAnio as $per){
                $diasTomados = $per['PEVA_VAPE'] - $per['PEVA_VAGO'];
                $detalles[] = [
                    "FECHASVACACIONES" => $per['PEVA_FETO'],
                    "DIASTOMADOS" => $diasTomados
                ];
                $diasAnio -= $diasTomados;
            }

            if($i <= $diffYears){
                $caducado = $hoy->diffInMonths($fechaIngreso) > 18;
                
                $periodosF[] = [
                    "PERIODO" => $periodo,
                    "VACACIONESDISPONIBLES" => $diasAnio,
                    "CADUCADO" => $caducado ? "Si" : "No",
                    "ESEAYG" => "No",
                    "DETALLES" => $detalles
                ];
            }else{
                if($diffEAYG >= 90){
                    $diasEAYG = ($arrDVAA[$i] / 365) * $diffEAYG;
                    $diasEAYG = intval($diasEAYG);

                    $diasEAYG -= $diasTomados;
                    $periodosF[] = [
                        "PERIODO" => $periodo,
                        "VACACIONESDISPONIBLES" => $diasEAYG,
                        "CADUCADO" => "No",
                        "ESEAYG" => "Si",
                        "DETALLES" => $detalles
                    ];
                }
            }
        }
        
        return $this->makeResponse(false, "EXITO", $periodosF);

        //Se compara la fecha de ingreso laboral del usuario con la fecha actual
        /*$now = Carbon::now()->timezone('America/Mexico_City');
        $fein = new Carbon($usuario->USUA_FEIN);

        $diffDays = $now->diffInDays($fein);
        $diffYears = $now->diffInYears($fein);
        if($fein->gt($now)){
            return $this->makeResponse(true, "ERR_MESMPR_SER_GVS003: El usuario consultado tiene un error en su registro, por favor contacte al departamento de TI.", [], 500);
        }else if($diffDays < 90 && $diffYears == 0){
            //Caso 1: El usuario es de nuevo ingreso pero no tiene más de 90 días laborando.
            return $this->makeResponse(false, "EXITO");
        }else if($diffDays >= 90 && $diffYears == 0){
            //Caso 2: El usuario es de nuevo ingreso pero tiene más de 90 días laborando
            $eaygDisp = $dvaa[1];
            $eaygDiasCalc = ($eaygDisp / 365) * $diffDays;
            $eaygDiasCalc = intval($eaygDiasCalc);
            //Una vez obtenidos los días proporcionales de EAYG se buscan los periodos de vacaciones tomados
            $peva  = $fein->toDateString() . "|";
            $peva .= $fein->addYear()->toDateString();

            $qryPeva = "SELECT * FROM S001V01TPEVA WHERE PEVA_PEVA = :peva AND PEVA_EMPL = :empl";
            $gstPeva = $pdo->prepare($qryPeva);

            $gstPeva->bindParam(":peva", $peva);
            $gstPeva->bindParam(":empl", $idus);

            try{
                $gstPeva->execute();
            }catch(PDOException $e){
                return $this->makeResponse(true, "ERR_MESMPR_SER_GVS004: No se pudieron consultar los periodos tomados por el usuario.", [], 500);
            }

            $periodosV = $gstPeva->fetchAll($pdo::FETCH_ASSOC);
            $detalles = array();
            //Se descuentan los días que el usuario haya tomado
            foreach($periodosV as $periodoV){
                $diasTomados = $periodoV['PEVA_VAPE'] - $periodoV['PEVA_VAGO'];
                $eaygDiasCalc = $eaygDiasCalc - $diasTomados;
                $detalles[] = [
                    "FECHASVACACIONES" => $periodoV['PEVA_FETO'],
                    "DIASTOMADOS" => $diasTomados
                ];
            }

            $res = (object) [
                "PERIODO" => $peva,
                "VACACIONESDISPONIBLES" => 0,
                "DIASEAYGDISPONIBLES" => $eaygDiasCalc,
                "DETALLES" => $detalles
            ];
            
            return $this->makeResponse(false, "EXITO", [$res]);
        }else{
            //Caso 3: Usuarios con más de 1 año laborando
            $diasVacacionesArr = array();
            foreach($dvaa as $key=>$val){
                if(str_contains($key, "-")){
                    $arrLimites = explode("-", $key);
                    for($i = intval($arrLimites[0]); $i <= intval($arrLimites[1]); $i++){
                        $diasVacacionesArr[$i] = intval($val);
                    }
                }else{
                    $diasVacacionesArr[$key] = intval($val);
                }
            }

            $diasUsr = $diasVacacionesArr[$diffYears];
            $periodosV = array();
            for($i = 1; $i <= $diffYears; $i++){
                $periodo  = $fein->toDateString() . "|";
                $periodo .= $fein->addYear()->toDateString();

                $qryPeva = "SELECT * FROM S001V01TPEVA WHERE PEVA_PEVA = :peva AND PEVA_EMPL = :idus";
                $gstPeva = $pdo->prepare($qryPeva);

                $gstPeva->bindParam(":peva", $periodo);
                $gstPeva->bindParam(":idus", $idus);

                try{
                    $gstPeva->execute();
                }catch(PDOException $e){
                    return $this->makeResponse(true, "ERR_MESMPR_SER_GVS005: No se pudieron consultar los periodos tomados por el usuario.", [], 500);
                }

                $periodos = $gstPeva->fetchAll($pdo::FETCH_ASSOC);
                $detalles = array();
                
                foreach($periodos as $per){
                    $vacacionesGozadas = $per['PEVA_VAPE'] - $per['PEVA_VAGO'];
                    $diasUsr = $diasUsr - $vacacionesGozadas;

                    $detalles[] = [
                        "FECHASVACACIONES" => $per['PEVA_FETO'],
                        "DIASTOMADOS" => $vacacionesGozadas
                    ];
                }

                $periodoV = (object) [
                    "PERIODO" => $periodo,
                    "VACACIONESDISPONIBLES" => $diasUsr,
                    "DIASEAYGDISPONIBLES" => 0,
                    "DETALLES" => $detalles
                ];
                $periodosV[] = $periodoV;
            }
            //Al finalizar el cálculo de los periodos disponibles de los usuarios se añade los disponibles por EAYG si puede aplicarlos
            $diffEAYG = $now->diffInDays($fein);
            if($diffEAYG >= 30){
                $diasAplicables = $diasVacacionesArr[$diffYears + 1];
                $diasEAYG = ($diasAplicables / 365) * $diffEAYG;
                $diasEAYG = intval($diasEAYG);
                $periodoStr = $fein->toDateString() . "|" . $fein->addYear()->toDateString();

                $qryPeva = "SELECT * FROM S001V01TPEVA WHERE PEVA_PEVA = :peva AND PEVA_EMPL = :idus";
                $gstPeva = $pdo->prepare($qryPeva);

                $gstPeva->bindParam(":peva", $periodoStr);
                $gstPeva->bindParam(":idus", $idus);

                try{
                    $gstPeva->execute();
                }catch(PDOException $e){
                    return $this->makeResponse(true, "ERR_MESMPR_SER_GVS006: No se pudieron consultar los periodos Earn As Yo Go tomados por el usuario.", [], 500);
                }

                $periodosEAYG = $gstPeva->fetchAll($pdo::FETCH_ASSOC);
                $detalles = array();
                
                foreach($periodosEAYG as $per){
                    $vacacionesGozadas = $per['PEVA_VAPE'] - $per['PEVA_VAGO'];
                    $diasEAYG = $diasEAYG - $vacacionesGozadas;

                    $detalles[] = [
                        "FECHASVACACIONES" => $per['PEVA_FETO'],
                        "DIASTOMADOS" => $vacacionesGozadas
                    ];
                }

                $periodoV = (object) [
                    "PERIODO" => $periodoStr,
                    "VACACIONESDISPONIBLES" => 0,
                    "DIASEAYGDISPONIBLES" => $diasEAYG,
                    "DETALLES" => $detalles
                ];
                $periodosV[] = $periodoV;
            }
            return $this->makeResponse(false, "EXITO", $periodosV);
        }*/
    }

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