<?php

namespace App\Http\Controllers;
use App\Custom\SQLConnection;
use App\Custom\Misc;

use Illuminate\Support\Facades\Response;
use Illuminate\Support\Facades\Session;
use Illuminate\Support\Facades\Request;
use PragmaRX\Google2FALaravel\Facade as Google2FA;
use BaconQrCode\Renderer\ImageRenderer;
use BaconQrCode\Renderer\Image\ImagickImageBackEnd;
use BaconQrCode\Renderer\RendererStyle\RendererStyle;
use BaconQrCode\Writer;
use Log;

use Auth;
class LoginController extends Controller {

	//Cambiar la clave actual con parametros post.
	public function cambiarClave() {
		$usuario = Misc::decrypt(Request::input('u'));
		// $usuario 				= Request::input('u');
		$clave_anterior = Request::input('old_password');
		$clave_nueva = Request::input('new_password');
		//

		if (!preg_match('/^[A-ZÑa-zñ0-9!@#$%^&()\-_+*=]{10,26}$/', $clave_nueva)) {
			// La clave nueva no cumple con los requisitos
			return json_encode(array('error' => 2, 'mensaje' => 'La contraseña debe contener entre 10 y 26 caracteres, una minúscula, una mayúscula, un número, y un caracter especial'));
			//
		}
		//
		$respuesta = SQLConnection::cambiarClave($usuario, $clave_anterior, $clave_nueva);
		if (isset($respuesta->status)) {
			switch ($respuesta->status) {
				case '20':
					return json_encode(array('error' => 0, 'mensaje' => "OK"));
					break;
				default:
					return json_encode(array('error' => 1, 'mensaje' => $respuesta->status_message));
					break;
			}
		}
	}

	//Envía mail para restablecer la clave de un usuario
	public function enviarRestablecerClave() {
		$mail = Request::input('mail');
		//

		$data = SQLConnection::enviarRestablecerClave($mail);
		if (!isset($data)) {
			Log::warning('No un usuario vinculado a este email'.$mail);
			return json_encode(array('error' => 0,'mensaje' => "Si la información que ingresaste coincide con una cuenta, te enviaremos un correo electrónico con instrucciones para restablecer tu contraseña."));
		}
		$date = strtotime("now");
		$content = new \stdClass();
		$content->username = $data->username;
		$user_encrypt = Misc::encrypt(json_encode(array('u' => $data->username, 'd' => $date)));
		$user_encrypt = urlencode($user_encrypt);
		$content->link = "http://" . \Request::header()['host'][0] . "/restablecer-clave?u=$user_encrypt";
		if (Misc::enviarMail("mails/restablecer_clave", $data->email, $content, "Recuperación de Clave")) {
			// return json_encode(array('error' => 0, 'mensaje' => "Se enviaron los datos de restablecimiento de mail a " . $mail));
			return json_encode(array('error' => 0,'mensaje' => "Si la información que ingresaste coincide con una cuenta, te enviaremos un correo electrónico con instrucciones para restablecer tu contraseña."));
		}
		Log::warning('No se pudo enviar la solicitud de restablecimiento de contraseña para '.$mail);
		return json_encode(array('error' => 0,'mensaje' => "Si la información que ingresaste coincide con una cuenta, te enviaremos un correo electrónico con instrucciones para restablecer tu contraseña."));
		// return json_encode(array('error' => 1, 'mensaje' => 'Ocurrió un error al intentar procesar su solicitud, por favor reintente mas tarde'));
	}


	/*Vista con el formulario de restablecimiento de clave, previamente se chequea que posea 20 min de duración máxima de restablecimiento de la misma sino debe
		  volver a pedir otro restablecimiento de clave.*/
	public function obtenerRestablecerClave() {
		$usuario = json_decode(Misc::decrypt(Request::input('u')));
		//
		$error = "";
		if (!$usuario) {
			$error = "Ocurrió un error inesperado, por favor vuelva a recuperar la clave desde el menú";
		}
		$date1 = new \DateTime(date('Y-m-d H:i:s', $usuario->d));
		$date2 = new \DateTime("now");
		$interval = $date1->diff($date2);
		if ($interval->y > 0 || $interval->m > 0 || $interval->d > 0 || $interval->h > 0 || $interval->i > 20) {
			$error = "La sesión expiró por favor vuelva a reiniciar el proceso de recuperación de clave <a href='/'>Aquí</a>";
		}
		$usuario = Misc::encrypt(json_encode(array('usuario' => (string) $usuario->u)));
		return \View::make('formulario_restablecer_clave')->with('error', $error)->with('usuario', $usuario);
	}

