package com.its.op.service.its.oper;

import com.its.op.dao.repository.its.oper.TbOperSystMenuRepository;
import com.its.op.dao.repository.its.oper.TbUserGropInfrRepository;
import com.its.op.dao.repository.its.oper.TbUserGropMenuAthrRepository;
import com.its.op.dto.its.oper.TbUserGropMenuAthrDto;
import com.its.op.entity.its.oper.*;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Optional;

@Slf4j
@RequiredArgsConstructor
@Service
public class TbUserGropMenuAthrService {

    private final TbUserGropMenuAthrRepository repo;
    private final TbUserGropInfrRepository userGropRepo;
    private final TbOperSystMenuRepository systMenuRepo;

    // 전체 데이터 조회
    @Transactional(readOnly = true)
    public List<TbUserGropMenuAthrDto> findAll() {
        List<TbUserGropMenuAthrDto> result = new ArrayList<>();

        List<TbUserGropInfr> userGrops = this.userGropRepo.findAll();
        List<TbOperSystMenu> systMenus = this.systMenuRepo.findAll();
        List<TbUserGropMenuAthr> menuAuths = this.repo.findAll();

        // 메뉴 중에 최상위 메뉴 선택
        HashMap<String, String> systMenuMap = new HashMap<>();
        for (TbOperSystMenu systMenu : systMenus) {
            if (("N").equals(systMenu.getDelYn()) & systMenu.getMenuLevl() == 1) {
                // 레벨이 1 인 것이 최상위 메뉴이다, OPERSYST_MENU_ID, OPER_SYST_ID 는 NULL 로 들어가 있다.
                systMenuMap.put(systMenu.getMenuId(), systMenu.getMenuName());
            }
        }

        // 등록되어 있는 권한 메모리 저장
        HashMap<String, TbUserGropMenuAthr> authMap = new HashMap<>();
        for (TbUserGropMenuAthr menuAthr : menuAuths) {
            authMap.put(menuAthr.getGropId() + "*" + menuAthr.getMenuId(), menuAthr);
        }

        // 권한별로 모든 메뉴 생성
        for (TbUserGropInfr userGrop : userGrops) {
            if (("Y").equals(userGrop.getDelYn())) {
                continue;
            }

            // 모든 메뉴에 대해서
            for (TbOperSystMenu systMenu : systMenus) {
                if (("Y").equals(systMenu.getDelYn()) || systMenu.getMenuLevl() == 1) {
                    // 메뉴레벨이 1인 최상위 메뉴는 제외한다.
                    continue;
                }

                // 최상위 메뉴명을 업데이트
                systMenu.setOperSystNm(systMenuMap.get(systMenu.getOperSystId()));
                // 메뉴권한 등록
                TbUserGropMenuAthrDto menuAthr = TbUserGropMenuAthr.toDtoByMenu(userGrop, systMenu);
                TbUserGropMenuAthr auth = authMap.get(userGrop.getGropId() + "*" + systMenu.getMenuId());
                if (auth != null) {
                    // 메뉴권한이 등록되어 있으면 업데이트
                    menuAthr.updateMenuAuth(auth);
                }
                result.add(menuAthr);
            }
        }
        return result;
    }

    // 데이터 변경 또는 생성-목록(데이터가 존재하면 업데이트 없으면 신규로 생성)
    @Transactional
    public List<TbUserGropMenuAthrDto> mergeInfoList(List<TbUserGropMenuAthrDto.TbUserGropMenuAthrUpdReq> reqList) {
        List<TbUserGropMenuAthrDto> result = new ArrayList<>();
        for (TbUserGropMenuAthrDto.TbUserGropMenuAthrUpdReq req : reqList) {
            //TbGropMenuAthrKey key = new TbGropMenuAthrKey(req.getGropId(), req.getOperSystMenuId());
            //Optional<TbGropMenuAthr> data = this.repo.findById(key);
            TbUserGropMenuAthr obj = req.toEntity();
            this.repo.save(obj);
            result.add(obj.toDto());
        }

        return result;
    }

    // 데이터 변경 또는 생성-개별(데이터가 존재하면 업데이트 없으면 신규로 생성)
    @Transactional
    public TbUserGropMenuAthrDto mergeInfo(TbUserGropMenuAthrDto.TbUserGropMenuAthrUpdReq req) {
        TbUserGropMenuAthr obj = req.toEntity();
        this.repo.save(obj);
        return obj.toDto();
    }

    // 정보 삭제-목록, 존재하는 데이터 만 삭제
    @Transactional
    public List<TbUserGropMenuAthrDto> deleteByIds(List<TbUserGropMenuAthrKey> ids) {
        List<TbUserGropMenuAthrDto> result = new ArrayList<>();
        for (TbUserGropMenuAthrKey id : ids) {
            Optional<TbUserGropMenuAthr> obj = this.repo.findById(id);
            if (obj.isPresent()) {
                this.repo.deleteById(id);
                result.add(obj.get().toDto());
            }
        }
        return result;
    }

}
