<?php
require_once __DIR__ . '/../app.php';
!class_exists("Rol") && require_once __DIR__ . '/../Models/rolModel.php';

header("Content-Type: application/json; charset=utf-8");

$respuesta = (object)[];

$sesionIniciada = App::verificarSesionIniciada();

if ($_SERVER["REQUEST_METHOD"] === "GET") {
    $accion = isset($_GET['accion']) ? $_GET['accion'] : null;

    switch ($accion) {
        case 'obtenerTodos':
            if (!App::validarRoot()) {
                $respuesta->status = 401;
                $respuesta->message = "No tiene permisos para realizar esta acción";
                break;
            }

            $respuesta = Usuario::obtenerTodos();
            break;
        case 'obtenerTodosParaCombo':
            App::verificarSesion();

            $respuesta = Usuario::obtenerTodosParaCombo();
            break;
        case 'obtenerRoles':
            $id = isset($_GET['id']) ? base64_decode(urldecode($_GET['id'])) : 0;

            if (!App::validarRoot() && $id != App::obtenerIdUsuario()) {
                $respuesta->status = 401;
                $respuesta->message = "No tiene permisos para realizar esta acción";
                break;
            }

            $usuario = new Usuario();
            $usuario->id = $id;

            $respuesta = $usuario->obtenerRoles();
            break;
        case 'verificarDisponibilidad':
            if (!App::validarRoot()) {
                $respuesta->status = 401;
                $respuesta->message = "No tiene permisos para realizar esta acción";
                break;
            }

            $id = isset($_GET['id']) && !empty($_GET['id']) ? base64_decode($_GET['id']) : 0;
            $username = isset($_GET['username']) && !empty($_GET['username']) ? $_GET['username'] : null;

            $respuesta = Usuario::verificarDisponibilidad($id, $username);
            break;
        case 'obtenerPorModulo':
            if (!App::validarRoot()) {
                $respuesta->status = 401;
                $respuesta->message = "No tiene permisos para realizar esta acción";
                break;
            }

            $modulo = isset($_GET['idModulo']) ? intval(base64_decode($_GET['idModulo'])) : 0;

            if ($modulo == 0 && isset($_GET['aid'])) {
                $idApartado = intval(base64_decode(urldecode($_GET['aid'])));
                !class_exists('Modulo') && require_once __DIR__ . '/../Models/moduloModel.php';

                $solicitud = Modulo::obtenerPorApartado($idApartado);

                if ($solicitud->status != 200 || empty($solicitud->data)) {
                    $respuesta->status = 404;
                    $respuesta->message = "No se encontró el módulo";
                    break;
                }

                $modulo = $solicitud->data->id;
            }

            !empty($modulo) && $modulo = intval($modulo);

            $respuesta = Usuario::obtenerPorModulo($modulo);
            break;
        case 'obtenerAsignacionesPorModulo':
            $idUsuario = isset($_GET['idUsuario']) ? base64_decode($_GET['idUsuario']) : 0;

            $modulo = isset($_GET['idModulo']) ? intval(base64_decode($_GET['idModulo'])) : 0;
            $contenedorModulo = isset($_GET['contenedorModulo']) ? urldecode($_GET['contenedorModulo']) : 'none';

            if ($modulo == 0 && isset($_GET['aid'])) {
                $idApartado = intval(base64_decode(urldecode($_GET['aid'])));
                !class_exists('Modulo') && require_once __DIR__ . '/../Models/moduloModel.php';

                $solicitud = Modulo::obtenerPorApartado($idApartado);

                if ($solicitud->status != 200 || empty($solicitud->data)) {
                    $respuesta->status = 404;
                    $respuesta->message = "No se encontró el módulo";
                    break;
                }

                $modulo = $solicitud->data->id;
                $contenedorModulo = $solicitud->data->contenedor;
            }

            !empty($modulo) && $modulo = intval($modulo);

            $respuesta = Usuario::obtenerAsignacionesPorModulo($idUsuario, $modulo, $contenedorModulo);
            break;
        default:
            $respuesta->status = 400;
            $respuesta->message = "Acción no válida";
            break;
    }
}

