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

import incheon.ags.ias.authrtAplyMng.mapper.AuthrtAplyMngMapper;
import incheon.ags.ias.authrtAplyMng.service.AuthrtAplyMngService;
import incheon.ags.ias.authrtAplyMng.vo.AuthrtAplyMngSearchVO;
import incheon.ags.ias.authrtAplyMng.vo.AuthrtAplyMngVO;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.egovframe.rte.fdl.cmmn.EgovAbstractServiceImpl;
import org.springframework.stereotype.Service;

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

@Slf4j
@Service("authAplyMngService")
@RequiredArgsConstructor
public class AuthrtAplyMngServiceImpl extends EgovAbstractServiceImpl implements AuthrtAplyMngService {
    private final AuthrtAplyMngMapper authrtAplyMngMapper;

    @Override
    public List<Map<String, Object>> selectUserRoleAplyList(AuthrtAplyMngSearchVO authrtAplyMngSearchVO) throws Exception {
        return authrtAplyMngMapper.selectUserRoleAplyList(authrtAplyMngSearchVO);
    }

    @Override
    public int selectUserRoleAplyTotalCnt(AuthrtAplyMngSearchVO authrtAplyMngSearchVO) throws Exception {
        return authrtAplyMngMapper.selectUserRoleAplyTotalCnt(authrtAplyMngSearchVO);
    }