	//cambia la contraseña de un usuario sin su clave anterior, esto solo ocurre cuando el usuario olvida su clave.
	public function restablecerClave() {
		$respuesta = json_decode(Misc::decrypt(Request::input('u')));
		$clave = Request::input('clave');
		if (!isset($respuesta->usuario) || !$clave) {
			return false;
		}
		$usuario = $respuesta->usuario;
		$data = SQLConnection::restablecerClave($usuario, $clave);
		if ($data->status == 20) {
			return json_encode(array('error' => 0, 'mensaje' => $data->status_message));
		} else {
			return json_encode(array('error' => 1, 'mensaje' => $data->status_message));
		}
	}

	public function obtenerLogin() {
		$mensaje = '';
		if (request::Input('ns')) {
			$mensaje = 'Su sesión expiró, por favor vuelva a iniciar sesión';
		}
		if (!is_null(Session::get('usuario'))) {
			return redirect('/');
		}
		return view('loginNew');
	}

	//Si los datos son correctos inicia y genera una sesión para el usuario
	public function iniciarSesion() {
		$usuario = Request::Input('usuario');
		$clave = Request::Input('clave');
		if (!isset($usuario) || !isset($clave)) {
			return false;
		}
		$usuario = SQLConnection::iniciarSesion($usuario, $clave, $simultaneo = 0);
		if (isset($usuario->status)) {
			if ($usuario->status == 0 || $usuario->status == 1) {
				/*$cliente = SQLConnection::obtenerCliente($usuario->user_id);
																if(($cliente) && $cliente->estado_cliente != 'A'){
																  return json_encode(array('error' => 99,'mensaje' => "El cliente se encuentra inactivo, por favor comuniquese al número 0800-SQL para la reactivación del mismo"));*/
			}
			$username = strtolower($usuario->username);
		}
		//
		switch ($usuario->status) {
			case '0':
				$permisos = SQLConnection::obtenerPermisos($usuario->user_id);
				$preferencias = SQLConnection::obtenerPreferenciasUsuario($usuario->user_id);
				//
				if (isset($preferencias->codigo_idioma)) {
					$usuario->codigo_idioma = $preferencias->codigo_idioma;
				}
				//
				if (empty($permisos)) {
					return json_encode(array('error' => 101, 'mensaje' => "Usuario no tiene permisos para loguearse"));
				}
				// Estructurar los permisos jerárquicamente
				$permisos = self::estructurarPermisosJerarquicos($permisos);
				//
				$user_horario = SQLConnection::backendStoreProcedure('obtener_users_horarios', array($usuario->user_id), 'selectOne');
				if (!isset($user_horario->respuesta)) {
					return json_encode(array('error' => 100, 'mensaje' => "No puede ingresar en éste momento"));
				}
				$usuario->user_horario = $user_horario;
				//
				Session::put('usuario', $usuario);
				Session::put('permisos', $permisos);
				Session::put('informes_test_access', false);
				Session::put('google_auth', false);
				Session::save();
				\Artisan::call('view:clear');
				return json_encode(array('error' => 0, 'mensaje' => "OK"));
				break;
			case '1':
				return json_encode(array('error' => 1, 'u' => Misc::encrypt($usuario->username), 'mensaje' => $usuario->status_message));
				break;
			default:
				return json_encode(array('error' => 2, 'mensaje' => $usuario->status_message));
				break;
		}
	}

	public static function Fa2Authentication(){
		$user_id = Session::get('usuario')->user_id;
		$qr_scaneado = true;
		$credenciales_seguridad = SQLConnection::backendStoreProcedure('userSecurityCredentials',array('SELECCIONAR',$user_id),true);
		if ( !empty($credenciales_seguridad) ){
			$secretKey = $credenciales_seguridad->two_factor_secret;
		} else {
			$secretKey = Google2FA::generateSecretKey();
			$qr_scaneado = false;
		}
		// Generate the QR code URL
		$qrCodeUrl = Google2FA::getQRCodeUrl(
			config('app.name'),
			Session::get('usuario')->email,
			$secretKey
		);
		// Generate the Google Secret
		Session::put(['google2fa_secret' => $secretKey]);

		$writer = new Writer(
			new ImageRenderer(
				new RendererStyle(400),
				new ImagickImageBackEnd()
			)
		);

		$qrcode_image = base64_encode($writer->writeString($qrCodeUrl));

		return view('google2fa-enable', compact('qrcode_image', 'secretKey', 'qr_scaneado'));
	}

