package com.imprimelibros.erp.users;

import java.time.LocalDateTime;

import jakarta.persistence.*;

import org.hibernate.annotations.SQLDelete;
import org.hibernate.annotations.SQLRestriction;

@Entity
@Table(name = "users_roles", uniqueConstraints = {
        @UniqueConstraint(name = "ux_users_roles_active", columnNames = { "user_id", "role_id", "deleted" })
})
@SQLDelete(sql = "UPDATE users_roles SET deleted = TRUE, deleted_at = NOW() WHERE id = ?")
@SQLRestriction("deleted = false")
public class UserRole {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;

    // FK a users
    @ManyToOne(fetch = FetchType.LAZY)
    @JoinColumn(name = "user_id", nullable = false, foreignKey = @ForeignKey(name = "FK_users_roles_user"))
    private User user;

    // FK a roles
    @ManyToOne(fetch = FetchType.LAZY)
    @JoinColumn(name = "role_id", nullable = false, foreignKey = @ForeignKey(name = "FK_users_roles_role"))
    private Role role;

    @Column(nullable = false)
    private boolean deleted = false;

    @Column(name = "deleted_at")
    private LocalDateTime deletedAt;

    protected UserRole() {
    }

    public UserRole(User user, Role role) {
        this.user = user;
        this.role = role;
    }

    /* ---- helpers ---- */
    public void softDelete() {
        this.deleted = true;
        this.deletedAt = LocalDateTime.now();
    }

    @Override
    public boolean equals(Object o) {
        if (this == o)
            return true;
        if (!(o instanceof UserRole other))
            return false;

        Long u1 = this.getUser() != null ? this.getUser().getId() : null;
        Long r1 = this.getRole() != null ? this.getRole().getId() : null;
        Long u2 = other.getUser() != null ? other.getUser().getId() : null;
        Long r2 = other.getRole() != null ? other.getRole().getId() : null;

        // igualdad por clave lógica (user_id, role_id) cuando existen
        if (u1 != null && r1 != null && u2 != null && r2 != null) {
            return u1.equals(u2) && r1.equals(r2);
        }
        // fallback: identidad por id si está asignado
        if (this.getId() != null && other.getId() != null) {
            return this.getId().equals(other.getId());
        }
        return false;
    }

    @Override
    public int hashCode() {
        Long u = this.getUser() != null ? this.getUser().getId() : null;
        Long r = this.getRole() != null ? this.getRole().getId() : null;
        if (u != null && r != null) {
            return java.util.Objects.hash(u, r);
        }
        return java.util.Objects.hash(getId());
    }

    /* ---- getters/setters ---- */
    public Long getId() {
        return id;
    }

    public User getUser() {
        return user;
    }

    public void setUser(User user) {
        this.user = user;
    }

    public Role getRole() {
        return role;
    }

    public void setRole(Role role) {
        this.role = role;
    }

    public boolean isDeleted() {
        return deleted;
    }

    public void setDeleted(boolean deleted) {
        this.deleted = deleted;
    }

    public LocalDateTime getDeletedAt() {
        return deletedAt;
    }

    public void setDeletedAt(LocalDateTime deletedAt) {
        this.deletedAt = deletedAt;
    }
}
