package incheon.ags.ias.role.web;

import incheon.ags.ias.authrt.service.AuthrtService;
import incheon.ags.ias.authrt.vo.AuthrtVO;
import incheon.ags.ias.role.service.RoleService;
import incheon.ags.ias.role.vo.RoleSearchVO;
import incheon.ags.ias.role.vo.RoleVO;
import incheon.ags.ias.sys.service.SysService;
import incheon.com.security.annotation.RequireRole;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.egovframe.rte.ptl.mvc.tags.ui.pagination.PaginationInfo;
import org.springframework.stereotype.Controller;
import org.springframework.ui.ModelMap;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.RequestParam;

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

@Controller
@RequiredArgsConstructor
@Slf4j
@RequireRole(system = "AGS", roles = "ROLE_SUPER_ADMIN", description = "통합관리자 역할 접근 제어")
public class RoleController {

    private final RoleService roleService;
    private final SysService sysService;
    private final AuthrtService authrtService;

    @GetMapping("/ags/ias/role/roleList.do")
    public String roleList(
            @RequestParam(defaultValue = "1") int page,
            @ModelAttribute RoleSearchVO roleSearchVO,
            ModelMap model) throws Exception {

        // 최초 진입 시에만 기초데이터 처리 (페이징/검색 시에는 스킵)
        boolean isInitialAccess = page == 1
            && (roleSearchVO.getSearchSysCd() == null || roleSearchVO.getSearchSysCd().isEmpty())
            && (roleSearchVO.getSearchRoleNm() == null || roleSearchVO.getSearchRoleNm().isEmpty())
            && (roleSearchVO.getSearchRoleTypeCd() == null || roleSearchVO.getSearchRoleTypeCd().isEmpty())
            && (roleSearchVO.getUseYn() == null || roleSearchVO.getUseYn().isEmpty());

        if (isInitialAccess) {
            // PERM_MENU_ACCESS 권한 검증 및 자동 생성
            ensurePermMenuAccessForAllSystems();

            // 시스템별 임시역할 검증 및 자동 생성
            ensureTempRolesForAllSystems();

            // 시스템별 업무관리자 역할 검증 및 자동 생성
            ensureSystemAdminRoles();
        }

        roleSearchVO.setPageIndex(page);

        PaginationInfo paginationInfo = new PaginationInfo();
        paginationInfo.setCurrentPageNo(page);
        paginationInfo.setRecordCountPerPage(roleSearchVO.getRecordCountPerPage());
        paginationInfo.setPageSize(roleSearchVO.getPageSize());

        roleSearchVO.setFirstIndex(paginationInfo.getFirstRecordIndex());
        roleSearchVO.setLastIndex(paginationInfo.getLastRecordIndex());
        roleSearchVO.setRecordCountPerPage(paginationInfo.getRecordCountPerPage());

        int totalCount = roleService.selectRoleCnt(roleSearchVO);
        model.addAttribute("totalCount", totalCount);
        paginationInfo.setTotalRecordCount(totalCount);

        List<Map<String, Object>> roleList = roleService.selectRoleList(roleSearchVO);
        model.addAttribute("roleList", roleList);
        model.addAttribute("roleSearchVO", roleSearchVO);
        model.addAttribute("paginationInfo", paginationInfo);

        return "/ags/ias/role/roleList";
    }

