package com.kamco.cd.training.postgres.entity;

import com.kamco.cd.training.common.enums.ModelType;
import com.kamco.cd.training.hyperparam.dto.HyperClsParamDto;
import jakarta.persistence.*;
import jakarta.validation.constraints.NotNull;
import jakarta.validation.constraints.Size;
import java.time.ZonedDateTime;
import java.util.UUID;
import lombok.Getter;
import lombok.Setter;
import org.hibernate.annotations.ColumnDefault;
import org.hibernate.annotations.UuidGenerator;

@Getter
@Setter
@Entity
@Table(
    name = "tb_model_cls_hyper_params",
    indexes = {@Index(name = "idx_hyper_cls_params_hyper_ver", columnList = "hyper_ver")})
public class ModelHyperClsParamEntity {

  @Id
  @GeneratedValue(strategy = GenerationType.IDENTITY)
  @Column(name = "hyper_param_id", nullable = false)
  private Long id;

  @NotNull
  @UuidGenerator
  @Column(name = "uuid", nullable = false, updatable = false)
  private UUID uuid = UUID.randomUUID();

  @Size(max = 50)
  @NotNull
  @Column(name = "hyper_ver", nullable = false, length = 50)
  private String hyperVer;

  // -------------------------
  // Important (Default 반영)
  // -------------------------

  /** Choices: 256,256 or 512,512. Default: 256,256 */
  @Size(max = 15)
  @NotNull
  @Column(name = "input_size", nullable = false, length = 15)
  private String inputSize = "256,256";

  /** Range: >=1. Default: 16 (per GPU) */
  @NotNull
  @Column(name = "batch_size", nullable = false)
  private Integer batchSize = 16;

  /** Range: >=1. Default: 16 */
  @NotNull
  @Column(name = "workers", nullable = false)
  private Integer workers = 16;

  // -------------------------
  // Augmentation (Default 반영)
  // -------------------------

  @Column(name = "scale")
  private Double scale = 0.5;

  @Column(name = "translate")
  private Double translate = 0.1;

  @Column(name = "fliplr")
  private Double fliplr = 0.5;

  @Column(name = "flipud")
  private Double flipud = 0.5;

  @Column(name = "erasing")
  private Double erasing;

  @Column(name = "mixup")
  private Double mixup = 0.1;

  @Column(name = "hsv_h")
  private Double hsvH;

  @Column(name = "hsv_s")
  private Double hsvS;

  @Column(name = "hsv_v")
  private Double hsvV;

  @Column(name = "dropout")
  private Double dropout;

  @Column(name = "label_smoothing")
  private Double labelSmoothing;

  // -------------------------
  // Common
  // -------------------------

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

  @NotNull
  @ColumnDefault("false")
  @Column(name = "del_yn", nullable = false, length = 1)
  private Boolean delYn = false;

  @NotNull
  @ColumnDefault("CURRENT_TIMESTAMP")
  @Column(name = "created_dttm", nullable = false)
  private ZonedDateTime createdDttm = ZonedDateTime.now();

  @NotNull
  @Column(name = "created_uid", nullable = false)
  private Long createdUid;

  @ColumnDefault("CURRENT_TIMESTAMP")
  @Column(name = "updated_dttm")
  private ZonedDateTime updatedDttm;

  @Column(name = "updated_uid")
  private Long updatedUid;

  @ColumnDefault("CURRENT_TIMESTAMP")
  @Column(name = "last_used_dttm")
  private ZonedDateTime lastUsedDttm;

  @Column(name = "model_type")
  @Enumerated(EnumType.STRING)
  private ModelType modelType;

  @Column(name = "default_param")
  private Boolean isDefault = false;

  @Column(name = "total_use_cnt")
  private Integer totalUseCnt = 0;

  public HyperClsParamDto.Basic toDto() {
    return new HyperClsParamDto.Basic(
        this.modelType,
        this.uuid,
        this.hyperVer,
        this.createdDttm,
        this.lastUsedDttm,
        this.totalUseCnt,
        // -------------------------
        // Model
        // -------------------------
        this.inputSize,
        this.batchSize,
        this.workers,

        // -------------------------
        // Argument
        // -------------------------
        this.scale,
        this.translate,
        this.fliplr,
        this.flipud,
        this.erasing,
        this.mixup,
        this.hsvH,
        this.hsvS,
        this.hsvV,
        this.dropout,
        this.labelSmoothing,

        // -------------------------
        // Memo
        // -------------------------
        this.memo,

        // -------------------------
        // Hardware
        // -------------------------
        this.isDefault);
  }
}
