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

class MCOMPVController extends Controller
{
    public function create(Request $request){
        $validator = Validator::make($request->all(), [
            'rfc_empresa' => 'required|string',
            'nombre_politica' => 'required|string|max:100',
            'dias_vacaciones' => 'required|string',
            'earn_as_you_go' => 'required|string|max:2',
            //'dias_earn_as_you_go' => 'required_if:earn_as_you_go,==,Si|integer|max:30',
            'dias_descanso' => 'required|string',
            //'caducidad' => 'required|date',
            'id_usuario_registra' => 'required|string|max:50',
        ]);

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

        $politica = $request->all();

        if(!$this->isJSON($politica['dias_vacaciones'])) return $this->makeResponse(true, "ERR_MCOMPV_USU_CRE001: El campo dias_vacaciones debe tener un formato JSON", [], 400);
        if(!$this->isJSON($politica['dias_descanso'])) return $this->makeResponse(true, "ERR_MCOMPV_USU_CRE002: El campo dias_descanso debe tener un formato JSON", [], 400);
        
        //$caducidad = new Carbon($politica['caducidad']);
        $hoy = Carbon::now()->timezone('America/Mexico_City');
        
        /*if($hoy->gt($caducidad)) return $this->makeResponse(true, "ERR_MCOMPV_USU_CRE003: La fecha de caducidad debe ser mayor a la actual", [], 400);
        if($hoy->diffInMonths($caducidad) < 12) return $this->makeResponse(true, "ERR_MCOMPV_USU_CRE004: La fecha de caducidad debe ser al menos 12 meses mayor a la actual", [], 400);
        if($hoy->diffInMonths($caducidad) > 24) return $this->makeResponse(true, "ERR_MCOMPV_USU_CRE005: La fecha de caducidad debe ser máximo 24 meses mayor a la actual", [], 400);
        */
        $pdo = DB::connection()->getPdo();
        $qry = 'INSERT INTO S001V01TPOLI (POLI_RFCE, POLI_NOPO, POLI_DVAA, POLI_EAYG, POLI_DIDE, POLI_USRE, POLI_FERE, POLI_FEAR) 
                VALUES (:rfce, :nopo, :dvaa, :eayg, :dide, :usre, :fere, CURRENT_TIMESTAMP)';
        $gst = $pdo->prepare($qry);

        $diasEarnAsYouGo = $politica['earn_as_you_go'] == "S" ? $politica['dias_earn_as_you_go'] : null;
        $encriptacion = new EncController();
        $rfce = $encriptacion->desencriptar($politica['rfc_empresa']);
        $fere = $hoy->toDateTimeString();

        $gst->bindParam(":rfce", $rfce);
        $gst->bindParam(":nopo", $politica['nombre_politica']);
        $gst->bindParam(":dvaa", $politica['dias_vacaciones']);
        $gst->bindParam(":eayg", $politica['earn_as_you_go']);
        //$gst->bindParam(":deay", $diasEarnAsYouGo);
        $gst->bindParam(":dide", $politica['dias_descanso']);
        //$gst->bindParam(":cadu", $politica['caducidad']);
        $gst->bindParam(":usre", $politica['id_usuario_registra']);
        $gst->bindParam(":fere", $fere);

        if (!$gst->execute()) {
            return $this->makeResponse(true, "ERR_MCOMPV_SER_CRE006: Error al insertar la política", [], 500);
        }

        return $this->makeResponse(false, "EXITO: Política insertada");
    }

