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

import static com.kamco.cd.kamcoback.postgres.entity.QMenuEntity.menuEntity;
import static com.kamco.cd.kamcoback.postgres.entity.QMenuMappEntity.menuMappEntity;

import com.kamco.cd.kamcoback.postgres.entity.MenuEntity;
import com.kamco.cd.kamcoback.postgres.entity.QMenuEntity;
import com.querydsl.jpa.impl.JPAQueryFactory;
import java.util.List;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Repository;

@Repository
@RequiredArgsConstructor
public class MenuRepositoryImpl implements MenuRepositoryCustom {

  private final JPAQueryFactory queryFactory;

  @Override
  public List<MenuEntity> getFindAll() {
    return queryFactory.selectFrom(menuEntity).where(menuEntity.deleted.isFalse()).fetch();
  }

  /**
   * 권한별 메뉴 목록
   *
   * @return
   */
  @Override
  public List<MenuEntity> getFindByRole(String role) {

    QMenuEntity parent = QMenuEntity.menuEntity;
    QMenuEntity child = new QMenuEntity("child");

    List<MenuEntity> content =
        queryFactory
            .selectDistinct(parent)
            .from(parent)
            .leftJoin(parent.children, child)
            .fetchJoin()
            .leftJoin(menuMappEntity)
            .on(
                menuMappEntity
                    .roleCode
                    .eq(role)
                    .and(menuMappEntity.deleted.isFalse())
                    .and(menuMappEntity.menuUid.eq(child)))
            .where(
                parent.parent.isNull(),
                parent.deleted.isFalse(),
                parent.isUse.isTrue(),
                menuMappEntity.id.isNotNull())
            .orderBy(parent.menuOrder.asc().nullsLast(), child.menuOrder.asc().nullsLast())
            .fetch();

    return content;
  }

  /**
   * 사용자 role 기준으로 접근 가능한 메뉴 URL 목록 조회
   *
   * @param role
   * @return
   */
  @Override
  public List<MenuEntity> findAllowedMenuUrlsByRole(String role) {

    return queryFactory
        .selectDistinct(menuEntity)
        .from(menuMappEntity)
        .join(menuMappEntity.menuUid, menuEntity)
        .where(
            menuMappEntity.roleCode.eq(role),
            menuMappEntity.deleted.isFalse(),
            menuEntity.deleted.isFalse(),
            menuEntity.isUse.isTrue(),
            menuEntity.menuUrl.isNotNull(),
            menuEntity.menuUrl.isNotEmpty())
        .orderBy(menuEntity.menuOrder.asc().nullsLast())
        .fetch();
  }

  @Override
  public List<MenuEntity> findMenusByRequestPath(String requestPath) {
    return queryFactory
        .selectDistinct(menuEntity)
        .from(menuMappEntity)
        .join(menuMappEntity.menuUid, menuEntity)
        .where(
            menuMappEntity.deleted.isFalse(),
            menuEntity.deleted.isFalse(),
            menuEntity.isUse.isTrue(),
            menuEntity.menuUrl.isNotNull(),
            menuEntity.menuUrl.isNotEmpty(),
            menuEntity.menuUrl.eq(requestPath))
        .orderBy(menuEntity.menuOrder.asc().nullsLast())
        .fetch();
  }
}