	public static function Fa2Validation(){
		$secret = Session::get('google2fa_secret');
		$verification_id = Request::input('id_verification');
		$user_id = Session::get('usuario')->user_id;
		// cantidad de intentos
		$cant_intentos = Session::get('intentos') ?? 0;
		Session::put('intentos',$cant_intentos + 1);
		//
		if (Google2FA::verifyKey($secret, $verification_id)) {
			// Grabo Key en la base de datos
			SQLConnection::backendStoreProcedure('userSecurityCredentials',array('AUTORIZAR',$user_id,$secret));
			//
			Session::forget('intentos');
			Session::forget('google2fa_secret');
			Session::put('2fa_verified',true);
			Session::save();
			//
			return Response::json(['link' => '/','error' => 0]);
		}
		if ( ($cant_intentos + 1) >= 3 ){
			Session::forget('intentos');
			Session::forget('google2fa_secret');
			Session::save();
			return Response::json(['link' => '/cerrar-sesion','error' => 1]);
		}
		return Response::json(['link' => null,'error' => 2]);
	}

	//Cierra la sesión actual y redirecciona al /
	public function cerrarSesion() {
		if ( isset(Session::get('usuario')->username) ){
            $username = Session::get('usuario')->username;
            SQLConnection::cerrarSesion($username);
        }
		Session::flush();
		Session::invalidate(); // borra el archivo de session
		Session::regenerate(); // genera una session nueva
		Session::save();
		return redirect('/login');
	}
	/**
	 * Funcion que devuelve una matriz con los permisos jerarquicamente distribuidos
	 * 
	 * @access public
	 * @static
	 * @param array|null|\Countable $permisos La lista de permisos
	 * @return array|object la lista jerarquica de permisos
	 */
	public static function estructurarPermisosJerarquicos($permisos) {
		$permisos_estructurados = (object) ['primarios' => [], 'secundarios' => [], 'terciarios' => []];
		$nodos_hijos = [];
		$nodos_padres = [];
		//
		$cant_permisos = count($permisos);
		// loop diferencia los independientes de los dependientes
		for ($i = 0; $i < $cant_permisos; $i++) {
			if (is_null($permisos[$i]->dependent_item) && !in_array($permisos[$i]->id_menu_item, $nodos_padres)) {
				// registros primarios
				$permisos_estructurados->primarios[] = $permisos[$i];
				$nodos_padres[] = $permisos[$i]->id_menu_item;
			} else if (!is_null($permisos[$i]->dependent_item) && !in_array($permisos[$i]->id_menu_item, $nodos_hijos)) {
				// registros con hijos
				$nodos_hijos[] = $permisos[$i]->id_menu_item;
			}
		}
		// loop diferencia los que tienen padre y hijo de los que tienen solo hijo
		for ($i = 0; $i < $cant_permisos; $i++) {
			if (!is_null($permisos[$i]->dependent_item)) {
				if (in_array($permisos[$i]->dependent_item, $nodos_hijos)) {
					// registros terciarios (si su padre esta como hijo)
					$permisos_estructurados->terciarios[$permisos[$i]->dependent_item][] = $permisos[$i];
				} else if (in_array($permisos[$i]->id_menu_item, $nodos_hijos)) {
					// sino registros secundarios
					$permisos_estructurados->secundarios[$permisos[$i]->dependent_item][] = $permisos[$i];
				}
			}
		}
		//
		unset($permisos);
		//
		return $permisos_estructurados;
	}

	public function accesoReportesTest() {
		if (Session::has('informes_test_access')) {
			if (Session::get('informes_test_access')) {
				// quita acceso
				Session::forget('informes_test_access');
				Session::put('informes_test_access', false);
			} else {
				// da acceso
				Session::forget('informes_test_access');
				Session::put('informes_test_access', true);
			}
		} else {
			Session::put('informes_test_access', false);
		}
		//
		return Response::Json(['error' => 0, 'mensaje' => 'OK']);
	}

	//pato 01/08 para ver informe comercial
	public static function obtenerSeccionesHabilitadas($user_id) {
		$secciones_habilitadas = SQLConnection::obtenerSeccionesHabilitadasInforme($user_id, ENV('ID_INFORME_COMERCIAL'));
		$secciones_habilitadas_ordenadas = [];
		foreach ($secciones_habilitadas as $secciones) {
			$secciones_habilitadas_ordenadas[$secciones->nombre_seccion] = $secciones;
		}
		return $secciones_habilitadas_ordenadas;
	}

}
