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.*;
import jakarta.validation.constraints.NotNull;
import jakarta.validation.constraints.Size;
import java.time.ZonedDateTime;
import java.util.ArrayList;
import java.util.List;
import lombok.AccessLevel;
import lombok.Getter;
import lombok.NoArgsConstructor;
import org.hibernate.annotations.Where;

@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;

  @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)
  @Where(clause = "deleted = false or deleted is null")
  private List<CommonCodeEntity> children = new ArrayList<>();

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

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

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

  @Column(name = "deleted_dttm")
  private ZonedDateTime deletedDttm;

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

  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(),
        this.props1,
        this.props2,
        this.props3,
        this.deletedDttm);
  }

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

  public boolean isDeleted() {
    return deleted;
  }

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

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

  public void update(
      String name, String description, boolean used, String props1, String props2, String props3) {
    this.name = name;
    this.description = description;
    this.used = used;
    this.props1 = props1;
    this.props2 = props2;
    this.props3 = props3;
  }
}