    public function update(Request $request){
        $validator = Validator::make($request->all(), [
            'nombre_politica' => 'required|string|max:100',
            'dias_vacaciones' => 'required|string',
            'earn_as_you_go' => 'required|string|max:2',
            //'dias_earn_as_you_go' => 'required_if:earn_as_you_go,==,Si|integer|max:30',
            'dias_descanso' => 'required|string',
            //'caducidad' => 'required|date',
            'id_usuario_modifica' => 'required|string|max:50',
            'id_politica' => 'required|integer'
        ]);

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

        $politica = $request->all();

        if(!$this->isJSON($politica['dias_vacaciones'])) return $this->makeResponse(true, "ERR_MCOMPV_USU_UPD001: El campo dias_vacaciones debe tener un formato JSON", [], 400);
        if(!$this->isJSON($politica['dias_descanso'])) return $this->makeResponse(true, "ERR_MCOMPV_USU_UPD002: El campo dias_descanso debe tener un formato JSON", [], 400);
        
        //$caducidad = new Carbon($politica['caducidad']);
        $hoy = $fere = Carbon::now()->timezone('America/Mexico_City');
        
        /*if($hoy->gt($caducidad)) return $this->makeResponse(true, "ERR_MCOMPV_USU_UPD003: La fecha de caducidad debe ser mayor a la actual", [], 400);
        if($hoy->diffInMonths($caducidad) < 12) return $this->makeResponse(true, "ERR_MCOMPV_USU_UPD004: La fecha de caducidad debe ser al menos 12 meses mayor a la actual", [], 400);
        if($hoy->diffInMonths($caducidad) > 24) return $this->makeResponse(true, "ERR_MCOMPV_USU_UPD005: La fecha de caducidad debe ser máximo 24 meses mayor a la actual", [], 400);
        */
        $pdo = DB::connection()->getPdo();
        $qryRFCE = "SELECT USUA_RFCE FROM S001V01TUSUA WHERE USUA_IDUS = :idus";
        $gstRFCE = $pdo->prepare($qryRFCE);
        $gstRFCE->bindParam(":idus", $politica['id_usuario_modifica']);

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

        $qry = "UPDATE S001V01TPOLI SET POLI_NOPO = :nopo, POLI_DVAA = :dvaa, POLI_EAYG = :eayg, POLI_DIDE = :dide, POLI_USMO = :usmo, POLI_FEMO = :femo, 
        POLI_FEAR = CURRENT_TIMESTAMP WHERE POLI_IDPO = :idpo AND POLI_RFCE = :rfce";
        $gst = $pdo->prepare($qry);

        $diasEarnAsYouGo = $politica['earn_as_you_go'] == "S" ? $politica['dias_earn_as_you_go'] : null;
        $femo = $hoy->toDateTimeString();

        $gst->bindParam(":nopo", $politica['nombre_politica']);
        $gst->bindParam(":dvaa", $politica['dias_vacaciones']);
        $gst->bindParam(":eayg", $politica['earn_as_you_go']);
        $gst->bindParam(":dide", $politica['dias_descanso']);
        $gst->bindParam(":usmo", $politica['id_usuario_modifica']);
        $gst->bindParam(":femo", $femo);
        $gst->bindParam(":idpo", $politica['id_politica']);
        $gst->bindParam(":rfce", $rfce);

        if (!$gst->execute()) {
            return $this->makeResponse(true, "ERR_MCOMPV_SER_UPD006: Error al modificar la política", [], 500);
        }

        return $this->makeResponse(false, "EXITO: Política modificada");
    }

    public function delete(Request $request){
        $validator = Validator::make($request->all(), [
            'id_usuario_elimina' => 'required|string|max:50',
            'id_politica' => 'required|integer'
        ]);

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

        $politica = $request->all();
        $pdo = DB::connection()->getPdo();
        $qryRFCE = "SELECT USUA_RFCE FROM S001V01TUSUA WHERE USUA_IDUS = :idus";
        $gstRFCE = $pdo->prepare($qryRFCE);
        $gstRFCE->bindParam(":idus", $politica['id_usuario_elimina']);

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

        $qryUsu = "SELECT * FROM S001V01TUSUA WHERE USUA_POLI = :poli";
        $gstUsu = $pdo->prepare($qryUsu);

        $gstUsu->bindParam(":poli", $politica['id_politica']);

        if(!$gstUsu->execute()){
            return $this->makeResponse(true, "ERR_MCOMPV_SER_DEL001: No se pudieron consultar los usuarios vinculados a la política requerida.", [], 500);
        }

        $usuarios = $gstUsu->fetchAll($pdo::FETCH_ASSOC);
        if(count($usuarios) > 0){
            return $this->makeResponse(true, "ERR_MCOMPV_USU_DEL002: La política no se puede eliminar por que hay usuarios vinculados a ella.", [], 401);
        }
        
        $qry = "UPDATE S001V01TPOLI SET POLI_ESTA = 'Eliminado', POLI_USMO = :usmo, POLI_FEMO = :femo, POLI_FEAR = CURRENT_TIMESTAMP WHERE POLI_IDPO = :idpo AND POLI_RFCE = :rfce";
        $gst = $pdo->prepare($qry);

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

        $gst->bindParam(":usmo", $politica['id_usuario_elimina']);
        $gst->bindParam(":femo", $femo);
        $gst->bindParam(":idpo", $politica['id_politica']);
        $gst->bindParam(":rfce", $rfce);

        if (!$gst->execute()) {
            return $this->makeResponse(true, "ERR_MCOMPV_SER_DEL003: Error al eliminar la política.", [], 500);
        }

        return $this->makeResponse(false, "EXITO: Política eliminada");
    }

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

