<?php
!class_exists('Apartado') && require_once __DIR__ . '/apartadoModel.php';
class Modulo
{
    public $id;
    public $titulo;
    public $contenedor;
    public $descripcion;
    public $mantenimiento;
    public $apartados = [];
    public $fechaRegistro;

    function __construct()
    {
        !empty($this->fechaRegistro) && $this->fechaRegistro = date("d-m-Y h:i a", strtotime($this->fechaRegistro));
    }

    public static function obtenerTodos(): object
    {
        $db = obtenerConexion();

        $query = "SELECT * FROM sistema.view_modulos WHERE estado = 1 ORDER BY titulo ASC;";
        $stmt = $db->prepare($query, [PDO::ATTR_CURSOR => PDO::CURSOR_SCROLL]);

        try {
            $stmt->execute();

            $data = $stmt->fetchAll(PDO::FETCH_CLASS, __CLASS__);

            return (object)[
                'status' => 200,
                'data' => $data
            ];
        } catch (PDOException $e) {
            return (object)[
                'status' => 500,
                'message' => $e->getMessage()
            ];
        }
    }

    public function guardar($usuario): object
    {
        $db = obtenerConexion();

        $respuesta = null;
        $id = null;

        $query = 'EXEC sistema.sp_guardarModulo :id,:titulo,:contenedor,:descripcion,:mantenimiento,:usuario,:respuesta,:idModulo;';
        $stmt = $db->prepare($query, [PDO::ATTR_CURSOR => PDO::CURSOR_SCROLL]);
        $stmt->bindParam(':id', $this->id, PDO::PARAM_INT);
        $stmt->bindParam(':titulo', $this->titulo, PDO::PARAM_STR);
        $stmt->bindParam(':contenedor', $this->contenedor, PDO::PARAM_STR);
        $stmt->bindParam(':descripcion', $this->descripcion, PDO::PARAM_STR);
        $stmt->bindParam(':mantenimiento', $this->mantenimiento, PDO::PARAM_INT);
        $stmt->bindParam(':respuesta', $respuesta, PDO::PARAM_STR | PDO::PARAM_INPUT_OUTPUT, 4000);
        $stmt->bindParam(':usuario', $usuario, PDO::PARAM_INT);
        $stmt->bindParam(':idModulo', $id, PDO::PARAM_INT | PDO::PARAM_INPUT_OUTPUT, 100);

        try {
            $db->beginTransaction();

            $stmt->execute();

            if ($respuesta == 'success') {
                $this->id = $id;

                $idsApartados = [];

                foreach ($this->apartados as $apartadoN1) {
                    $nivel = 1;
                    $nuevoApartadoN1 = new Apartado();
                    $nuevoApartadoN1->idModulo = $this->id;
                    $nuevoApartadoN1->id = $apartadoN1['id'];
                    $nuevoApartadoN1->icono = $apartadoN1['icono'];
                    $nuevoApartadoN1->titulo = $apartadoN1['titulo'];
                    $nuevoApartadoN1->descripcion = $apartadoN1['descripcion'];
                    $nuevoApartadoN1->nivel = isset($apartadoN1['nivel']) ? $apartadoN1['nivel'] : $nivel;
                    $nuevoApartadoN1->tipo = $apartadoN1['tipo'];
                    $nuevoApartadoN1->nombreArchivo = $apartadoN1['nombreArchivo'];
                    $nuevoApartadoN1->mantenimiento = $apartadoN1['mantenimiento'];
                    $nuevoApartadoN1->superior = null;

                    $respuestaN1 = $nuevoApartadoN1->guardar($db, $usuario);

                    if ($respuestaN1->status != 200 || ($respuestaN1->status == 200 && $respuestaN1->message != 'success')) {
                        $db->rollBack();
                        return (object)[
                            'status' => 500,
                            'message' => 'Ocurrió un error al guardar el apartado ' . $nuevoApartadoN1->titulo . ' nivel 1'
                        ];
                        break;
                    }

                    $idsApartados[] = $respuestaN1->id;
                    $nuevoApartadoN1->id = $respuestaN1->id;

                    foreach ($apartadoN1['subApartados'] as $apartadoN2) {
                        $nivel = 2;
                        $nuevoApartadoN2 = new Apartado();
                        $nuevoApartadoN2->idModulo = $this->id;
                        $nuevoApartadoN2->id = $apartadoN2['id'];
                        $nuevoApartadoN2->icono = $apartadoN2['icono'];
                        $nuevoApartadoN2->titulo = $apartadoN2['titulo'];
                        $nuevoApartadoN2->descripcion = $apartadoN2['descripcion'];
                        $nuevoApartadoN2->nivel = isset($apartadoN2['nivel']) ? $apartadoN2['nivel'] : $nivel;
                        $nuevoApartadoN2->tipo = $apartadoN2['tipo'];
                        $nuevoApartadoN2->nombreArchivo = $apartadoN2['nombreArchivo'];
                        $nuevoApartadoN2->mantenimiento = $apartadoN2['mantenimiento'];
                        $nuevoApartadoN2->superior = $nuevoApartadoN1->id;

                        $respuestaN2 = $nuevoApartadoN2->guardar($db, $usuario);

                        if ($respuestaN2->status != 200 || ($respuestaN2->status == 200 && $respuestaN2->message != 'success')) {
                            $db->rollBack();
                            return (object)[
                                'status' => 500,
                                'message' => 'Ocurrió un error al guardar el apartado ' . $nuevoApartadoN2->titulo . ' nivel 2'
                            ];
                            break;
                        }

                        $idsApartados[] = $respuestaN2->id;
                        $nuevoApartadoN2->id = $respuestaN2->id;

                        foreach ($apartadoN2['subApartados'] as $apartadoN3) {
                            $nivel = 3;
                            $nuevoApartadoN3 = new Apartado();
                            $nuevoApartadoN3->idModulo = $this->id;
                            $nuevoApartadoN3->id = $apartadoN3['id'];
                            $nuevoApartadoN3->icono = $apartadoN3['icono'];
                            $nuevoApartadoN3->titulo = $apartadoN3['titulo'];
                            $nuevoApartadoN3->descripcion = $apartadoN3['descripcion'];
                            $nuevoApartadoN3->nivel = isset($apartadoN3['nivel']) ? $apartadoN3['nivel'] : $nivel;
                            $nuevoApartadoN3->tipo = $apartadoN3['tipo'];
                            $nuevoApartadoN3->nombreArchivo = $apartadoN3['nombreArchivo'];
                            $nuevoApartadoN3->mantenimiento = $apartadoN3['mantenimiento'];
                            $nuevoApartadoN3->superior = $nuevoApartadoN2->id;

                            $respuestaN3 = $nuevoApartadoN3->guardar($db, $usuario);

                            if ($respuestaN3->status != 200 || ($respuestaN3->status == 200 && $respuestaN3->message != 'success')) {
                                $db->rollBack();
                                return (object)[
                                    'status' => 500,
                                    'message' => 'Ocurrió un error al guardar el apartado ' . $nuevoApartadoN3->titulo . ' nivel 3'
                                ];
                                break;
                            }

                            $idsApartados[] = $respuestaN3->id;
                            $nuevoApartadoN3->id = $respuestaN3->id;

                            foreach ($apartadoN3['subApartados'] as $apartadoN4) {
                                $nivel = 4;
                                $nuevoApartadoN4 = new Apartado();
                                $nuevoApartadoN4->idModulo = $this->id;
                                $nuevoApartadoN4->id = $apartadoN4['id'];
                                $nuevoApartadoN4->icono = $apartadoN4['icono'];
                                $nuevoApartadoN4->titulo = $apartadoN4['titulo'];
                                $nuevoApartadoN4->descripcion = $apartadoN4['descripcion'];
                                $nuevoApartadoN4->nivel = isset($apartadoN4['nivel']) ? $apartadoN4['nivel'] : $nivel;
                                $nuevoApartadoN4->tipo = $apartadoN4['tipo'];
                                $nuevoApartadoN4->nombreArchivo = $apartadoN4['nombreArchivo'];
                                $nuevoApartadoN4->mantenimiento = $apartadoN4['mantenimiento'];
                                $nuevoApartadoN4->superior = $nuevoApartadoN3->id;

                                $respuestaN4 = $nuevoApartadoN4->guardar($db, $usuario);

                                if ($respuestaN4->status != 200 || ($respuestaN4->status == 200 && $respuestaN4->message != 'success')) {
                                    $db->rollBack();
                                    return (object)[
                                        'status' => 500,
                                        'message' => 'Ocurrió un error al guardar el apartado ' . $nuevoApartadoN4->titulo . ' nivel 4'
                                    ];
                                    break;
                                }

                                $idsApartados[] = $respuestaN4->id;
                            }
                        }
                    }
                }

                $limpiezaApartados = Apartado::limpiarPorModulo($db, $this->id, $idsApartados);

                if ($limpiezaApartados->status != 200 || ($limpiezaApartados->status == 200 && $limpiezaApartados->message != 'success')) {
                    $db->rollBack();
                    return (object)[
                        'status' => 500,
                        'message' => 'Ocurrió un error al limpiar los apartados'
                    ];
                }
            }

            $db->commit();
            return (object)[
                'status' => 200,
                'message' => $respuesta,
                'data' => (object)['id' => $id, 'fechaRegistro' => date("d-m-Y h:i a")]
            ];
        } catch (PDOException $e) {
            $db->rollBack();
            return (object)[
                'status' => 500,
                'message' => $e->getMessage()
            ];
        }
    }

