package com.ffii.lioner.modules.user.entity;

import java.time.LocalDate;
import java.util.Collection;

import org.hibernate.annotations.ColumnTransformer;

import jakarta.persistence.Column;
import jakarta.persistence.Entity;
import jakarta.persistence.Table;
import jakarta.persistence.Transient;
import jakarta.validation.constraints.NotBlank;
import jakarta.validation.constraints.NotNull;

import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.userdetails.UserDetails;

import com.fasterxml.jackson.annotation.JsonIgnore;
import com.ffii.core.entity.BaseEntity;

/** @author Terence */
@Entity
@Table(name = "user")
public class User extends BaseEntity<Long> implements UserDetails {

	@NotBlank
	//@Column(unique = true)
	@Column
	private String username;

	@JsonIgnore
	@Column
	private String password;

	// @NotNull
	@Column
	private Boolean locked = Boolean.FALSE;

	@NotBlank
	@Column
	private String name;

	@Column
	private LocalDate expiryDate;

	@JsonIgnore
	@Transient
	private Collection<GrantedAuthority> authorities;

	@Column
	private String locale;

	@Column
	private String fullname;

	@Column
	private String firstname;

	@Column
	private String lastname;

	@Column
	private String department;

	@Column
	private String title;

	@Column
	private String email;

	@Column
	private String phone1;

	@Column
	private String phone2;

	@Column
	private String remarks;

	/**
	 * The Base32-encoded secret key used for TOTP (Time-based One-Time Password).
	 * Generated once during 2FA setup and stored securely.
	 * NULL = 2FA not configured
	 */
	@Column
	private String twoFactorSecret;

	/**
	 * Indicates whether 2FA is enabled for this user.
	 * false = not enabled (default)
	 * true  = enabled and required during login
	 */
	@Column
	private boolean twoFactorEnabled = false;


	public boolean isLocked() {
		return this.locked == null ? false : this.locked;
	}

	// getter & setter

	public void setUsername(String username) {
		this.username = username;
	}

	public void setPassword(String password) {
		this.password = password;
	}

	public Boolean getLocked() {
		return locked;
	}

	public void setLocked(Boolean locked) {
		this.locked = locked;
	}

	public String getName() {
		return name;
	}

	public void setName(String name) {
		this.name = name;
	}

	public LocalDate getExpiryDate() {
		return expiryDate;
	}

	public void setExpiryDate(LocalDate expiryDate) {
		this.expiryDate = expiryDate;
	}

	public void setAuthorities(Collection<GrantedAuthority> authorities) {
		this.authorities = authorities;
	}

	public String getLocale() {
		return locale;
	}

	public void setLocale(String locale) {
		this.locale = locale;
	}

	public String getFullname() {
		return fullname;
	}

	public void setFullname(String fullname) {
		this.fullname = fullname;
	}

	public String getFirstname() {
		return firstname;
	}

	public void setFirstname(String firstname) {
		this.firstname = firstname;
	}

	public String getLastname() {
		return lastname;
	}

	public void setLastname(String lastname) {
		this.lastname = lastname;
	}

	public String getTitle() {
		return title;
	}

	public void setTitle(String title) {
		this.title = title;
	}

	public String getEmail() {
		return email;
	}

	public void setEmail(String email) {
		this.email = email;
	}

	public String getPhone1() {
		return phone1;
	}

	public void setPhone1(String phone1) {
		this.phone1 = phone1;
	}

	public String getPhone2() {
		return phone2;
	}

	public void setPhone2(String phone2) {
		this.phone2 = phone2;
	}

	public String getRemarks() {
		return remarks;
	}

	public void setRemarks(String remarks) {
		this.remarks = remarks;
	}

	// override

	@Override
	public Collection<? extends GrantedAuthority> getAuthorities() {
		return this.authorities;
	}

	@Override
	public String getPassword() {
		return this.password;
	}

	@Override
	public String getUsername() {
		return this.username;
	}

	@Override
	public boolean isAccountNonExpired() {
		return this.getExpiryDate() == null || this.getExpiryDate().isAfter(LocalDate.now());
	}

	@Override
	public boolean isAccountNonLocked() {
		return !this.isLocked();
	}

	@JsonIgnore
	@Override
	public boolean isCredentialsNonExpired() {
		return true;
	}

	@JsonIgnore
	@Override
	public boolean isEnabled() {
		return true;
	}

	public String getDepartment() {
		return department;
	}

	public void setDepartment(String department) {
		this.department = department;
	}

    public String getTwoFactorSecret() {
        return twoFactorSecret;
    }

    public void setTwoFactorSecret(String twoFactorSecret) {
        this.twoFactorSecret = twoFactorSecret;
    }

    public boolean isTwoFactorEnabled() {
        return twoFactorEnabled;
    }

    public void setTwoFactorEnabled(boolean twoFactorEnabled) {
        this.twoFactorEnabled = twoFactorEnabled;
    }

}