    /**
     * 모든 시스템에 대해 임시역할이 있는지 확인하고 없으면 자동 생성
     *
     * 개선: roleTypeCd(ROLTYP999=임시역할)로 존재 여부 체크
     *    - 사용자가 역할 코드를 변경해도 중복 생성 방지
     */
    private void ensureTempRolesForAllSystems() throws Exception {
        // 모든 시스템 조회 (RoleMapper의 selectSysList 사용 - 페이징 없음)
        List<Map<String, Object>> sysList = roleService.selectSysList();

        for (Map<String, Object> sys : sysList) {
            String sysCd = (String) sys.get("sysCd");
            if (sysCd == null) {
                sysCd = (String) sys.get("SYS_CD");
            }

            String sysNm = (String) sys.get("sysNm");
            if (sysNm == null) {
                sysNm = (String) sys.get("SYS_NM");
            }

            if (sysCd != null && !sysCd.trim().isEmpty()) {
                // 임시역할 존재 확인 (시스템 + 권한그룹유형으로 체크)
                RoleVO existingRole = roleService.selectRoleBySysAndType(sysCd, "ROLTYP999");

                // 없으면 생성
                if (existingRole == null) {
                    // 임시역할 코드 생성: ROLE_TMPR_{시스템코드}
                    String tempRoleCd = "ROLE_TMPR_" + sysCd;

                    RoleVO newRole = new RoleVO();
                    newRole.setRoleCd(tempRoleCd);
                    newRole.setRoleNm("임시역할(" + sysNm + ")");
                    newRole.setRoleExpln("임시역할(" + sysNm + ")");
                    newRole.setRoleTypeCd("ROLTYP999");
                    newRole.setSysCd(sysCd);
                    newRole.setUseYn("Y");
                    newRole.setRoleSortSeq(999);
                    newRole.setFrstRegId("SYSTEM");
                    newRole.setLastMdfcnId("SYSTEM");

                    roleService.insertRole(newRole);
                    log.info("임시역할 자동 생성 - roleCd: {}, sysCd: {}", tempRoleCd, sysCd);
                } else {
                    log.debug("임시역할 이미 존재 - sysCd: {}, 기존 roleCd: {}", sysCd, existingRole.getRoleCd());
                }
            }
        }
    }

    /**
     * 모든 시스템에 대해 업무관리자 역할이 있는지 확인하고 없으면 자동 생성
     * ROLE_SUPER_ADMIN 하위에 시스템별 업무관리자 생성 (예: ROLE_AGS_ADMIN)
     *
     * 개선: roleTypeCd(ROLTYP002=업무관리자)로 존재 여부 체크
     *    - 사용자가 역할 코드를 변경해도 중복 생성 방지
     */
    private void ensureSystemAdminRoles() throws Exception {
        // 모든 시스템 조회 (RoleMapper의 selectSysList 사용 - 페이징 없음)
        List<Map<String, Object>> sysList = roleService.selectSysList();

        for (Map<String, Object> sys : sysList) {
            String sysCd = (String) sys.get("sysCd");
            if (sysCd == null) {
                sysCd = (String) sys.get("SYS_CD");
            }

            String sysNm = (String) sys.get("sysNm");
            if (sysNm == null) {
                sysNm = (String) sys.get("SYS_NM");
            }

            if (sysCd != null && sysNm != null && !sysCd.trim().isEmpty() && !sysNm.trim().isEmpty()) {
                // 업무관리자 역할 존재 확인 (시스템 + 권한그룹유형으로 체크)
                RoleVO existingRole = roleService.selectRoleBySysAndType(sysCd, "ROLTYP002");

                // 없으면 생성
                if (existingRole == null) {
                    // 시스템 코드를 직접 사용 (이미 영문 약어임)
                    String sysAbbr = sysCd.trim().toUpperCase();

                    // 업무관리자 역할 코드 생성: ROLE_{시스템코드}_ADMIN
                    String adminRoleCd = "ROLE_" + sysAbbr + "_ADMIN";

                    RoleVO newRole = new RoleVO();
                    newRole.setRoleCd(adminRoleCd);
                    newRole.setRoleNm(sysNm + " 관리자");
                    newRole.setRoleExpln(sysNm + " 시스템 업무관리자");
                    newRole.setRoleTypeCd("ROLTYP002"); // 업무관리자
                    newRole.setSysCd(sysCd);
                    newRole.setUpRoleCd("ROLE_SUPER_ADMIN"); // ROLE_SUPER_ADMIN 하위
                    newRole.setUseYn("Y");
                    newRole.setRoleSortSeq(2); // SUPER_ADMIN(1) 다음
                    newRole.setFrstRegId("SYSTEM");
                    newRole.setLastMdfcnId("SYSTEM");

                    roleService.insertRole(newRole);
                    log.info("시스템 업무관리자 역할 자동 생성 - roleCd: {}, sysCd: {}, sysNm: {}", adminRoleCd, sysCd, sysNm);
                } else {
                    log.debug("시스템 업무관리자 역할 이미 존재 - sysCd: {}, 기존 roleCd: {}", sysCd, existingRole.getRoleCd());
                }
            }
        }
    }