        $qry = 'SELECT POLI_IDPO AS IDPOLITICA, POLI_NOPO AS NOMBREPOLITICA, POLI_DVAA AS DIASVACACIONESAPLICABLES, POLI_EAYG AS EARNASYOUGO, 
        POLI_DEAY AS DIASEARNASYOUGO, POLI_DIDE AS DIASDESCANSO, POLI_CADU AS CADUCIDAD FROM S001V01TPOLI WHERE POLI_ESTA != "Eliminado" AND POLI_RFCE = :rfce';
        $gst = $pdo->prepare($qry);
        $gst->bindParam(":rfce", $rfce);
        
        if (!$gst->execute()) {
            return $this->makeResponse(true, "ERR_MCOMPV_SER_GPO000: No se pudo recuperar información de la base de datos.", [], 500);
        }

        $politicas = $gst->fetchAll($pdo::FETCH_ASSOC);
        $politicasF = array();

        foreach($politicas as $politica){
            $diasVacaciones = json_decode($politica['DIASVACACIONESAPLICABLES'], true);
            $politicaF = array();
            foreach($diasVacaciones as $key=>$value){
                if(str_contains($key, "-")){
                    $limites = explode("-", $key);
                    for($i = intval($limites[0]); $i <= intval($limites[1]); $i++){
                        $politicaF[] = [
                            "anio" => $i,
                            "dias" => $value
                        ];
                    }
                }else{
                    $politicaF[] = [
                        "anio" => $key,
                        "dias" => $value
                    ];
                }
            }
            $diasDescanso = json_decode($politica['DIASDESCANSO'], true);
            $descansoF = array();
            foreach($diasDescanso as $key=>$value){
                $descansoF[] = [
                    "dia" => $key,
                    "descansa" => $value
                ];
            }
            $politicasF[] = [
                "IDPOLITICA" => $politica['IDPOLITICA'],
                "NOMBREPOLITICA" => $politica['NOMBREPOLITICA'],
                "DIASVACACIONESAPLICABLES" => $politicaF,
                "EARNASYOUGO" => $politica['EARNASYOUGO'],
                //"DIASEARNASYOUGO" => $politica['DIASEARNASYOUGO'],
                "DIASDESCANSO" => $descansoF,
                //"CADUCIDAD" => $politica['CADUCIDAD'],
            ];
        }

        return $this->makeResponse(false, "EXITO: Consulta exitosa", $politicasF);
    }

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

        $qry = 'SELECT POLI_IDPO AS IDPOLITICA, POLI_NOPO AS NOMBREPOLITICA, POLI_DVAA AS DIASVACACIONESAPLICABLES, POLI_EAYG AS EARNASYOUGO, 
        POLI_DEAY AS DIASEARNASYOUGO, POLI_DIDE AS DIASDESCANSO, POLI_CADU AS CADUCIDAD, POLI_ESTA AS ESTATUS FROM S001V01TPOLI WHERE POLI_IDPO = :idpo AND POLI_RFCE = :rfce';
        $gst = $pdo->prepare($qry);

        $gst->bindParam(":idpo", $idpo);
        $gst->bindParam(":rfce", $rfce);
        
        if (!$gst->execute()) {
            return $this->makeResponse(true, "ERR_MCOMPV_SER_GEP000: No se pudo recuperar información de la base de datos.", [], 500);
        }

        $politica = $gst->fetchObject();
        
        if(!$politica){
            return $this->makeResponse(true, "ERR_MCOMPV_USU_GEP001: La política no existe.", [], 404);
        }

        if ($politica->ESTATUS == 'Eliminado') {
            return $this->makeResponse(true, "ERR_MCOMPV_USU_GEP002: Politica eliminada.", [], 404);
        }

        //return response()->json(['politica' => $politica], 200);
        return $this->makeResponse(true, "EXITO", $politica);
    }

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

    private function isJSON($string){
        json_decode($string);
        return json_last_error() === JSON_ERROR_NONE;
    }
}