if ($_SERVER["REQUEST_METHOD"] === 'POST') {
    $input = json_decode(file_get_contents('php://input'), true);
    !empty($_POST) && $input = $_POST;
    $accion = isset($input['accion']) ? $input['accion'] : null;

    switch ($accion) {
        case 'autenticar':
            $contrasenia = isset($input['contrasenia']) ? md5(base64_decode($input['contrasenia'])) : '';
            $usuario = new Usuario();
            $usuario->username = $input['username'];

            $respuesta = $usuario->autenticar($contrasenia);
            break;
        case 'cambiarContrasenia':
            $id = isset($input['id']) ? base64_decode($input['id']) : null;
            $username = isset($input['username']) ? $input['username'] : null;
            $contrasenia = isset($input['contrasenia']) ? md5(base64_decode($input['contrasenia'])) : null;
            $nuevaContrasenia = isset($input['nuevaContrasenia']) ? md5(base64_decode($input['nuevaContrasenia'])) : null;
            $origen = isset($input['origen']) ? $input['origen'] : 'Usuario';

            if (empty($id) && App::verificarSesionIniciada())
                $id = $_SESSION[INDICE_SESION]->id;

            $usuario = new Usuario();
            $usuario->id = $id;
            $usuario->username = $username;

            $respuesta = $usuario->cambiarContrasenia($contrasenia, $nuevaContrasenia, $origen);

            if ($respuesta->status == 200 && $respuesta->message == 'success' && mb_strtolower($origen, 'utf-8') == 'login') {
                $respuesta = $usuario->autenticar($nuevaContrasenia);
            }
            break;
        case 'cerrarSesion':
            if (isset($_SESSION[INDICE_SESION])) {
                $respuesta = $_SESSION[INDICE_SESION]->cerrarSesion();
            } else {
                $respuesta->status = 200;
                $respuesta->message = 'success';
            }
            break;
        case 'guardar':
            if (!App::validarRoot()) {
                $respuesta->status = 401;
                $respuesta->message = "No tiene permisos para realizar esta acción";
                break;
            }

            $usuario = new Usuario();
            $usuario->id = isset($input['id']) ? base64_decode($input['id']) : 0;
            $usuario->username = $input['username'];
            $usuario->nombres = $input['nombres'];
            $usuario->apellidos = $input['apellidos'];
            $usuario->email = $input['email'];

            $contrasenia = isset($input['contrasenia']) && !empty($input['contrasenia']) ? md5(base64_decode($input['contrasenia'])) : null;

            $db = obtenerConexion();

            try {
                $db->beginTransaction();
                $respuesta = $usuario->guardar($db, $contrasenia);

                if ($respuesta->status != 200 || ($respuesta->status == 200 && $respuesta->message != 'success')) {
                    $db->rollBack();
                    break;
                }

                $idRoles = array_values(array_map(function ($rol) {
                    return $rol["idRol"];
                }, (array_filter($input["roles"], function ($rol) {
                    return intval($rol["idRol"]) != 0;
                }))));

                $rolesPendientes = array_values(array_filter($input["roles"], function ($rol) {
                    return intval($rol["idRol"]) == 0;
                }));

                foreach ($rolesPendientes as $rol) {
                    $nuevoRol = new Rol();
                    $nuevoRol->id = 0;
                    $nuevoRol->rol = $rol["rol"];
                    $nuevoRol->idTipo = $rol["idTipo"];

                    $respuestaRol = $nuevoRol->guardar($db);

                    if ($respuestaRol->status != 200 || ($respuestaRol->status == 200 && $respuestaRol->message != 'success')) {
                        $respuesta->status = $respuestaRol->status;
                        $respuesta->message = "Error al guardar el rol: " . $rol["rol"];
                        $db->rollBack();
                        break;
                    }

                    $idRoles[] = $respuestaRol->id;
                }

                $usuario->id = $respuesta->data->id;
                $respuestaRoles = $usuario->guardarRoles($db, $idRoles);

                if ($respuestaRoles->status != 200 || ($respuestaRoles->status == 200 && $respuestaRoles->message != 'success')) {
                    $respuesta->status = $respuestaRoles->status;
                    $respuesta->message = "Ocurrió un error al guardar los roles del usuario";
                    $db->rollBack();
                    break;
                }

                $db->commit();
            } catch (PDOException $e) {
                $db->rollBack();
                $respuesta->status = 500;
                $respuesta->message = $e->getMessage();
            }
            break;
        case "crearContrasenia":
            if (!App::verificarSesionIniciada()) {
                $respuesta->status = 403;
                $respuesta->message = "No tiene permisos para realizar esta acción";
                break;
            }

            $usuario = new Usuario();
            $usuario->id = isset($input['id']) ? base64_decode($input['id']) : 0;
            $usuario->username = $input['username'];
            $usuario->email = $input['email'];

            $respuesta = $usuario->crearContrasenia();
            break;
        case "cambiarEstado":
            if (!App::validarRoot()) {
                $respuesta->status = 401;
                $respuesta->message = "No tiene permisos para realizar esta acción";
                break;
            }

            $usuario = new Usuario();
            $usuario->id = isset($input['id']) ? base64_decode($input['id']) : 0;
            $nuevoEstado = isset($input['bloqueado']) ? $input['bloqueado'] : 1;

            $respuesta = $usuario->cambiarEstado($nuevoEstado);
            break;
        case "eliminar":
            if (!App::validarRoot()) {
                $respuesta->status = 401;
                $respuesta->message = "No tiene permisos para realizar esta acción";
                break;
            }

            $usuario = new Usuario();
            $usuario->id = isset($input['id']) ? base64_decode($input['id']) : 0;

            $respuesta = $usuario->eliminar(App::obtenerIdUsuario());
            break;
        case "actualizarFoto":
            App::verificarSesion();

            $usuario = new Usuario();
            $usuario->id = isset($input['id']) ? base64_decode($input['id']) : 0;

            if (empty($_FILES)) {
                $respuesta->status = 400;
                $respuesta->message = "No se ha enviado ninguna imagen";
                break;
            }

            $extension = pathinfo($_FILES['archivo']['name'], PATHINFO_EXTENSION);
            $nombreArchivo = 'u' . $usuario->id . '.' . $extension;

            $respuesta = $usuario->actualizarFoto($nombreArchivo);

            if ($respuesta->status == 200 && $respuesta->message == 'success') {
                $directorio = __DIR__ . '/../../assets/images/users/';
                file_exists($directorio . $nombreArchivo) && unlink($directorio . $nombreArchivo);
                move_uploaded_file($_FILES['archivo']['tmp_name'], $directorio . $nombreArchivo);

                if ($usuario->id == App::obtenerIdUsuario()) App::actualizarFotoUsuario($nombreArchivo);
            }
            break;
        case 'guardarAsignacionesModulo':
            App::verificarAcceso();
            $id = isset($input['id']) ? base64_decode($input['id']) : 0;
            $idModulo = isset($input['idModulo']) ? intval($input['idModulo']) : 0;
            $modulo = 'GENERAL';

            $idSuperior = null; //IMPORTANTE, PARA MÓDULOS QUE REQUIERAN UN PARÁMETRO SUPERIOR A LA EMPRESA

            $asignaciones = isset($input['asignaciones']) ? $input['asignaciones'] : array();

            if ($idModulo == 0 && isset($input['aid'])) {
                !class_exists("Modulo") && require_once __DIR__ . '/../models/moduloModel.php';

                $idApartado = isset($input['aid']) ? intval(base64_decode(urldecode($input['aid']))) : 0;

                $requestModulo = Modulo::obtenerPorApartado($idApartado);

                if ($requestModulo->status != 200 || empty($requestModulo->data)) {
                    $respuesta->status = 500;
                    $respuesta->message = 'Error al obtener el módulo';
                    break;
                }

                $idModulo = $requestModulo->data->id;
                $modulo = $requestModulo->data->contenedor;
            }

            $modulosSuperior = ['RRHH'];

            $empresasValidas = [];

            $asignacionesEmpresas = [];

            !class_exists("Empresa") && require_once __DIR__ . '/../models/empresaModel.php';
            !class_exists('Sucursal') && require_once __DIR__ . '/../models/sucursalModel.php';
            !class_exists('Proyecto') && require_once __DIR__ . '/../models/proyectoModel.php';

            $db = obtenerConexion();

            try {
                $db->beginTransaction();
                if (in_array($modulo, $modulosSuperior)) {
                    switch ($modulo) {
                        case 'RRHH':
                            !class_exists('TipoPlanilla') && require_once __DIR__ . '/../../RRHH/code/models/tipoPlanillaModel.php';

                            $tiposPlanillaValidos = [];
                            foreach ($asignaciones as $keyAsignacion => $asignacion) {
                                $idTipoPlanilla = intval($asignacion['idTipoPlanilla']);
                                $codtipoplanilla = intval($asignacion['codtipoplanilla']);
                                $tipoPlanilla = $asignacion['tipoPlanilla'];

                                $setTipoPlanilla = TipoPlanilla::guardarAsignacionUsuario($id, $idTipoPlanilla, $codtipoplanilla, $tipoPlanilla, $db);

                                if ($setTipoPlanilla->status != 200) {
                                    $db->rollBack();
                                    $respuesta->status = 500;
                                    $respuesta->message = 'Error al guardar las asignaciones, Tipo de planilla';
                                    echo json_encode($respuesta);
                                    die;
                                }

                                foreach ($asignacion['empresas'] as $keyEmpresa => $empresa) {
                                    $empresa['idSuperior'] = $codtipoplanilla;
                                    $asignacionesEmpresas[] = $empresa;
                                }

                                $tiposPlanillaValidos[] = $codtipoplanilla;
                            }

                            TipoPlanilla::limpiarAsignacionesPorUsuario($id, $tiposPlanillaValidos, $db);
                            break;
                    }
                }

                if (!in_array($modulo, $modulosSuperior)) {
                    $asignacionesEmpresas = $asignaciones;
                }

                foreach ($asignacionesEmpresas as $keyEmpresa => $empresa) {
                    $idAsignacion = intval($empresa['id']);
                    $idEmpresa = intval($empresa['idEmpresa']);
                    $nombreEmpresa = $empresa['nombreEmpresa'];
                    $codempresa = $empresa['codempresa'];
                    $idSuperior = isset($empresa['idSuperior']) ? intval($empresa['idSuperior']) : null;

                    $sucursalesValidas = [];

                    $setEmpresa = Empresa::guardarAsignacionUsuarioModulo($idAsignacion, $id, $idModulo, $idEmpresa, $codempresa, $nombreEmpresa, $idSuperior, $db);

                    if ($setEmpresa->status != 200) {
                        $db->rollBack();
                        $respuesta->status = 500;
                        $respuesta->message = 'Error al guardar las asignaciones, Empresas';
                        echo json_encode($respuesta);
                        die;
                    }

                    $idAsignacion = $setEmpresa->id;
                    $empresasValidas[] = $idAsignacion;

                    foreach ($empresa['sucursales'] as $keySucursal => $sucursal) {
                        $codsucursal = $sucursal['codsucursal'];
                        $nombreSucursal = $sucursal['nombreSucursal'];
                        $idAsignacionSucursal = intval($sucursal['id']);

                        $setSucursal = Sucursal::guardarAsignacionUsuarioEmpresaModulo($idAsignacion, $idAsignacionSucursal, $codsucursal, $nombreSucursal, $id, $db);

                        if ($setSucursal->status != 200) {
                            $db->rollBack();
                            $respuesta->status = 500;
                            $respuesta->message = 'Error al guardar las asignaciones, Sucursales';
                            echo json_encode($respuesta);
                            die;
                        }

                        $idAsignacionSucursal = $setSucursal->id;
                        $sucursalesValidas[] = $idAsignacionSucursal;

                        $proyectosValidos = [];

                        foreach ($sucursal['proyectos'] as $keyProyecto => $proyecto) {
                            $codproyecto = $proyecto['codproyecto'];
                            $nombreProyecto = $proyecto['nombreProyecto'];
                            $idAsignacionProyecto = intval($proyecto['id']);

                            $setProyecto = Proyecto::guardarAsignacionUsuarioSucursalEmpresaModulo($idAsignacionSucursal, $idAsignacionProyecto, $codproyecto, $nombreProyecto, $id, $db);

                            if ($setProyecto->status != 200) {
                                $db->rollBack();
                                $respuesta->status = 500;
                                $respuesta->message = 'Error al guardar las asignaciones, Proyectos';
                                echo json_encode($respuesta);
                                die;
                            }

                            $idAsignacionProyecto = $setProyecto->id;
                            $proyectosValidos[] = $idAsignacionProyecto;
                        }

                        Proyecto::limpiarAsignacionesPorUsuarioSucursalEmpresaModulo($idAsignacionSucursal, $id, $proyectosValidos, $db);
                    }

                    Sucursal::limpiarAsignacionesPorUsuarioEmpresaModulo($idAsignacion, $id, $sucursalesValidas, $db);
                }

                Empresa::limpiarAsignacionesPorUsuarioModulo($id, $idModulo, $empresasValidas, $db);

                $db->commit();


                $respuesta->status = 200;
                $respuesta->message = 'success';
            } catch (PDOException $e) {
                $db->rollBack();
                $respuesta->status = 500;
                $respuesta->message = $e->getMessage();
                break;
            }
            break;
        case 'solicitarRestablecimientoContrasenia':
            $usuario = new Usuario();
            $usuario->username = $input['username'];
            $usuario->email = $input['email'];

            $respuesta = $usuario->solicitarRestablecimientoContrasenia();
            break;

        default:
            $respuesta->status = 400;
            $respuesta->message = "Acción no válida";
            break;
    }
}

$httpCode = isset($respuesta->status) ? $respuesta->status : 500;
http_response_code($httpCode);
echo json_encode($respuesta);