    /**
     * 모든 시스템에 대해 PERM_MENU_ACCESS 권한이 있는지 확인하고 없으면 자동 생성
     */
    private void ensurePermMenuAccessForAllSystems() throws Exception {
        // 모든 시스템 조회 (RoleMapper의 selectSysList 사용 - 페이징 없음)
        List<Map<String, Object>> sysList = roleService.selectSysList();

        for (Map<String, Object> sys : sysList) {
            String sysCd = (String) sys.get("sysCd");
            if (sysCd == null) {
                sysCd = (String) sys.get("SYS_CD");
            }

            if (sysCd != null && !sysCd.trim().isEmpty()) {
                // PERM_MENU_ACCESS 권한 확인
                AuthrtVO checkAuthrt = new AuthrtVO();
                checkAuthrt.setAuthrtCd("PERM_MENU_ACCESS");
                checkAuthrt.setSysCd(sysCd);
                AuthrtVO existingAuthrt = authrtService.selectAuthrtDetail(checkAuthrt);

                // 없으면 생성
                if (existingAuthrt == null) {
                    AuthrtVO newAuthrt = new AuthrtVO();
                    newAuthrt.setAuthrtCd("PERM_MENU_ACCESS");
                    newAuthrt.setAuthrtNm("메뉴 접근 권한");
                    newAuthrt.setAuthrtExpln("메뉴 접근을 위한 기본 권한");
                    newAuthrt.setAuthrtTypeCd("MENU");
                    newAuthrt.setSysCd(sysCd);
                    newAuthrt.setUseYn("Y");
                    newAuthrt.setFrstRegId("SYSTEM");
                    newAuthrt.setLastMdfcnId("SYSTEM");

                    authrtService.insertAuthrt(newAuthrt);
                    log.info("PERM_MENU_ACCESS 권한 자동 생성 - sysCd: {}", sysCd);
                }
            }
        }
    }

    @GetMapping("/ags/ias/role/roleDetail.do")
    public String roleDetail(
            @RequestParam(value = "roleCd", required = false) String roleCd,
            @RequestParam(value = "sysCd", required = false) String sysCd,
            ModelMap model) throws Exception {

        RoleVO vo = new RoleVO();
        vo.setRoleCd(roleCd);
        vo.setSysCd(sysCd);
        RoleVO roleDetail = roleService.selectRoleById(vo);
        model.addAttribute("roleDetail", roleDetail);

        return "ags/ias/role/roleDetail";
    }

    @GetMapping("/ags/ias/role/roleRegist.do")
    public String roleRegist(
            ModelMap model) throws Exception {

        List<Map<String, Object>> sysList = sysService.selectAllSysList();
        model.addAttribute("sysList", sysList);

        return "ags/ias/role/roleRegist";
    }

    @GetMapping("/ags/ias/role/roleModify.do")
    public String roleModify(
            @RequestParam(value = "roleCd", required = false) String roleCd,
            @RequestParam(value = "sysCd", required = false) String sysCd,
            ModelMap model) throws Exception {

        RoleVO vo = new RoleVO();
        vo.setRoleCd(roleCd);
        vo.setSysCd(sysCd);
        RoleVO roleDetail = roleService.selectRoleById(vo);
        model.addAttribute("roleDetail", roleDetail);

        List<Map<String, Object>> sysList = sysService.selectAllSysList();
        model.addAttribute("sysList", sysList);
        return "ags/ias/role/roleModify";
    }
}