package com.kamco.cd.kamcoback.postgres.repository.label;

import static com.kamco.cd.kamcoback.postgres.entity.QMapSheetAnalDataInferenceEntity.mapSheetAnalDataInferenceEntity;
import static com.kamco.cd.kamcoback.postgres.entity.QMapSheetAnalDataInferenceGeomEntity.mapSheetAnalDataInferenceGeomEntity;

import com.kamco.cd.kamcoback.label.dto.LabelWorkDto;
import com.kamco.cd.kamcoback.label.dto.LabelWorkDto.LabelWorkMng;
import com.kamco.cd.kamcoback.postgres.entity.MapSheetAnalDataGeomEntity;
import com.querydsl.core.BooleanBuilder;
import com.querydsl.core.types.Projections;
import com.querydsl.core.types.dsl.CaseBuilder;
import com.querydsl.core.types.dsl.Expressions;
import com.querydsl.core.types.dsl.StringExpression;
import com.querydsl.jpa.impl.JPAQueryFactory;
import jakarta.persistence.EntityManager;
import jakarta.persistence.PersistenceContext;
import java.time.format.DateTimeFormatter;
import java.util.List;
import lombok.extern.slf4j.Slf4j;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageImpl;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.data.jpa.repository.support.QuerydslRepositorySupport;
import org.springframework.stereotype.Repository;

@Slf4j
@Repository
public class LabelWorkRepositoryImpl extends QuerydslRepositorySupport
    implements LabelWorkRepositoryCustom {

  private final JPAQueryFactory queryFactory;
  private final StringExpression NULL_STRING = Expressions.stringTemplate("cast(null as text)");

  @PersistenceContext private EntityManager em;

  public LabelWorkRepositoryImpl(JPAQueryFactory queryFactory) {
    super(MapSheetAnalDataGeomEntity.class);
    this.queryFactory = queryFactory;
  }

  @Override
  public Page<LabelWorkMng> labelWorkMngList(LabelWorkDto.LabelWorkMngSearchReq searchReq) {

    Pageable pageable = PageRequest.of(searchReq.getPage(), searchReq.getSize());
    BooleanBuilder whereBuilder = new BooleanBuilder();
    BooleanBuilder whereSubBuilder = new BooleanBuilder();

    DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyyMMdd");

    if (searchReq.getDetectYyyy() != null) {
      whereBuilder.and(mapSheetAnalDataInferenceEntity.targetYyyy.eq(searchReq.getDetectYyyy()));
    }

    // mapSheetAnalDataInferenceGeomEntity.dataUid.eq(mapSheetAnalDataInferenceEntity.id)

    whereSubBuilder.and(
        mapSheetAnalDataInferenceGeomEntity.dataUid.eq(mapSheetAnalDataInferenceEntity.id));

    if (searchReq.getStrtDttm() != null
        && !searchReq.getStrtDttm().isEmpty()
        && searchReq.getEndDttm() != null
        && !searchReq.getEndDttm().isEmpty()) {

      // whereSubBuilder.and(mapSheetAnalDataInferenceGeomEntity.labelStateDttm.isNotNull());
      whereSubBuilder.and(
          Expressions.stringTemplate(
                  "to_char({0}, 'YYYYMMDD')", mapSheetAnalDataInferenceGeomEntity.labelStateDttm)
              .between(searchReq.getStrtDttm(), searchReq.getEndDttm()));

      // whereBuilder.and(mapSheetAnalDataInferenceGeomEntity.labelStateDttm.min().isNotNull());

    }

    List<LabelWorkMng> foundContent =
        queryFactory
            .select(
                Projections.constructor(
                    LabelWorkMng.class,
                    mapSheetAnalDataInferenceEntity.compareYyyy,
                    mapSheetAnalDataInferenceEntity.targetYyyy,
                    mapSheetAnalDataInferenceEntity.stage,
                    mapSheetAnalDataInferenceEntity.createdDttm.min(),
                    mapSheetAnalDataInferenceGeomEntity.dataUid.count(),
                    mapSheetAnalDataInferenceGeomEntity.dataUid.count(),
                    new CaseBuilder()
                        .when(mapSheetAnalDataInferenceGeomEntity.labelState.eq("STOP"))
                        .then(1L)
                        .otherwise(0L)
                        .sum(),
                    new CaseBuilder()
                        .when(mapSheetAnalDataInferenceGeomEntity.labelState.eq("LABEL_ING"))
                        .then(1L)
                        .otherwise(0L)
                        .sum(),
                    new CaseBuilder()
                        .when(mapSheetAnalDataInferenceGeomEntity.labelState.eq("LABEL_COMPLETE"))
                        .then(1L)
                        .otherwise(0L)
                        .sum(),
                    mapSheetAnalDataInferenceGeomEntity.labelStateDttm.min()))
            .from(mapSheetAnalDataInferenceEntity)
            .innerJoin(mapSheetAnalDataInferenceGeomEntity)
            .on(whereSubBuilder)
            .where(whereBuilder)
            .groupBy(
                mapSheetAnalDataInferenceEntity.compareYyyy,
                mapSheetAnalDataInferenceEntity.targetYyyy,
                mapSheetAnalDataInferenceEntity.stage)
            .orderBy(
                mapSheetAnalDataInferenceEntity.targetYyyy.desc(),
                mapSheetAnalDataInferenceEntity.stage.desc())
            .offset(pageable.getOffset())
            .limit(pageable.getPageSize())
            .fetch();

    /*
    Long countQuery =
      queryFactory
        .select(mapSheetAnalDataInferenceEntity.count())
        .from(mapSheetAnalDataInferenceEntity)
        .leftJoin(mapSheetAnalDataInferenceGeomEntity)
        .on(whereSubBuilder)
        .where(whereBuilder)
        .groupBy(
          mapSheetAnalDataInferenceEntity.compareYyyy,
          mapSheetAnalDataInferenceEntity.targetYyyy,
          mapSheetAnalDataInferenceEntity.stage
        )
        .fetchOne();

     */

    Long countQuery = foundContent.stream().count();

    return new PageImpl<>(foundContent, pageable, countQuery);
  }
}
