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

import com.kamco.cd.kamcoback.code.dto.CommonCodeDto;
import com.kamco.cd.kamcoback.code.dto.CommonCodeDto.Basic;
import com.kamco.cd.kamcoback.common.service.BaseCoreService;
import com.kamco.cd.kamcoback.postgres.entity.CommonCodeEntity;
import com.kamco.cd.kamcoback.postgres.repository.code.CommonCodeRepository;
import com.kamco.cd.kamcoback.zoo.dto.AnimalDto.SearchReq;
import jakarta.persistence.EntityNotFoundException;
import java.util.List;
import java.util.Optional;
import lombok.RequiredArgsConstructor;
import org.springframework.data.domain.Page;
import org.springframework.stereotype.Service;

@Service
@RequiredArgsConstructor
public class CommonCodeCoreService
    implements BaseCoreService<CommonCodeDto.Basic, Long, SearchReq> {

  private final CommonCodeRepository commonCodeRepository;

  public List<CommonCodeDto.Basic> findAll() {
    return commonCodeRepository.findByAll().stream().map(CommonCodeEntity::toDto).toList();
  }

  public CommonCodeDto.Basic save(CommonCodeDto.AddReq req) {
    if (req.getParentId() != null) {
      CommonCodeEntity parentCommonCodeEntity =
          commonCodeRepository
              .findById(req.getParentId())
              .orElseThrow(
                  () ->
                      new EntityNotFoundException(
                          "parent id 를 찾을 수 없습니다. id : " + req.getParentId()));

      CommonCodeEntity entity =
          new CommonCodeEntity(
              req.getCode(), req.getName(), req.getDescription(), req.getOrder(), req.isUsed());
      entity.addParent(parentCommonCodeEntity);
      return commonCodeRepository.save(entity).toDto();
    }

    CommonCodeEntity entity =
        new CommonCodeEntity(
            req.getCode(), req.getName(), req.getDescription(), req.getOrder(), req.isUsed());
    return commonCodeRepository.save(entity).toDto();
  }

  public CommonCodeDto.Basic update(Long id, CommonCodeDto.ModifyReq req) {
    CommonCodeEntity found =
        commonCodeRepository
            .findByCodeId(id)
            .orElseThrow(() -> new EntityNotFoundException("common code 를 찾을 수 없습니다. id : " + id));

    CommonCodeEntity entity =
        new CommonCodeEntity(
            id,
            req.getName(),
            req.getDescription(),
            req.getOrder(),
            req.isUsed(),
            found.getDeleted());

    return commonCodeRepository.save(entity).toDto();
  }

  public void updateOrder(CommonCodeDto.OrderReq req) {
    commonCodeRepository.updateOrder(req);
  }

  public List<CommonCodeDto.Basic> findByCode(String code) {
    return commonCodeRepository.findByCode(code).stream().map(CommonCodeEntity::toDto).toList();
  }

  /**
   * 공통코드 이름 조회
   *
   * @param parentCodeCd
   * @param childCodeCd
   * @return
   */
  public Optional<String> getCode(String parentCodeCd, String childCodeCd) {
    return commonCodeRepository.getCode(parentCodeCd, childCodeCd);
  }

  @Override
  public void remove(Long id) {
    CommonCodeEntity entity =
        commonCodeRepository
            .findByCodeId(id)
            .orElseThrow(() -> new EntityNotFoundException("code를 찾을 수 없습니다. id " + id));

    // 하위 코드 deleted = false 업데이트
    entity.getChildren().forEach(CommonCodeEntity::deleted);
    // id 코드 deleted = false 업데이트
    entity.deleted();
  }

  @Override
  public Basic getOneById(Long id) {
    CommonCodeEntity entity =
        commonCodeRepository
            .findByCodeId(id)
            .orElseThrow(() -> new EntityNotFoundException("code를 찾을 수 없습니다. id " + id));
    return entity.toDto();
  }

  @Override
  public Page<Basic> search(SearchReq searchReq) {
    return null;
  }
}
