package com.kamco.cd.training.postgres.repository.upload;

import static com.kamco.cd.training.postgres.entity.QUploadSessionEntity.uploadSessionEntity;

import com.kamco.cd.training.postgres.entity.UploadSessionEntity;
import com.kamco.cd.training.upload.dto.UploadDto;
import com.querydsl.core.types.Projections;
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.util.UUID;
import org.springframework.data.jpa.repository.support.QuerydslRepositorySupport;

public class UploadSessionRepositoryImpl extends QuerydslRepositorySupport
    implements UploadSessionRepositoryCustom {

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

  @PersistenceContext private EntityManager em;

  public UploadSessionRepositoryImpl(JPAQueryFactory queryFactory) {
    super(UploadSessionEntity.class);
    this.queryFactory = queryFactory;
  }

  @Override
  public void insertUploadSession(UploadDto.UploadAddReq addReq) {
    long execCnt =
        queryFactory
            .insert(uploadSessionEntity)
            .columns(
                uploadSessionEntity.uploadId,
                uploadSessionEntity.datasetId,
                uploadSessionEntity.fileName,
                uploadSessionEntity.fileSize,
                uploadSessionEntity.finalPath,
                uploadSessionEntity.status,
                uploadSessionEntity.tempPath,
                uploadSessionEntity.chunkIndex,
                uploadSessionEntity.chunkTotalIndex,
                uploadSessionEntity.uploadDivi,
                uploadSessionEntity.fileHash,
                uploadSessionEntity.uuid)
            .values(
                addReq.getUploadId(),
                addReq.getDatasetId(),
                addReq.getFileName(),
                addReq.getFileSize(),
                addReq.getFinalPath(),
                addReq.getStatus(),
                addReq.getTempPath(),
                addReq.getChunkIndex(),
                addReq.getChunkTotalIndex(),
                addReq.getUploadDivi(),
                addReq.getFileHash(),
                addReq.getUuid())
            .execute();
  }

  @Override
  public UploadDto.uploadDto findByDatasetUid(String uploadDivi, UUID uuid) {

    UploadDto.uploadDto foundContent =
        queryFactory
            .select(
                Projections.constructor(
                    UploadDto.uploadDto.class,
                    uploadSessionEntity.uploadId,
                    uploadSessionEntity.datasetId,
                    uploadSessionEntity.fileName,
                    uploadSessionEntity.fileSize,
                    uploadSessionEntity.finalPath,
                    uploadSessionEntity.uploadDivi,
                    uploadSessionEntity.status,
                    uploadSessionEntity.tempPath,
                    uploadSessionEntity.chunkIndex,
                    uploadSessionEntity.chunkTotalIndex,
                    uploadSessionEntity.fileHash,
                    uploadSessionEntity.uuid))
            .from(uploadSessionEntity)
            .where(
                uploadSessionEntity
                    .uploadDivi
                    .eq(uploadDivi)
                    .and(uploadSessionEntity.uuid.eq(uuid)))
            .limit(1)
            .fetchOne();

    return foundContent;
  }

  @Override
  public UploadDto.uploadDto findByUuid(String uuid) {

    UploadDto.uploadDto foundContent =
        queryFactory
            .select(
                Projections.constructor(
                    UploadDto.uploadDto.class,
                    uploadSessionEntity.uploadId,
                    uploadSessionEntity.datasetId,
                    uploadSessionEntity.fileName,
                    uploadSessionEntity.fileSize,
                    uploadSessionEntity.finalPath,
                    uploadSessionEntity.uploadDivi,
                    uploadSessionEntity.status,
                    uploadSessionEntity.tempPath,
                    uploadSessionEntity.chunkIndex,
                    uploadSessionEntity.chunkTotalIndex,
                    uploadSessionEntity.fileHash,
                    uploadSessionEntity.uuid))
            .from(uploadSessionEntity)
            .where(uploadSessionEntity.uuid.eq(UUID.fromString(uuid)))
            .limit(1)
            .fetchOne();

    return foundContent;
  }

  public void updateUploadSessionStatus(UploadDto.UploadAddReq addReq) {
    long fileCount =
        queryFactory
            .update(uploadSessionEntity)
            .set(uploadSessionEntity.chunkIndex, addReq.getChunkIndex())
            .set(uploadSessionEntity.status, addReq.getStatus())
            .where(uploadSessionEntity.uploadId.eq(addReq.getUploadId()))
            .execute();
  }
}
