package incheon.ags.ias.sysMenuAuthrt.service.impl;

import incheon.ags.ias.sysMenuAuthrt.mapper.SysMenuAuthrtMapper;
import incheon.ags.ias.sysMenuAuthrt.service.SysMenuAuthrtService;
import incheon.ags.ias.sysMenuAuthrt.vo.SysMenuAuthrtSearchVO;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.egovframe.rte.fdl.cmmn.EgovAbstractServiceImpl;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

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

@Slf4j
@Service("sysMenuAuthrtService")
@RequiredArgsConstructor
public class SysMenuAuthrtServiceImpl extends EgovAbstractServiceImpl implements SysMenuAuthrtService {
    private final SysMenuAuthrtMapper sysMenuAuthrtMapper;

    @Override
    public List<Map<String, Object>> selectSysMenuAuthrtList(SysMenuAuthrtSearchVO sysMenuAuthrtSearchVO) throws Exception {
        return sysMenuAuthrtMapper.selectSysMenuAuthrtList(sysMenuAuthrtSearchVO);
    }

    @Override
    public int selectSysMenuAuthrtListCnt(SysMenuAuthrtSearchVO sysMenuAuthrtSearchVO) throws Exception {
        return sysMenuAuthrtMapper.selectSysMenuAuthrtListCnt(sysMenuAuthrtSearchVO);
    }

    @Override
    public List<Map<String, Object>> selectAuthrtList() throws Exception {
        return sysMenuAuthrtMapper.selectAuthrtList();
    }

    @Override
    public List<Map<String, Object>> selectRoleList() throws Exception {
        return sysMenuAuthrtMapper.selectRoleList();
    }

    @Override
    public List<Map<String, Object>> selectAuthrtStngList(String sysCd) throws Exception {
        return sysMenuAuthrtMapper.selectAuthrtStngList(sysCd);
    }

    @Override
    public List<Map<String, Object>> selectSystemAuthrtList(String sysCd) throws Exception {
        return sysMenuAuthrtMapper.selectSystemAuthrtList(sysCd);
    }

    @Override
    public Map<String, Object> selectRoleInfo(Map<String, Object> params) throws Exception {
        return sysMenuAuthrtMapper.selectRoleInfo(params);
    }

    @Override
    public List<Map<String, Object>> selectMenuListBySysCd(String sysCd) throws Exception {
        return sysMenuAuthrtMapper.selectMenuListBySysCd(sysCd);
    }

    @Override
    public List<Map<String, Object>> selectSystemList() throws Exception {
        return sysMenuAuthrtMapper.selectSystemList();
    }

    @Override
    public List<Map<String, Object>> selectSysMenuAuthrtByRoleCd(Map<String, Object> params) throws Exception {
        return sysMenuAuthrtMapper.selectSysMenuAuthrtByRoleCd(params);
    }

    @Override
    public List<Map<String, Object>> selectSysRoleAuthrtByRoleCd(Map<String, Object> params) throws Exception {
        return sysMenuAuthrtMapper.selectSysRoleAuthrtByRoleCd(params);
    }

    @Override
    @Transactional
    public int updateAuthrtStngByTarget(String typeCd, String trgtCd, List<Map<String, Object>> stngList, String userId, String sysCd) throws Exception {
        log.info("권한 설정 재설정 시작 - Type: {}, Target: {}", typeCd, trgtCd);

        // 1. 기존 권한 설정 조회
        Map<String, Object> queryParams = new HashMap<>();
        queryParams.put("authrtStngTypeCd", typeCd);
        queryParams.put("authrtStngTrgtCd", trgtCd);
        queryParams.put("sysCd", sysCd);
        List<Map<String, Object>> existingStngList = sysMenuAuthrtMapper.selectAuthrtStngByTarget(queryParams);
        log.info("기존 권한 설정 {}건 조회", existingStngList.size());

        // 2. 새로운 권한 목록 추출
        java.util.Set<String> newAuthrtCdSet = new java.util.HashSet<>();
        if (stngList != null && !stngList.isEmpty()) {
            for (Map<String, Object> stng : stngList) {
                String authrtCd = (String) stng.get("authrtCd");
                if (authrtCd != null) {
                    newAuthrtCdSet.add(authrtCd);
                }
            }
        }

        // 3. 삭제될 권한 목록 추출 및 매핑 삭제
        int deletedMappingCount = 0;
        for (Map<String, Object> existingStng : existingStngList) {
            String authrtCd = (String) existingStng.get("authrtCd");
            if (authrtCd == null) authrtCd = (String) existingStng.get("AUTHRT_CD");

            // 새로운 목록에 없는 권한은 매핑 삭제
            if (!newAuthrtCdSet.contains(authrtCd)) {
                Map<String, Object> deleteMapParams = new HashMap<>();

                if ("MENU".equals(typeCd)) {
                    deleteMapParams.put("menuCd", trgtCd);
                    deleteMapParams.put("authrtCd", authrtCd);
                    deletedMappingCount += sysMenuAuthrtMapper.deleteMenuRoleAuthrtMpngByMenuAndAuthrt(deleteMapParams);
                    log.info("메뉴-역할-권한 매핑 삭제 - Menu: {}, Authrt: {}", trgtCd, authrtCd);
                } else if ("SYS".equals(typeCd)) {
                    deleteMapParams.put("sysCd", trgtCd);
                    deleteMapParams.put("authrtCd", authrtCd);
                    deletedMappingCount += sysMenuAuthrtMapper.deleteSysRoleAuthrtMpngBySysAndAuthrt(deleteMapParams);
                    log.info("시스템-역할-권한 매핑 삭제 - Sys: {}, Authrt: {}", trgtCd, authrtCd);
                }
            }
        }
        log.info("매핑 테이블에서 {}건 삭제 (쓰레기 데이터 제거)", deletedMappingCount);

        // 4. 기존 권한 설정 전체 삭제
        int deletedCount = sysMenuAuthrtMapper.deleteAuthrtStngByTarget(queryParams);
        log.info("기존 권한 설정 {}건 삭제", deletedCount);

        // 5. 새로운 권한 설정 삽입
        int insertCount = 0;
        if (stngList != null && !stngList.isEmpty()) {
            for (Map<String, Object> stng : stngList) {
                incheon.ags.ias.sysMenuAuthrt.vo.AuthrtStngVO vo = new incheon.ags.ias.sysMenuAuthrt.vo.AuthrtStngVO();
                vo.setAuthrtCd((String) stng.get("authrtCd"));
                vo.setAuthrtStngTypeCd((String) stng.get("authrtStngTypeCd"));
                vo.setAuthrtStngTrgtCd((String) stng.get("authrtStngTrgtCd"));
                vo.setSysCd(sysCd);
                vo.setFrstRegId(userId);
                vo.setLastMdfcnId(userId);

                insertCount += sysMenuAuthrtMapper.insertAuthrtStng(vo);
            }
            log.info("권한 설정 {}건 등록 완료", insertCount);
        } else {
            log.info("삽입할 권한 설정이 없습니다 (전체 삭제만 수행)");
        }

        return insertCount;
    }

