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

import com.kamco.cd.kamcoback.inference.dto.InferenceResultDto;
import com.kamco.cd.kamcoback.inference.dto.InferenceResultDto.Dashboard;
import com.kamco.cd.kamcoback.inference.dto.InferenceResultDto.MapSheet;
import com.kamco.cd.kamcoback.postgres.entity.MapInkx5kEntity;
import com.kamco.cd.kamcoback.postgres.entity.MapSheetAnalDataEntity;
import com.kamco.cd.kamcoback.postgres.entity.MapSheetAnalDataGeomEntity;
import com.kamco.cd.kamcoback.postgres.repository.Inference.InferenceResultRepository;
import com.kamco.cd.kamcoback.postgres.repository.scene.MapInkx5kRepository;
import jakarta.persistence.EntityNotFoundException;
import jakarta.validation.constraints.NotNull;
import java.util.List;
import lombok.RequiredArgsConstructor;
import org.springframework.data.domain.Page;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

@Service
@RequiredArgsConstructor
public class InferenceResultCoreService {

  private final InferenceResultRepository inferenceResultRepository;
  private final MapInkx5kRepository mapInkx5kRepository;

  /**
   * 추론관리 > 분석결과 목록 조회
   *
   * @param searchReq
   * @return
   */
  public Page<InferenceResultDto.AnalResList> getInferenceResultList(
      InferenceResultDto.SearchReq searchReq) {
    return inferenceResultRepository.getInferenceResultList(searchReq);
  }

  /**
   * 분석결과 요약정보
   *
   * @param id
   * @return
   */
  public InferenceResultDto.AnalResSummary getInferenceResultSummary(Long id) {
    InferenceResultDto.AnalResSummary summary =
        inferenceResultRepository
            .getInferenceResultSummary(id)
            .orElseThrow(() -> new EntityNotFoundException("요약정보를 찾을 수 없습니다. " + id));
    return summary;
  }

  /**
   * 분석결과 상세 class name별 탐지 개수
   *
   * @param id
   * @return
   */
  public List<Dashboard> getDashboard(Long id) {
    return inferenceResultRepository.getDashboard(id);
  }

  /**
   * 분석결과 상세 목록
   *
   * @param searchGeoReq
   * @return
   */
  public Page<InferenceResultDto.Geom> getInferenceResultGeomList(
      Long id, InferenceResultDto.SearchGeoReq searchGeoReq) {
    return inferenceResultRepository.getInferenceGeomList(id, searchGeoReq);
  }

  /**
   * 분석결과 상세 목록
   *
   * @param searchReq
   * @return
   */
  @Transactional(readOnly = true)
  public Page<InferenceResultDto.DetailListEntity> listInferenceResultWithGeom(
      @NotNull Long analyId, InferenceResultDto.SearchGeoReq searchReq) {
    // 분석 ID 에 해당하는 dataids를 가져온다.
    List<Long> dataIds =
        inferenceResultRepository.listAnalyGeom(analyId).stream()
            .mapToLong(MapSheetAnalDataEntity::getId)
            .boxed()
            .toList();
    // 해당데이터의 폴리곤데이터를 가져온다
    Page<MapSheetAnalDataGeomEntity> mapSheetAnalDataGeomEntities =
        inferenceResultRepository.listInferenceResultWithGeom(dataIds, searchReq);
    return mapSheetAnalDataGeomEntities.map(MapSheetAnalDataGeomEntity::toEntity);
  }

  /**
   * 추론된 5000:1 도엽 목록
   *
   * @param id
   * @return
   */
  public List<Long> getSheets(Long id) {
    return inferenceResultRepository.getSheets(id);
  }

  @Transactional(readOnly = true)
  public List<MapSheet> listGetScenes5k(Long analyId) {
    List<String> sceneCodes =
        inferenceResultRepository.listAnalyGeom(analyId).stream()
            .mapToLong(MapSheetAnalDataEntity::getMapSheetNum)
            .mapToObj(String::valueOf)
            .toList();

    return mapInkx5kRepository.listGetScenes5k(sceneCodes).stream()
        .map(MapInkx5kEntity::toEntity)
        .toList();
  }
}