    @Override
    public int approveUserRoleAplyAll(List<Long> aplySnList, List<String> sysCdList, String currentUserId, String rvwOpnnCn) throws Exception {
        int successCount = 0;

        log.info("=== 일괄 승인 처리 시작 ===");
        log.info("총 승인 건수: {}", aplySnList.size());

        // 시스템별로 그룹화 (같은 시스템에 대한 신청들을 함께 처리)
        Map<String, List<Integer>> sysCdToIndexMap = new java.util.HashMap<>();
        for (int i = 0; i < aplySnList.size(); i++) {
            String sysCd = (sysCdList != null && sysCdList.size() > i) ? sysCdList.get(i) : null;
            if (sysCd != null) {
                sysCdToIndexMap.computeIfAbsent(sysCd, k -> new java.util.ArrayList<>()).add(i);
            }
        }

        // 시스템별로 처리
        for (Map.Entry<String, List<Integer>> entry : sysCdToIndexMap.entrySet()) {
            String sysCd = entry.getKey();
            List<Integer> indices = entry.getValue();
            
            log.info("=== 시스템 {} 처리 시작 (신청 {}건) ===", sysCd, indices.size());

            // 1. 모든 신청 정보 수집 및 검증
            List<Map<String, Object>> aplyInfoList = new java.util.ArrayList<>();
            String userId = null;
            Long maxAplySn = null; // 가장 큰 신청 번호
            
            for (int idx : indices) {
                Long aplySn = aplySnList.get(idx);
                
                AuthrtAplyMngVO mstVO = new AuthrtAplyMngVO();
                mstVO.setAplySn(aplySn);
                mstVO.setSysCd(sysCd);
                AuthrtAplyMngVO aplyMstInfo = authrtAplyMngMapper.selectUserRoleAplyMstWithAplySn(mstVO);

                if (aplyMstInfo == null) {
                    throw new Exception("신청 정보를 찾을 수 없습니다. aplySn: " + aplySn);
                }

                // 첫 번째 신청의 userId 저장 (모든 신청이 같은 사용자여야 함)
                if (userId == null) {
                    userId = aplyMstInfo.getAplcnUserId();
                } else if (!userId.equals(aplyMstInfo.getAplcnUserId())) {
                    throw new Exception("다른 사용자의 신청을 함께 처리할 수 없습니다.");
                }

                // 가장 큰 신청 번호 찾기
                if (maxAplySn == null || aplySn > maxAplySn) {
                    maxAplySn = aplySn;
                }

                List<Map<String, Object>> aplyDtlList = authrtAplyMngMapper.selectUserRoleAplyDtlWithAplySn(mstVO);
                if (aplyDtlList == null || aplyDtlList.isEmpty()) {
                    throw new Exception("신청 상세 정보를 찾을 수 없습니다. aplySn: " + aplySn);
                }

                Map<String, Object> aplyInfo = new java.util.HashMap<>();
                aplyInfo.put("aplySn", aplySn);
                aplyInfo.put("mstInfo", aplyMstInfo);
                aplyInfo.put("dtlList", aplyDtlList);
                aplyInfoList.add(aplyInfo);
            }

            log.info("신청자: {}, 시스템: {}, 최종 승인할 신청번호: {}", userId, sysCd, maxAplySn);

            // 2. 기존 신청 마스터 만료 처리 (현재 일괄 승인하는 신청들 모두 제외)
            Map<String, Object> expireParams = new java.util.HashMap<>();
            expireParams.put("userId", userId);
            expireParams.put("sysCd", sysCd);
            expireParams.put("currentUserId", currentUserId);
            // currentAplySn을 설정하지 않으면 모든 기존 신청 만료
            
            int expiredCount = authrtAplyMngMapper.expireUserRoleAplyMst(expireParams);
            log.info("기존 신청 마스터 만료 처리 완료: {}건", expiredCount);

            // 3. 기존 권한 전체 삭제 (시스템 단위 - 한 번만 실행)
            Map<String, Object> deleteParams = new java.util.HashMap<>();
            deleteParams.put("userId", userId);
            deleteParams.put("sysCd", sysCd);
            int deletedCount = authrtAplyMngMapper.deleteUserRolesBySystem(deleteParams);
            log.info("기존 권한 전체 삭제 완료: {}건", deletedCount);

            // 4. 각 신청 처리 (신청 번호 기준으로 정렬)
            aplyInfoList.sort((a, b) -> Long.compare((Long) a.get("aplySn"), (Long) b.get("aplySn")));
            
            for (int i = 0; i < aplyInfoList.size(); i++) {
                Map<String, Object> aplyInfo = aplyInfoList.get(i);
                Long aplySn = (Long) aplyInfo.get("aplySn");
                AuthrtAplyMngVO mstInfo = (AuthrtAplyMngVO) aplyInfo.get("mstInfo");
                List<Map<String, Object>> dtlList = (List<Map<String, Object>>) aplyInfo.get("dtlList");
                boolean isMaxAplySn = aplySn.equals(maxAplySn); // 가장 큰 신청번호인지 확인

                log.info("--- 신청 번호: {} 처리 ({}/{}) {} ---", 
                    aplySn, i + 1, aplyInfoList.size(), isMaxAplySn ? "[최신 신청 - 승인]" : "[이전 신청 - 만료]");

                // 가장 큰 신청번호인 경우에만 권한 등록
                if (isMaxAplySn) {
                    for (Map<String, Object> dtl : dtlList) {
                        AuthrtAplyMngVO mpngVO = new AuthrtAplyMngVO();
                        mpngVO.setUserId(mstInfo.getAplcnUserId());
                        mpngVO.setRoleCd((String) dtl.get("roleCd"));
                        mpngVO.setRoleBgngYmd(mstInfo.getAplyBgngYmd());
                        mpngVO.setRoleEndYmd(mstInfo.getAplyEndYmd());
                        mpngVO.setSysCd(sysCd);
                        mpngVO.setNowUserId(currentUserId);

                        int mpngResult = authrtAplyMngMapper.approveUserRoleAplyWithMpng(mpngVO);
                        if (mpngResult <= 0) {
                            throw new Exception("권한 매핑 등록 실패. roleCd: " + dtl.get("roleCd"));
                        }
                    }
                    log.info("새 권한 등록 완료: {}건", dtlList.size());
                }

                // 신청 마스터 상태 업데이트 (가장 큰 번호는 승인, 나머지는 만료)
                AuthrtAplyMngVO updateVO = new AuthrtAplyMngVO();
                updateVO.setAplySn(aplySn);
                updateVO.setSysCd(sysCd);
                updateVO.setAplyStcd(isMaxAplySn ? "APLYSTTSTY003" : "APLYSTTSTY005"); // 최신만 승인, 나머지 만료
                updateVO.setRvwUserId(currentUserId);
                // 승인 사유: 사용자 입력값이 있으면 사용, 없으면 기본값
                String approveReason = (rvwOpnnCn != null && !rvwOpnnCn.isEmpty()) ? rvwOpnnCn : "일괄 승인 처리됨";
                updateVO.setRvwOpnnCn(isMaxAplySn ? approveReason : "이후 신청으로 대체됨");
                updateVO.setNowUserId(currentUserId);

                int updateResult = authrtAplyMngMapper.updateAplyStcd(updateVO);
                if (updateResult <= 0) {
                    throw new Exception("신청 상태 업데이트 실패");
                }
                log.info("신청 상태 {} 처리 완료", isMaxAplySn ? "승인(APLYSTTSTY003)" : "만료(APLYSTTSTY005)");

                successCount++;
            }
            
            log.info("=== 시스템 {} 처리 완료 ===", sysCd);
        }

        log.info("=== 일괄 승인 처리 완료: 총 {}건 처리 ===", successCount);
        return successCount;
    }


