package com.oguerreiro.resilient.domain;

import java.math.BigDecimal;

import org.hibernate.annotations.Cache;
import org.hibernate.annotations.CacheConcurrencyStrategy;

import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import com.oguerreiro.resilient.security.custom.ResilientSecurityResourceConfig;

import jakarta.persistence.Column;
import jakarta.persistence.Entity;
import jakarta.persistence.FetchType;
import jakarta.persistence.ManyToOne;
import jakarta.persistence.Table;
import jakarta.validation.constraints.NotNull;

/**
 * Unit
 */
@Entity
@Table(name = "unit")
@Cache(usage = CacheConcurrencyStrategy.READ_WRITE)
@ResilientSecurityResourceConfig()
public class Unit extends AbstractResilientLongIdEntity<Unit> {

  private static final long serialVersionUID = 1L;

  /**
   * Required code to use in integrations
   */
  @NotNull
  @Column(name = "code", nullable = false, unique = true)
  private String code;

  /**
   * Math symbol that is usually used as sufix for this unit. Eg. 'm3' for square metters.
   */
  @NotNull
  @Column(name = "symbol", nullable = false)
  private String symbol;

  /**
   * Math name for this unit. Eg. 'Square metters'.
   */
  @NotNull
  @Column(name = "name", nullable = false)
  private String name;

  @Column(name = "description")
  private String description;

  /**
   * The conversion rate (CR), relative to the base unit.
   * This values answers the question: When the base unit is 1 (one), what's the value of this unit measure ?
   * Ex: How many Ml (milligrams) 1Kg has? 1000
   * The formula to convert between any value unit the scale is:
   * <Value>*CR(target unit)/CR(source unit)
   */
  @NotNull
  @Column(name = "convertion_rate", precision = 21, scale = 2, nullable = false)
  private BigDecimal convertionRate;

  @ManyToOne(fetch = FetchType.LAZY)
  @JsonIgnoreProperties(value = { "units" }, allowSetters = true)
  private UnitType unitType;

  public String getCode() {
    return this.code;
  }

  public Unit code(String code) {
    this.setCode(code);
    return this;
  }

  public void setCode(String code) {
    this.code = code;
  }

  public String getSymbol() {
    return this.symbol;
  }

  public Unit symbol(String symbol) {
    this.setSymbol(symbol);
    return this;
  }

  public void setSymbol(String symbol) {
    this.symbol = symbol;
  }

  public String getName() {
    return this.name;
  }

  public Unit name(String name) {
    this.setName(name);
    return this;
  }

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

  public String getDescription() {
    return this.description;
  }

  public Unit description(String description) {
    this.setDescription(description);
    return this;
  }

  public void setDescription(String description) {
    this.description = description;
  }

  public BigDecimal getConvertionRate() {
    return this.convertionRate;
  }

  public Unit convertionRate(BigDecimal convertionRate) {
    this.setConvertionRate(convertionRate);
    return this;
  }

  public void setConvertionRate(BigDecimal convertionRate) {
    this.convertionRate = convertionRate;
  }

  public UnitType getUnitType() {
    return this.unitType;
  }

  public void setUnitType(UnitType unitType) {
    this.unitType = unitType;
  }

  public Unit unitType(UnitType unitType) {
    this.setUnitType(unitType);
    return this;
  }

//@formatter:off
  @Override
  public String toString() {
    return "Unit{" +
              "id=" + getId() +
              ", code='" + getCode() + "'" +
              ", symbol='" + getSymbol() + "'" +
              ", name='" + getName() + "'" +
              ", description='" + getDescription() + "'" +
              ", convertionRate=" + getConvertionRate() +
              ", version=" + getVersion() +
           "}";
  }
//@formatter:on
}
