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

import com.kamco.cd.kamcoback.auth.dto.AuthDto;
import com.kamco.cd.kamcoback.auth.dto.AuthDto.Basic;
import com.kamco.cd.kamcoback.postgres.entity.QUserEntity;
import com.kamco.cd.kamcoback.postgres.entity.UserEntity;
import com.querydsl.core.BooleanBuilder;
import com.querydsl.core.types.Projections;
import com.querydsl.core.types.dsl.BooleanExpression;
import com.querydsl.jpa.impl.JPAQueryFactory;
import java.util.List;
import java.util.Optional;
import lombok.RequiredArgsConstructor;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageImpl;
import org.springframework.data.domain.Pageable;
import org.springframework.stereotype.Repository;

@Repository
@RequiredArgsConstructor
public class AuthRepositoryImpl implements AuthRepositoryCustom {

  private final JPAQueryFactory queryFactory;
  private final QUserEntity userEntity = QUserEntity.userEntity;

  /**
   * 유저 아이디로 조회
   *
   * @param userId
   * @return
   */
  @Override
  public Optional<UserEntity> findByUserId(String userId) {
    return Optional.ofNullable(
        queryFactory.selectFrom(userEntity).where(userEntity.userId.eq(userId)).fetchOne());
  }

  /**
   * 유저 시퀀스 id로 조회
   *
   * @param id
   * @return
   */
  @Override
  public Optional<UserEntity> findUserById(Long id) {
    return Optional.ofNullable(
        queryFactory.selectFrom(userEntity).where(userEntity.id.eq(id)).fetchOne());
  }

  /**
   * 관리자 목록 조회
   *
   * @param searchReq
   * @return
   */
  @Override
  public Page<Basic> getUserList(AuthDto.SearchReq searchReq) {
    Pageable pageable = searchReq.toPageable();
    BooleanBuilder builder = new BooleanBuilder();
    if (searchReq.getUserNm() != null && !searchReq.getUserNm().isEmpty()) {
      builder.and(likeName(userEntity, searchReq.getUserNm()));
    }

    List<Basic> content =
        queryFactory
            .select(
                Projections.constructor(
                    AuthDto.Basic.class,
                    userEntity.id,
                    userEntity.userAuth,
                    userEntity.userNm,
                    userEntity.userId,
                    userEntity.empId,
                    userEntity.userEmail,
                    userEntity.createdDttm))
            .from(userEntity)
            .where(builder)
            .offset(pageable.getOffset())
            .limit(pageable.getPageSize())
            .orderBy(userEntity.userId.asc())
            .fetch();

    long total = queryFactory.select(userEntity.id).from(userEntity).where(builder).fetchCount();
    return new PageImpl<>(content, pageable, total);
  }

  private BooleanExpression likeName(QUserEntity entity, String nameStr) {
    if (nameStr == null || nameStr.isEmpty()) {
      return null;
    }
    // ex) WHERE LOWER(name) LIKE LOWER('%입력값%')
    return entity.userNm.containsIgnoreCase(nameStr.trim());
  }
}
