<?php

require_once __DIR__ . '/../database/database.php';

class usuarioModel {

    private PDO $db;

    public function __construct() {
        $this->db = Database::getConnection();
    }

    // ACTUALIZAR USUARIO

    public function actualizarUsuario(int $id, array $data): bool {
        
        if (empty($data)) {
            return false;
        }

        $campos = [];
        $params = []; // Se utiliza para evitar inyección SQL usando parámetros nombrados de PDO

        foreach ($data as $campo => $valor) {
            $campos[] = "$campo = :$campo"; // Arma el string relacionando $campo con los parámetros nombrados (se usa en la consulta)
            $params[":$campo"] = $valor; // Arma array relacionando el parámetro nombrado con el valor (se usa en la consulta)
        }

        $params[':id'] = $id;

        $sql = "UPDATE usuarios SET " . implode(', ', $campos) . " WHERE id = :id";

        $stmt = $this->db->prepare($sql);

        return $stmt->execute($params); // Relaciona los nombrados con los valores
    }

    // OBTENER USUARIO POR ID

    public function obtenerPorId(int $id): ?array { // El ? lo uso para que pueda devolver NULL

        $sql = "SELECT id, nombre, apellido, email, telefono, usuario, rol FROM usuarios WHERE id = :id LIMIT 1";

        $stmt = $this->db->prepare($sql);

        $stmt->execute([':id' => $id]); // Le asigna al parámetro nombrado el valor de $id

        $user = $stmt->fetch(PDO::FETCH_ASSOC); // Devuelve un array asociativo

        return $user ?: null; // Verifica si el array no esta vacío y lo devuelve, sino devuelve null
    }

    // LISTAR USUARIOS

    public function listarUsuarios(): array {

        $sql = "SELECT id, nombre, apellido, email, telefono, usuario, rol FROM usuarios WHERE (activo = true) ORDER BY id ASC";

        $stmt = $this->db->prepare($sql);

        $stmt->execute();

        return $stmt->fetchAll(PDO::FETCH_ASSOC);
    }

    // CREAR USUARIO

    public function crearUsuario(array $data): bool {
        
        $sql = "INSERT INTO usuarios (nombre, apellido, email, telefono, usuario, password, rol) VALUES (:nombre, :apellido, :email, :telefono, :usuario, :password, :rol)";

        $stmt = $this->db->prepare($sql);

        return $stmt->execute([
            ':nombre' => $data['nombre'],
            ':apellido' => $data['apellido'],
            ':email' => $data['email'],
            ':telefono' => $data['telefono'],
            ':usuario' => $data['usuario'],
            ':password' => $data['password'],
            ':rol' => $data['rol']
        ]);
    }

    // VERIFICAR EXISTENCIA DE USUARIO

    public function verificarExistencia(array $datosUsuario, ?int $idExcluir = null): bool {

        $sql = "SELECT 1 FROM usuarios WHERE ((nombre = :nombre AND apellido = :apellido AND email = :email) OR (usuario = :usuario) OR (email = :email))";

        if ($idExcluir !== null) {
            $sql .= " AND id <> :id_excluir";
        }

        $sql .= " LIMIT 1";

        $stmt = $this->db->prepare($sql);

        $params = [
            ':nombre' => $datosUsuario['nombre'],
            ':apellido' => $datosUsuario['apellido'],
            ':usuario' => $datosUsuario['usuario'],
            ':email' => $datosUsuario['email']
        ];

        if ($idExcluir !== null) {
            $params[':id_excluir'] = $idExcluir;
        }

        $stmt->execute($params);

        return (bool) $stmt->fetchColumn();
    }

    // ELIMINAR USUARIO (BAJA LÓGICA)

    public function eliminarUsuario(int $id): bool {

        $sql = "UPDATE usuarios
                    SET activo = false
                WHERE (usuarios.id = :id)";

        $stmt = $this->db->prepare($sql);

        return $stmt->execute([':id' => $id]);
    }

    // OBTENER USUARIO POR MAIL

    public function obtenerPorEmail ($email): ?array {

        $sql = "SELECT id, nombre, apellido, email, telefono, usuario, rol FROM usuarios WHERE email = :email LIMIT 1";

        $stmt = $this->db->prepare($sql);

        $stmt->execute([':email' => $email]);

        $user = $stmt->fetch(PDO::FETCH_ASSOC);

        return $user ?: null;
    }

    // RESTABLECER CONTRASENIA

    public function actualizarContrasenia(int $id, string $password): bool {

        $sql = "UPDATE usuarios
                    SET password = :password
                WHERE id = :id";

        $stmt = $this->db->prepare($sql);

        return $stmt->execute([
            ':password' => $password,
            ':id' => $id
        ]);
    }
}