    public static function obtenerTodosParaCombo(): object
    {
        $solicitud = self::obtenerTodos();

        $modulos = $solicitud->status == 200 ? $solicitud->data : [];

        $modulos = array_map(function ($item) {
            return (object)[
                'id' => $item->id,
                'titulo' => $item->titulo,
            ];
        }, $modulos);

        return (object)[
            'status' => 200,
            'data' => array_values($modulos)
        ];
    }

    public function configurarMantenimiento($usuario)
    {
        $db = obtenerConexion();

        $respuesta = null;

        $query = "EXEC sistema.sp_configurarMantenimientoModulo :id,:mantenimiento,:respuesta;";
        $stmt = $db->prepare($query, [PDO::ATTR_CURSOR => PDO::CURSOR_SCROLL]);
        $stmt->bindParam(':id', $this->id, PDO::PARAM_INT);
        $stmt->bindParam(':mantenimiento', $this->mantenimiento, PDO::PARAM_INT);
        $stmt->bindParam(':respuesta', $respuesta, PDO::PARAM_STR, 4000);

        try {
            $stmt->execute();

            return (object)[
                'status' => 200,
                'message' => $respuesta
            ];
        } catch (PDOException $e) {
            return (object)[
                'status' => 500,
                'message' => $e->getMessage()
            ];
        }
    }

