package es.tatvil.taiageweb.modelo;

import jakarta.persistence.*;
import java.util.HashSet;
import java.util.Set;

/**
 * Entidad JPA que representa a un usuario registrado en la plataforma.
 *
 * <p>Los usuarios se almacenan en la tabla {@code usuarios}. Sus roles se guardan
 * en la tabla auxiliar {@code usuario_roles} mediante una relación
 * {@code @ElementCollection}.</p>
 *
 * <h3>Roles disponibles</h3>
 * <ul>
 *   <li>{@code ROLE_USER} – usuario registrado, sin acceso al curso.</li>
 *   <li>{@code ROLE_PAGADO} – ha completado el pago; accede al temario completo.</li>
 *   <li>{@code ROLE_ADMIN} – administrador; acceso total al panel de gestión.</li>
 * </ul>
 */
@Entity
@Table(name = "usuarios")
public class Usuario {

    /** Identificador autogenerado (clave primaria). */
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;

    /** Dirección de correo electrónico; única e indexada, se usa como nombre de usuario. */
    @Column(unique = true, nullable = false, length = 100)
    private String email;

    /** Contraseña cifrada con BCrypt. Nunca se almacena en texto plano. */
    @Column(nullable = false, length = 255)
    private String password;

    /**
     * Indica si la cuenta está activa.
     * <p>Las cuentas nuevas arrancan con {@code false}; el administrador o un pago
     * completado la activan automáticamente.</p>
     */
    @Column(nullable = false)
    private boolean habilitado = false;

    /**
     * Conjunto de roles asignados al usuario.
     * Los valores posibles son {@code ROLE_USER}, {@code ROLE_PAGADO} y {@code ROLE_ADMIN}.
     */
    @ElementCollection(fetch = FetchType.EAGER)
    @CollectionTable(name = "usuario_roles", joinColumns = @JoinColumn(name = "usuario_id"))
    @Column(name = "rol")
    private Set<String> roles = new HashSet<>();

    /** Constructor sin argumentos requerido por JPA. */
    public Usuario() {}

    // ── Getters / Setters ────────────────────────────────────

    /**
     * Devuelve el identificador único del usuario.
     *
     * @return id generado por la base de datos
     */
    public Long getId() { return id; }

    /**
     * Devuelve el email del usuario.
     *
     * @return dirección de correo tal como fue registrada
     */
    public String getEmail() { return email; }

    /**
     * Establece el email del usuario.
     *
     * @param email dirección de correo electrónico
     */
    public void setEmail(String email) { this.email = email; }

    /**
     * Devuelve la contraseña cifrada.
     *
     * @return hash BCrypt de la contraseña
     */
    public String getPassword() { return password; }

    /**
     * Establece la contraseña (debe ser el hash BCrypt, nunca texto plano).
     *
     * @param password hash BCrypt
     */
    public void setPassword(String password) { this.password = password; }

    /**
     * Indica si la cuenta está habilitada para iniciar sesión.
     *
     * @return {@code true} si la cuenta está activa
     */
    public boolean isHabilitado() { return habilitado; }

    /**
     * Activa o desactiva la cuenta.
     *
     * @param habilitado {@code true} para habilitar la cuenta
     */
    public void setHabilitado(boolean habilitado) { this.habilitado = habilitado; }

    /**
     * Devuelve el conjunto de roles asignados al usuario.
     *
     * @return conjunto mutable de roles
     */
    public Set<String> getRoles() { return roles; }

    /**
     * Reemplaza el conjunto de roles del usuario.
     *
     * @param roles nuevo conjunto de roles
     */
    public void setRoles(Set<String> roles) { this.roles = roles; }

    // ── Helpers para la vista ────────────────────────────────

    /**
     * Indica si el usuario tiene acceso al curso (rol {@code ROLE_PAGADO}).
     *
     * @return {@code true} si el rol está presente
     */
    public boolean isPagado() { return roles.contains("ROLE_PAGADO"); }

    /**
     * Indica si el usuario es administrador (rol {@code ROLE_ADMIN}).
     *
     * @return {@code true} si el rol está presente
     */
    public boolean isAdmin()  { return roles.contains("ROLE_ADMIN"); }
}
