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

import incheon.ags.ias.role.mapper.RoleMapper;
import incheon.ags.ias.role.service.RoleService;
import incheon.ags.ias.role.vo.RoleSearchVO;
import incheon.ags.ias.role.vo.RoleVO;
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("roleService")
@RequiredArgsConstructor
public class RoleServiceImpl extends EgovAbstractServiceImpl implements RoleService {

    private final RoleMapper roleMapper;

    @Override
    public List<Map<String,Object>> selectRoleList(RoleSearchVO roleSearchVO) {
        log.debug("역할 목록 조회 요청 - 검색조건: {}", roleSearchVO);
        List<Map<String, Object>> result = roleMapper.selectRoleList(roleSearchVO);
        log.debug("역할 목록 조회 완료 - 조회건수: {}", result.size());
        return result;
    }

    @Override
    public RoleVO selectRoleById(RoleVO roleVO) {
        log.debug("역할 상세 조회 요청 - 역할코드: {}, 시스템코드: {}", roleVO.getRoleCd(), roleVO.getSysCd());
        RoleVO result = roleMapper.selectRoleById(roleVO);
        if (result == null) {
            log.warn("역할 상세 조회 실패 - 역할을 찾을 수 없음: ({}, {})", roleVO.getRoleCd(), roleVO.getSysCd());
        }
        return result;
    }

    @Override
    public int selectRoleCnt(RoleSearchVO roleSearchVO) {
        log.debug("역할 목록 총 개수 조회 요청");
        return roleMapper.selectRoleCnt(roleSearchVO);
    }

    @Override
    public int insertRole(RoleVO roleVO) {
        log.info("역할 등록 요청 - 역할코드: {}, 시스템코드: {}, 역할명: {}",
                roleVO.getRoleCd(), roleVO.getSysCd(), roleVO.getRoleNm());

        if (roleVO == null || roleVO.getRoleCd() == null || roleVO.getSysCd() == null) {
            log.error("역할 등록 실패 - 필수 파라미터 누락 (ROLE_CD, SYS_CD 필수)");
            throw new IllegalArgumentException("역할 정보가 올바르지 않습니다. (ROLE_CD, SYS_CD 필수)");
        }

        int result = roleMapper.insertRole(roleVO);

        if (result > 0) {
            log.info("역할 등록 성공 - 역할코드: ({}, {})", roleVO.getRoleCd(), roleVO.getSysCd());
        } else {
            log.error("역할 등록 실패 - 역할코드: ({}, {})", roleVO.getRoleCd(), roleVO.getSysCd());
        }

        return result;
    }

    @Override
    public int updateRole(RoleVO roleVO) {
        log.info("역할 수정 요청 - 역할코드: ({}, {})", roleVO.getRoleCd(), roleVO.getSysCd());

        if (roleVO == null || roleVO.getRoleCd() == null || roleVO.getSysCd() == null) {
            log.error("역할 수정 실패 - 필수 파라미터 누락 (ROLE_CD, SYS_CD 필수)");
            throw new IllegalArgumentException("역할 정보가 올바르지 않습니다. (ROLE_CD, SYS_CD 필수)");
        }

        int result = roleMapper.updateRole(roleVO);

        if (result > 0) {
            log.info("역할 수정 성공 - 역할코드: ({}, {})", roleVO.getRoleCd(), roleVO.getSysCd());
        } else {
            log.warn("역할 수정 실패 - 역할을 찾을 수 없음: ({}, {})", roleVO.getRoleCd(), roleVO.getSysCd());
        }

        return result;
    }

    @Override
    public int deleteRole(RoleVO roleVO) {
        log.info("역할 삭제 요청 - 역할코드: ({}, {})", roleVO.getRoleCd(), roleVO.getSysCd());

        if (roleVO == null || roleVO.getRoleCd() == null || roleVO.getSysCd() == null) {
            log.error("역할 삭제 실패 - 필수 파라미터 누락 (ROLE_CD, SYS_CD 필수)");
            throw new IllegalArgumentException("역할 코드가 올바르지 않습니다. (ROLE_CD, SYS_CD 필수)");
        }

        int result = roleMapper.deleteRole(roleVO);

        if (result > 0) {
            log.info("역할 삭제 성공 - 역할코드: ({}, {})", roleVO.getRoleCd(), roleVO.getSysCd());
        } else {
            log.warn("역할 삭제 실패 - 역할을 찾을 수 없음: ({}, {})", roleVO.getRoleCd(), roleVO.getSysCd());
        }

        return result;
    }

