package com.ffii.core.entity;

import java.io.Serializable;
import java.time.LocalDateTime;
import java.util.Optional;

import org.springframework.security.core.context.SecurityContextHolder;

import com.ffii.fhsmsc.modules.user.entity.User;

import jakarta.persistence.Column;
import jakarta.persistence.MappedSuperclass;
import jakarta.persistence.PrePersist;
import jakarta.persistence.PreUpdate;
import jakarta.persistence.Version;
import jakarta.validation.constraints.NotNull;

/** @author Terence */
@MappedSuperclass
public abstract class BaseEntity<ID extends Serializable> extends IdEntity<ID> {

	@NotNull
	@Version
	@Column
	private Integer version;

	@NotNull
	@Column(updatable = false)
	private LocalDateTime created;

	@Column(updatable = false)
	private Long createdBy;

	@NotNull
	@Column
	private LocalDateTime modified;

	@Column
	private Long modifiedBy;

	@NotNull
	@Column
	private Boolean deleted;

	@PrePersist
	public void autoSetCreated() {
		this.setCreated(LocalDateTime.now());
		this.setModified(LocalDateTime.now());
		this.setDeleted(Boolean.FALSE);

		Optional.ofNullable(SecurityContextHolder.getContext().getAuthentication())
				.ifPresentOrElse(
						authentication -> {
							if ("anonymousUser".equals(authentication.getPrincipal())){
								this.setCreatedBy(null);
								this.setModifiedBy(null);
							} else{
								Long userId = ((User)authentication.getPrincipal()).getId();
								this.setCreatedBy(userId);
								this.setModifiedBy(userId);
							}
						},
						() -> {
							this.setCreatedBy(null);
							this.setModifiedBy(null);
						});
	}

	@PreUpdate
	public void autoSetModified() {
		this.setModified(LocalDateTime.now());
		Optional.ofNullable(SecurityContextHolder.getContext().getAuthentication()).ifPresentOrElse(
				authentication -> this.setModifiedBy(((User)authentication.getPrincipal()).getId()),
				() -> this.setModifiedBy(null));
	}

	public Integer getVersion() {
		return this.version;
	}

	public void setVersion(Integer version) {
		this.version = version;
	}

	public LocalDateTime getCreated() {
		return this.created;
	}

	public void setCreated(LocalDateTime created) {
		this.created = created;
	}

	public Long getCreatedBy() {
		return this.createdBy;
	}

	public void setCreatedBy(Long createdBy) {
		this.createdBy = createdBy;
	}

	public LocalDateTime getModified() {
		return this.modified;
	}

	public void setModified(LocalDateTime modified) {
		this.modified = modified;
	}

	public Long getModifiedBy() {
		return this.modifiedBy;
	}

	public void setModifiedBy(Long modifiedBy) {
		this.modifiedBy = modifiedBy;
	}

	public Boolean isDeleted() {
		return this.deleted;
	}

	public Boolean getDeleted() {
		return this.deleted;
	}

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

}