    /**
     * 역할-권한 매핑 전체 재설정 (삭제 후 재삽입)
     * 트랜잭션으로 묶여서 실행되므로 중간에 실패하면 전체 롤백됨
     */
    @Override
    @Transactional
    public void updateRoleAuthrtMapping(String roleCd, String sysCd, List<Map<String, Object>> menuAuthrtList,
                                        List<Map<String, Object>> sysAuthrtList, String userId) throws Exception {

        log.info("역할 권한 매핑 재설정 시작 - roleCd: {}, sysCd: {}", roleCd, sysCd);

        // 1. 기존 메뉴 권한 삭제
        Map<String, Object> deleteMenuParams = new HashMap<>();
        deleteMenuParams.put("roleCd", roleCd);
        deleteMenuParams.put("sysCd", sysCd);
        int deletedMenuCount = sysMenuAuthrtMapper.deleteMenuRoleAuthrtMpngByRoleCd(deleteMenuParams);
        log.info("기존 메뉴 권한 {}건 삭제", deletedMenuCount);

        // 2. 기존 시스템 권한 삭제
        Map<String, Object> deleteSysParams = new HashMap<>();
        deleteSysParams.put("roleCd", roleCd);
        deleteSysParams.put("sysCd", sysCd);
        int deletedSysCount = sysMenuAuthrtMapper.deleteSysRoleAuthrtMpngByRoleCd(deleteSysParams);
        log.info("기존 시스템 권한 {}건 삭제", deletedSysCount);

        // 3. 메뉴 권한 재삽입
        int insertedMenuCount = 0;
        if (menuAuthrtList != null && !menuAuthrtList.isEmpty()) {
            for (Map<String, Object> mapping : menuAuthrtList) {
                incheon.ags.ias.sysMenuAuthrt.vo.MenuRoleAuthrtMpngVO vo = new incheon.ags.ias.sysMenuAuthrt.vo.MenuRoleAuthrtMpngVO();
                vo.setMenuCd((String) mapping.get("menuCd"));
                vo.setRoleCd(roleCd);
                vo.setSysCd((String) mapping.get("sysCd"));  // 복합키 필수
                vo.setAuthrtCd((String) mapping.get("authrtCd"));
                vo.setFrstRegId(userId);
                vo.setLastMdfcnId(userId);

                log.info(">>> 메뉴 권한 삽입: menuCd={}, roleCd={}, sysCd={}, authrtCd={}",
                         vo.getMenuCd(), vo.getRoleCd(), vo.getSysCd(), vo.getAuthrtCd());

                insertedMenuCount += sysMenuAuthrtMapper.insertMenuRoleAuthrtMpng(vo);
            }
            log.info("메뉴 권한 {}건 삽입", insertedMenuCount);
        }

        // 4. 시스템 권한 재삽입
        int insertedSysCount = 0;
        if (sysAuthrtList != null && !sysAuthrtList.isEmpty()) {
            for (Map<String, Object> mapping : sysAuthrtList) {
                incheon.ags.ias.sysMenuAuthrt.vo.SysRoleAuthrtMpngVO vo = new incheon.ags.ias.sysMenuAuthrt.vo.SysRoleAuthrtMpngVO();
                vo.setSysCd((String) mapping.get("sysCd"));
                vo.setRoleCd(roleCd);
                vo.setAuthrtCd((String) mapping.get("authrtCd"));
                vo.setFrstRegId(userId);
                vo.setLastMdfcnId(userId);

                insertedSysCount += sysMenuAuthrtMapper.insertSysRoleAuthrtMpng(vo);
            }
            log.info("시스템 권한 {}건 삽입", insertedSysCount);
        }

        log.info("역할 권한 매핑 재설정 완료 - 메뉴: {}건, 시스템: {}건", insertedMenuCount, insertedSysCount);
    }
}