    @Override
    public int rejectUserRoleAplyAll(List<Long> aplySnList, List<String> sysCdList, String currentUserId, String rvwOpnnCn) throws Exception {
        int successCount = 0;

        log.info("=== 일괄 반려 처리 시작 ===");
        log.info("총 반려 건수: {}", aplySnList.size());

        for (int i = 0; i < aplySnList.size(); i++) {
            Long aplySn = aplySnList.get(i);
            String sysCd = (sysCdList != null && sysCdList.size() > i) ? sysCdList.get(i) : null;

            log.info("--- 신청 번호: {} 반려 처리 ---", aplySn);

            // 신청 마스터 상태 업데이트 (반려)
            AuthrtAplyMngVO updateVO = new AuthrtAplyMngVO();
            updateVO.setAplySn(aplySn);
            updateVO.setSysCd(sysCd);
            updateVO.setAplyStcd("APLYSTTSTY002"); // 반려 상태
            updateVO.setRvwUserId(currentUserId);
            String rejectReason = (rvwOpnnCn != null && !rvwOpnnCn.isEmpty()) ? rvwOpnnCn : "일괄 반려 처리됨";
            updateVO.setRvwOpnnCn(rejectReason);
            updateVO.setNowUserId(currentUserId);

            int updateResult = authrtAplyMngMapper.updateAplyStcd(updateVO);
            if (updateResult <= 0) {
                throw new Exception("신청 상태 업데이트 실패. aplySn: " + aplySn);
            }
            log.info("신청 번호 {} 반려 처리 완료", aplySn);

            successCount++;
        }

        log.info("=== 일괄 반려 처리 완료: 총 {}건 처리 ===", successCount);
        return successCount;
    }

    @Override
    public AuthrtAplyMngVO selectUserRoleAplyDetail(AuthrtAplyMngVO authrtAplyMngVO) throws Exception {
        return authrtAplyMngMapper.selectUserRoleAplyDetail(authrtAplyMngVO);
    }