    @Override
    public List<Map<String, Object>> selectSysList() {
        log.debug("시스템 목록 조회 요청");
        return roleMapper.selectSysList();
    }

    @Override
    public RoleVO selectRoleBySysAndType(String sysCd, String roleTypeCd) {
        log.debug("시스템별 권한유형 역할 조회 요청 - 시스템코드: {}, 권한유형: {}", sysCd, roleTypeCd);
        RoleVO result = roleMapper.selectRoleBySysAndType(sysCd, roleTypeCd);
        if (result != null) {
            log.debug("시스템별 권한유형 역할 조회 완료 - 역할코드: {}", result.getRoleCd());
        }
        return result;
    }

    /**
     * 복합키 기반 ROLE_CD 일괄 변경 (SYS_CD 포함)
     */
    public int updateRoleCodeCascadeWithSys(String sysCd, String oldRoleCd, String newRoleCd) {
        log.info("ROLE_CD 일괄 변경 시작 - ({}, {}) → {} (수정자: ThreadLocal)",
                sysCd, oldRoleCd, newRoleCd);

        // 0. 신규 ROLE_CD 중복 체크 (동일 시스템 내)
        RoleVO oldRole = new RoleVO();
        oldRole.setRoleCd(oldRoleCd);
        oldRole.setSysCd(sysCd);
        RoleVO currentRole = roleMapper.selectRoleById(oldRole);

        if (currentRole == null) {
            log.error("❌ 변경 대상 역할을 찾을 수 없음: ({}, {})", oldRoleCd, sysCd);
            throw new IllegalArgumentException("변경 대상 역할을 찾을 수 없습니다.");
        }

        // 동일 시스템 내에서 중복 체크
        RoleVO checkDuplicate = new RoleVO();
        checkDuplicate.setRoleCd(newRoleCd);
        checkDuplicate.setSysCd(sysCd);
        RoleVO existingRole = roleMapper.selectRoleById(checkDuplicate);

        if (existingRole != null) {
            log.error("❌ ROLE_CD 변경 실패 - 동일 시스템({})에 이미 존재하는 코드: {}", sysCd, newRoleCd);
            throw new IllegalArgumentException("해당 시스템에 이미 존재하는 권한그룹 코드입니다: " + newRoleCd);
        }

        Map<String, Object> params = new HashMap<>();
        params.put("oldRoleCd", oldRoleCd);
        params.put("newRoleCd", newRoleCd);
        params.put("sysCd", sysCd);

        int totalUpdated = 0;

        // 1. ROLE 테이블 - ROLE_CD 변경 (PK 변경)
        //    → FK ON UPDATE CASCADE에 의해 모든 연관 테이블 자동 업데이트됨
        int roleUpdated = roleMapper.updateRoleCode(params);
        log.info("✓ ROLE 테이블 PK 업데이트: {} 건 (FK CASCADE로 8개 연관 테이블 자동 업데이트)", roleUpdated);
        totalUpdated += roleUpdated;

        // 2. ROLE 테이블 - UP_ROLE_CD 변경 (자기참조, FK 아님)
        int upRoleUpdated = roleMapper.updateUpRoleCode(params);
        log.info("✓ ROLE 테이블 UP_ROLE_CD 업데이트: {} 건", upRoleUpdated);
        totalUpdated += upRoleUpdated;

        log.info("ROLE_CD 일괄 변경 완료 - 총 {} 건 직접 업데이트 (FK CASCADE로 연관 테이블 자동 처리)", totalUpdated);

        return totalUpdated;
    }

    @Override
    public String selectRulNm(RoleVO roleVO) {
        log.debug("규칙명 조회 요청 - 역할코드: ({}, {})", roleVO.getRoleCd(), roleVO.getSysCd());
        return roleMapper.selectRulNm(roleVO);
    }

    @Override
    public int updateRulNm(RoleVO roleVO) {
        log.info("규칙명 수정 요청 - 역할코드: ({}, {}), 규칙명: {}",
                roleVO.getRoleCd(), roleVO.getSysCd(), roleVO.getRulNm());
        return roleMapper.updateRulNm(roleVO);
    }
}