    public function eliminar($usuario): object
    {
        $db = obtenerConexion();

        $respuesta = null;

        $query = "EXEC sistema.sp_eliminarModulo :id,:respuesta;";
        $stmt = $db->prepare($query, [PDO::ATTR_CURSOR => PDO::CURSOR_SCROLL]);
        $stmt->bindParam(':id', $this->id, PDO::PARAM_INT);
        $stmt->bindParam(':respuesta', $respuesta, PDO::PARAM_STR, 4000);

        try {
            $stmt->execute();

            return (object)[
                'status' => 200,
                'message' => $respuesta
            ];
        } catch (PDOException $e) {
            return (object)[
                'status' => 500,
                'message' => $e->getMessage()
            ];
        }
    }

    public static function obtenerPorApartado(int $apartado): object
    {
        $db = obtenerConexion();

        $query = "SELECT TOP(1) modulos.id,
            modulos.titulo nombreModulo,
            modulos.contenedor
        FROM sistema.det_apartados apartados
        inner join sistema.datos_modulos modulos on apartados.idModulo = modulos.id WHERE apartados.id = :idApartado";
        $stmt = $db->prepare($query, [PDO::ATTR_CURSOR => PDO::CURSOR_SCROLL]);
        $stmt->bindParam(':idApartado', $apartado, PDO::PARAM_INT);

        try {
            $stmt->execute();
            $data = $stmt->fetch(PDO::FETCH_OBJ);

            return (object)['status' => 200, 'message' => 'success', 'data' => $data];
        } catch (PDOException $e) {
            return (object)['status' => 500, 'message' => $e->getMessage()];
        }
    }
}
