package com.ga.common.menu;

import com.ga.common.exception.BizException;
import com.ga.common.exception.ErrorCode;
import com.ga.common.util.SecurityUtil;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.HashMap;
import java.util.List;
import java.util.Map;

@Service
@RequiredArgsConstructor
public class MenuService {

    private final MenuMapper mapper;

    /** 현재 로그인 사용자의 메뉴 트리 (권한 정보 포함) */
    public List<MenuResp> getMyMenus() {
        Long userId = SecurityUtil.getCurrentUserId();
        if (userId == null) throw new BizException(ErrorCode.UNAUTHORIZED);

        List<MenuVO> flat = mapper.selectAccessibleMenusByUserId(userId);
        Map<Long, List<String>> permissions = loadPermissionsByMenuId(userId);
        return MenuTreeBuilder.build(flat, permissions);
    }

    /** 전체 메뉴 트리 (관리자) */
    public List<MenuResp> getMenuTree() {
        return MenuTreeBuilder.build(mapper.selectAllActive(), Map.of());
    }

    public MenuVO getById(Long menuId) {
        MenuVO m = mapper.selectById(menuId);
        if (m == null) throw new BizException(ErrorCode.NOT_FOUND);
        return m;
    }

    @Transactional
    public Long create(MenuVO vo) {
        if (mapper.selectByCode(vo.getMenuCode()) != null) {
            throw new BizException(ErrorCode.DUPLICATE_DATA);
        }
        mapper.insert(vo);
        return vo.getMenuId();
    }

    @Transactional
    public void update(Long menuId, MenuVO vo) {
        getById(menuId);
        vo.setMenuId(menuId);
        mapper.update(vo);
    }

    @Transactional
    public void delete(Long menuId) {
        if (mapper.countChildren(menuId) > 0) {
            throw new BizException(ErrorCode.DEPENDENT_DATA, "하위 메뉴가 존재합니다");
        }
        mapper.deleteById(menuId);
    }

    private Map<Long, List<String>> loadPermissionsByMenuId(Long userId) {
        Map<Long, List<String>> result = new HashMap<>();
        for (Map<String, Object> row : mapper.selectUserPermissions(userId)) {
            Long menuId = ((Number) row.get("menuId")).longValue();
            String perm = (String) row.get("permCode");
            result.computeIfAbsent(menuId, k -> new java.util.ArrayList<>()).add(perm);
        }
        return result;
    }
}
