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

import com.kamco.cd.kamcoback.common.enums.CommonUseStatus;
import com.kamco.cd.kamcoback.config.api.ApiResponseDto.ApiResponseCode;
import com.kamco.cd.kamcoback.config.api.ApiResponseDto.ResponseObj;
import com.kamco.cd.kamcoback.inference.dto.InferenceResultDto.MapSheet;
import com.kamco.cd.kamcoback.postgres.entity.MapInkx50kEntity;
import com.kamco.cd.kamcoback.postgres.entity.MapInkx5kEntity;
import com.kamco.cd.kamcoback.postgres.repository.scene.MapInkx50kRepository;
import com.kamco.cd.kamcoback.postgres.repository.scene.MapInkx5kRepository;
import com.kamco.cd.kamcoback.scene.dto.MapInkxMngDto;
import com.kamco.cd.kamcoback.scene.dto.MapInkxMngDto.UseInferReq;
import jakarta.persistence.EntityNotFoundException;
import jakarta.validation.Valid;
import jakarta.validation.constraints.NotNull;
import java.util.Optional;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.locationtech.jts.geom.Polygon;
import org.springframework.data.domain.Page;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

@Slf4j
@Service
@RequiredArgsConstructor
public class MapInkxMngCoreService {

  private final MapInkx5kRepository mapInkx5kRepository;
  private final MapInkx50kRepository mapInkx50kRepository;

  // 목록
  public Page<MapInkxMngDto.MapList> findMapInkxMngList(
      MapInkxMngDto.searchReq searchReq, CommonUseStatus useInference, String searchVal) {
    return mapInkx5kRepository.findMapInkxMngList(searchReq, useInference, searchVal);
  }

  // 저장
  public ResponseObj saveMapInkx5k(MapInkxMngDto.AddMapReq req, Polygon map_polygon) {

    Long existsCount = mapInkx5kRepository.findByMapidCdNoExists(req.getMapidcdNo());

    if (existsCount > 0) {
      return new ResponseObj(ApiResponseCode.DUPLICATE_DATA, "이미 등록된 도엽코드 입니다.");
    }

    MapInkx50kEntity mapInkx50k = mapInkx50kRepository.findByMapidCdParentNo(req.getMapidcdNo());
    if (mapInkx50k == null) {
      return new ResponseObj(ApiResponseCode.NOT_FOUND_DATA, "1:50,000 도엽의 정보가 없습니다. 관리자에게 문의하세요.");
    }

    MapInkx5kEntity entity =
        new MapInkx5kEntity(req.getMapidcdNo(), req.getMapidNm(), map_polygon, mapInkx50k);

    mapInkx5kRepository.save(entity);

    return new ResponseObj(ApiResponseCode.OK, "");
  }

  // 도엽의 사용여부를 변경한다.
  public ResponseObj updateUseInference(@Valid UseInferReq useInferReq) {
    Optional<MapInkx5kEntity> entity =
        Optional.ofNullable(
            mapInkx5kRepository
                .findByMapidCdNoInfo(useInferReq.getMapidcdNo())
                .orElseThrow(() -> new EntityNotFoundException("도엽정보를 찾을 수 없습니다.")));

    entity.get().updateUseInference(useInferReq.getUseInference());
    return new ResponseObj(ApiResponseCode.OK, "");
  }

  /**
   * Updates the inference usage status of a given map sheet (도엽) based on the provided scene ID and
   * usage status. 도엽의 사용여부를 변경한다.
   *
   * @param sceneId5k the unique identifier for the map sheet whose usage status is being updated
   * @param useStatus the new usage status to be set for the specified map sheet
   * @return a ResponseObj indicating the outcome of the operation, including a response code and
   *     message
   * @throws EntityNotFoundException if no map sheet is found for the provided scene ID
   */
  @Transactional
  public MapSheet updateUseInference(
      @NotNull String sceneId5k, @NotNull CommonUseStatus useStatus) {

    log.debug("[updateUseInference]CHANGE_SCENE STATUS start: {}", sceneId5k);

    // 5k도엽 정보를 가져온다.
    MapInkx5kEntity getScene5k =
        mapInkx5kRepository
            .findByMapidCdNoInfo(sceneId5k)
            .orElseThrow(() -> new EntityNotFoundException("도엽정보를 찾을 수 없습니다."));

    log.debug(
        "[updateUseInference]CHANGE_SCENE STATUS: {} |BEFORE {} |AFTER {}",
        sceneId5k,
        getScene5k.getUseInference(),
        useStatus);
    // 상태를 업데이트한다.
    getScene5k.updateUseInference(useStatus);

    return getScene5k.toEntity();
  }
}
