package com.kamco.cd.training.hyperparam.dto;

import com.kamco.cd.training.common.enums.ModelType;
import com.kamco.cd.training.common.utils.enums.CodeExpose;
import com.kamco.cd.training.common.utils.enums.EnumType;
import com.kamco.cd.training.common.utils.interfaces.JsonFormatDttm;
import io.swagger.v3.oas.annotations.media.Schema;
import java.time.LocalDate;
import java.time.ZonedDateTime;
import java.util.UUID;
import lombok.AllArgsConstructor;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Sort;

public class HyperParamDto {

  @Schema(name = "Basic", description = "하이퍼파라미터 조회")
  @Getter
  @Setter
  @NoArgsConstructor
  @AllArgsConstructor
  public static class Basic {

    private ModelType model; // 20250212 modeltype추가
    private UUID uuid;
    private String hyperVer;
    @JsonFormatDttm private ZonedDateTime createdDttm;
    @JsonFormatDttm private ZonedDateTime lastUsedDttm;
    private Integer totalUseCnt;

    // -------------------------
    // Important
    // -------------------------
    private String backbone;
    private String inputSize;
    private String cropSize;
    private Integer batchSize;

    // -------------------------
    // Data
    // -------------------------
    private Integer trainNumWorkers;
    private Integer valNumWorkers;
    private Integer testNumWorkers;
    private Boolean trainShuffle;
    private Boolean trainPersistent;
    private Boolean valPersistent;

    // -------------------------
    // Model Architecture
    // -------------------------
    private Double dropPathRate;
    private Integer frozenStages;
    private String neckPolicy;
    private String decoderChannels;
    private String classWeight;

    // -------------------------
    // Loss & Optimization
    // -------------------------
    private Double learningRate;
    private Double weightDecay;
    private Double layerDecayRate;
    private Boolean ddpFindUnusedParams;
    private Integer ignoreIndex;
    private Integer numLayers;

    // -------------------------
    // Evaluation
    // -------------------------
    private String metrics;
    private String saveBest;
    private String saveBestRule;
    private Integer valInterval;
    private Integer logInterval;
    private Integer visInterval;

    // -------------------------
    // Augmentation
    // -------------------------
    private Double rotProb;
    private String rotDegree;
    private Double flipProb;
    private Double exchangeProb;
    private Integer brightnessDelta;
    private String contrastRange;
    private String saturationRange;
    private Integer hueDelta;

    // -------------------------
    // Memo
    // -------------------------
    private String memo;

    // -------------------------
    // Hardware
    // -------------------------
    private Integer gpuCnt;
    private String gpuIds;
    private Integer masterPort;

    private Boolean isDefault;
  }

  @Getter
  @Setter
  @NoArgsConstructor
  @AllArgsConstructor
  public static class List {
    private UUID uuid;
    private ModelType model;
    private String hyperVer;
    @JsonFormatDttm private ZonedDateTime createDttm;
    @JsonFormatDttm private ZonedDateTime lastUsedDttm;
    private String memo;
    private Integer totalUseCnt;
  }

  @Getter
  @Setter
  @NoArgsConstructor
  @AllArgsConstructor
  public static class SearchReq {
    private String type;
    private LocalDate startDate;
    private LocalDate endDate;
    private String hyperVer;

    // 페이징 파라미터
    private int page = 0;
    private int size = 20;
    private String sort;

    public Pageable toPageable() {
      if (sort != null && !sort.isEmpty()) {
        String[] sortParams = sort.split(",");
        String property = sortParams[0];
        Sort.Direction direction =
            sortParams.length > 1 ? Sort.Direction.fromString(sortParams[1]) : Sort.Direction.ASC;
        return PageRequest.of(page, size, Sort.by(direction, property));
      }
      return PageRequest.of(page, size);
    }
  }

  @CodeExpose
  @Getter
  @AllArgsConstructor
  public enum HyperType implements EnumType {
    CREATE_DATE("생성일"),
    LAST_USED_DATE("최근 사용일");

    private final String desc;

    @Override
    public String getId() {
      return name();
    }

    @Override
    public String getText() {
      return desc;
    }
  }
}