    @Override
    public int updateUserRoleAply(Long aplySn, List<String> roleCdList, AuthrtAplyMngVO authrtAplyMngVO, String currentUserId) throws Exception {
        int successCount = 0;

        try {
            log.info("=== 권한 신청 처리 시작 ===");
            log.info("신청 번호: {}, 처리 상태: {}", aplySn, authrtAplyMngVO.getAplyStcd());

            // MST 조회
            AuthrtAplyMngVO mstVO = new AuthrtAplyMngVO();
            mstVO.setAplySn(aplySn);
            AuthrtAplyMngVO aplyMstInfo = authrtAplyMngMapper.selectUserRoleAplyMstWithAplySn(mstVO);

            if (aplyMstInfo == null) {
                throw new Exception("신청 정보를 찾을 수 없습니다.");
            }
            log.info("신청자: {}, 시스템: {}", aplyMstInfo.getAplcnUserId(), aplyMstInfo.getSysCd());

            // 승인 처리인 경우
            if (authrtAplyMngVO.getAplyStcd().equals("APLYSTTSTY003")) {
                log.info("승인 처리 시작");

                // 1. 기존 신청 마스터 만료 처리 (현재 승인하는 신청 제외)
                Map<String, Object> expireParams = new java.util.HashMap<>();
                expireParams.put("userId", aplyMstInfo.getAplcnUserId());
                expireParams.put("sysCd", aplyMstInfo.getSysCd());
                expireParams.put("currentAplySn", aplySn);
                expireParams.put("currentUserId", currentUserId);
                int expiredCount = authrtAplyMngMapper.expireUserRoleAplyMst(expireParams);
                log.info("기존 신청 마스터 만료 처리 완료: {}건", expiredCount);

                // 2. 기존 권한 전체 삭제 (시스템 단위)
                Map<String, Object> deleteParams = new java.util.HashMap<>();
                deleteParams.put("userId", aplyMstInfo.getAplcnUserId());
                deleteParams.put("sysCd", aplyMstInfo.getSysCd());
                int deletedCount = authrtAplyMngMapper.deleteUserRolesBySystem(deleteParams);
                log.info("기존 권한 전체 삭제 완료: {}건", deletedCount);

                // 3. 새 권한 등록
                log.info("새 권한 등록 시작: {}건", roleCdList.size());
                for (String roleCd : roleCdList) {
                    AuthrtAplyMngVO mpngVO = new AuthrtAplyMngVO();
                    mpngVO.setUserId(authrtAplyMngVO.getAplcnUserId());
                    mpngVO.setRoleCd(roleCd);
                    mpngVO.setRoleBgngYmd(authrtAplyMngVO.getAplyBgngYmd());
                    mpngVO.setRoleEndYmd(authrtAplyMngVO.getAplyEndYmd());
                    mpngVO.setSysCd(aplyMstInfo.getSysCd());
                    mpngVO.setNowUserId(currentUserId);

                    int mpngResult = authrtAplyMngMapper.approveUserRoleAplyWithMpng(mpngVO);
                    if (mpngResult <= 0) {
                        throw new Exception("권한 매핑 등록 실패. roleCd: " + roleCd);
                    }
                }
                log.info("새 권한 등록 완료: {}건", roleCdList.size());
            } else {
                log.info("반려 처리");
            }

            // 4. 현재 신청 마스터 상태 업데이트
            AuthrtAplyMngVO updateVO = new AuthrtAplyMngVO();
            updateVO.setAplySn(aplySn);
            updateVO.setAplyStcd(authrtAplyMngVO.getAplyStcd());
            updateVO.setRvwUserId(currentUserId);
            updateVO.setRvwOpnnCn(authrtAplyMngVO.getRvwOpnnCn());
            updateVO.setNowUserId(currentUserId);

            int updateResult = authrtAplyMngMapper.updateAplyStcd(updateVO);
            if (updateResult <= 0) {
                throw new Exception("신청 상태 업데이트 실패");
            }
            log.info("신청 상태 업데이트 완료");

            successCount++;
            log.info("=== 권한 신청 처리 완료 (성공) ===");

        } catch (Exception e) {
            log.error("권한 신청 처리 실패 - aplySn: {}, error: {}", aplySn, e.getMessage(), e);
            throw e;
        }

        return successCount;
    }
}
