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

import com.kamco.cd.kamcoback.code.dto.CommonCodeDto;
import com.kamco.cd.kamcoback.postgres.CommonDateEntity;
import jakarta.persistence.CascadeType;
import jakarta.persistence.Column;
import jakarta.persistence.Entity;
import jakarta.persistence.FetchType;
import jakarta.persistence.GeneratedValue;
import jakarta.persistence.GenerationType;
import jakarta.persistence.Id;
import jakarta.persistence.JoinColumn;
import jakarta.persistence.ManyToOne;
import jakarta.persistence.OneToMany;
import jakarta.persistence.Table;
import jakarta.validation.constraints.NotNull;
import jakarta.validation.constraints.Size;
import java.util.ArrayList;
import java.util.List;
import lombok.AccessLevel;
import lombok.Getter;
import lombok.NoArgsConstructor;

@Entity
@Getter
@NoArgsConstructor(access = AccessLevel.PROTECTED)
@Table(name = "tb_cm_cd")
public class CommonCodeEntity extends CommonDateEntity {

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

  @Size(max = 255)
  @Column(name = "code_cd", updatable = false)
  private String code;

  @Size(max = 255)
  @Column(name = "cd_ct")
  private String description;

  @Size(max = 255)
  @Column(name = "cd_nm")
  private String name;

  @Column(name = "cd_odr")
  private Integer order;

  @Column(name = "used")
  private Boolean used;

  @Column(name = "misc_cd")
  private String miscCd;

  @NotNull
  @Column(name = "deleted", nullable = false)
  private Boolean deleted = false;

  @ManyToOne(fetch = FetchType.LAZY)
  @JoinColumn(name = "parent_id", updatable = false)
  private CommonCodeEntity parent;

  @OneToMany(mappedBy = "parent", fetch = FetchType.LAZY, cascade = CascadeType.ALL)
  private List<CommonCodeEntity> children = new ArrayList<>();

  public CommonCodeEntity(
      String code, String name, String description, Integer order, Boolean used) {
    this.code = code;
    this.name = name;
    this.description = description;
    this.order = order;
    this.used = used;
  }

  public CommonCodeEntity(
      Long id, String name, String description, Integer order, Boolean used, Boolean deleted) {
    this.id = id;
    this.name = name;
    this.description = description;
    this.order = order;
    this.used = used;
    this.deleted = deleted;
  }

  public CommonCodeDto.Basic toDto() {
    return new CommonCodeDto.Basic(
        this.id,
        this.code,
        this.description,
        this.name,
        this.order,
        this.used,
        this.deleted,
        this.children.stream().map(CommonCodeEntity::toDto).toList(),
        super.getCreatedDate(),
        super.getModifiedDate());
  }

  public void addParent(CommonCodeEntity parent) {
    this.parent = parent;
  }

  public boolean isDeleted() {
    return deleted;
  }

  public void deleted() {
    this.deleted = true;
  }

  public void updateOrder(int order) {
    this.order = order;
  }
}
