package go.kr.project.system.auth.controller;

import egovframework.constant.MessageConstants;
import egovframework.constant.TilesConstants;
import egovframework.util.ApiResponseUtil;
import egovframework.util.SessionUtil;
import go.kr.project.system.auth.model.AuthVO;
import go.kr.project.system.auth.model.GroupRoleVO;
import go.kr.project.system.auth.model.RoleMenuVO;
import go.kr.project.system.auth.service.AuthService;
import go.kr.project.system.group.model.GroupSearchVO;
import go.kr.project.system.group.model.GroupVO;
import go.kr.project.system.menu.model.MenuSearchVO;
import go.kr.project.system.menu.model.MenuVO;
import go.kr.project.system.role.model.RoleSearchVO;
import go.kr.project.system.role.model.RoleVO;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.responses.ApiResponse;
import io.swagger.v3.oas.annotations.responses.ApiResponses;
import io.swagger.v3.oas.annotations.tags.Tag;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.*;

import java.util.List;

/**
 * packageName    : go.kr.project.system.auth.controller
 * fileName       : AuthController
 * author         : 시스템 관리자
 * date           : 2023-06-15
 * description    : 권한 부여 관련 요청을 처리하는 컨트롤러
 * ===========================================================
 * DATE              AUTHOR             NOTE
 * -----------------------------------------------------------
 * 2023-06-15        시스템 관리자       최초 생성
 */
@RequestMapping("/system/auth")
@Controller
@RequiredArgsConstructor
@Slf4j
@Tag(name = "시스템: 권한 관리", description = "권한 관리 관련 API")
public class AuthController {

    private final AuthService authService;

    /**
     * 권한 부여 메인 페이지를 조회합니다.
     * 
     * @param model 뷰에 전달할 데이터를 담는 모델 객체
     * @return 권한 부여 메인 페이지 뷰 이름
     */
    @Operation(summary = "권한 관리 메인 페이지 조회", description = "권한 부여 메인 페이지를 조회합니다.")
    @ApiResponses(value = {
        @ApiResponse(responseCode = "200", description = "권한 관리 페이지 조회 성공")
    })
    @GetMapping("/main.do")
    public String authMain(Model model) {
        return "system/auth/main"+ TilesConstants.BASE;
    }

    /**
     * 역할-메뉴 권한 관리 페이지를 조회합니다.
     * 
     * @param model 뷰에 전달할 데이터를 담는 모델 객체
     * @return 역할-메뉴 권한 관리 페이지 뷰 이름
     */
    @Operation(summary = "역할-메뉴 권한 관리 페이지 조회", description = "역할-메뉴 권한 관리 페이지를 조회합니다.")
    @ApiResponses(value = {
        @ApiResponse(responseCode = "200", description = "역할-메뉴 권한 관리 페이지 조회 성공")
    })
    @GetMapping("/roleMenu.do")
    public String roleMenuManagement(Model model) {
        return "system/auth/roleMenu"+ TilesConstants.BASE;
    }

    /**
     * 그룹-역할 권한 관리 페이지를 조회합니다.
     * 
     * @param model 뷰에 전달할 데이터를 담는 모델 객체
     * @return 그룹-역할 권한 관리 페이지 뷰 이름
     */
    @Operation(summary = "그룹-역할 권한 관리 페이지 조회", description = "그룹-역할 권한 관리 페이지를 조회합니다.")
    @ApiResponses(value = {
        @ApiResponse(responseCode = "200", description = "그룹-역할 권한 관리 페이지 조회 성공")
    })
    @GetMapping("/groupRole.do")
    public String groupRoleManagement(Model model) {
        return "system/auth/groupRole"+ TilesConstants.BASE;
    }

    /**
     * 역할에 할당된 메뉴 목록을 조회하는 AJAX 메소드
     * 
     * @param roleId 역할 ID
     * @return 역할에 할당된 메뉴 목록과 성공 상태를 담은 ResponseEntity 객체
     */
    @Operation(summary = "역할에 할당된 메뉴 목록 조회", description = "특정 역할에 할당된 메뉴 목록을 조회합니다.")
    @ApiResponses(value = {
        @ApiResponse(responseCode = "200", description = "메뉴 목록 조회 성공"),
        @ApiResponse(responseCode = "400", description = "메뉴 목록 조회 실패"),
        @ApiResponse(description = "오류로 인한 실패")
    })
    @PostMapping("/roleMenu/list.ajax")
    public ResponseEntity<?> getRoleMenuListAjax(@RequestParam String roleId) {
        List<RoleMenuVO> roleMenuList = authService.selectRoleMenuList(roleId);
        return ApiResponseUtil.success(roleMenuList);
    }

    /**
     * 역할에 할당되지 않은 메뉴 목록을 조회하는 AJAX 메소드
     * 
     * @param roleId 역할 ID
     * @return 역할에 할당되지 않은 메뉴 목록과 성공 상태를 담은 ResponseEntity 객체
     */
    @Operation(summary = "역할에 할당되지 않은 메뉴 목록 조회", description = "특정 역할에 할당되지 않은 메뉴 목록을 조회합니다.")
    @ApiResponses(value = {
        @ApiResponse(responseCode = "200", description = "메뉴 목록 조회 성공"),
        @ApiResponse(responseCode = "400", description = "메뉴 목록 조회 실패"),
        @ApiResponse(description = "오류로 인한 실패")
    })
    @PostMapping("/roleMenu/unassignedList.ajax")
    public ResponseEntity<?> getUnassignedMenuListAjax(@RequestParam String roleId) {
        List<MenuVO> unassignedMenuList = authService.selectUnassignedMenuList(roleId);
        return ApiResponseUtil.success(unassignedMenuList);
    }

    /**
     * 역할에 메뉴를 할당하는 AJAX 메소드
     * 
     * @param roleId 역할 ID
     * @param menuId 메뉴 ID
     * @return 할당 결과와 성공 상태를 담은 ResponseEntity 객체
     */
    @Operation(summary = "역할에 메뉴 할당", description = "특정 역할에 메뉴를 할당합니다.")
    @ApiResponses(value = {
        @ApiResponse(responseCode = "200", description = "메뉴 할당 성공"),
        @ApiResponse(responseCode = "400", description = "메뉴 할당 실패"),
        @ApiResponse(description = "오류로 인한 실패")
    })
    @PostMapping("/roleMenu/assign.ajax")
    public ResponseEntity<?> assignMenuToRoleAjax(@RequestParam String roleId, @RequestParam String menuId) {
        RoleMenuVO roleMenuVO = new RoleMenuVO();
        roleMenuVO.setRoleId(roleId);
        roleMenuVO.setMenuId(menuId);
        roleMenuVO.setRgtr(SessionUtil.getUserId()); // 실제 구현에서는 로그인한 사용자 정보를 가져와야 함

        int result = authService.insertRoleMenu(roleMenuVO);

        if (result > 0) {
            return ApiResponseUtil.success(MessageConstants.Auth.MENU_ROLE_ASSIGN_SUCCESS);
        } else {
            return ApiResponseUtil.error("메뉴 할당에 실패했습니다.");
        }
    }

    /**
     * 역할에서 메뉴를 제거하는 AJAX 메소드
     * 
     * @param roleId 역할 ID
     * @param menuId 메뉴 ID
     * @return 제거 결과와 성공 상태를 담은 ResponseEntity 객체
     */
    @Operation(summary = "역할에서 메뉴 제거", description = "특정 역할에서 메뉴를 제거합니다.")
    @ApiResponses(value = {
        @ApiResponse(responseCode = "200", description = "메뉴 제거 성공"),
        @ApiResponse(responseCode = "400", description = "메뉴 제거 실패"),
        @ApiResponse(description = "오류로 인한 실패")
    })
    @PostMapping("/roleMenu/remove.ajax")
    public ResponseEntity<?> removeMenuFromRoleAjax(@RequestParam String roleId, @RequestParam String menuId) {
        int result = authService.deleteRoleMenu(roleId, menuId);

        if (result > 0) {
            return ApiResponseUtil.success(MessageConstants.Auth.MENU_ROLE_REMOVE_SUCCESS);
        } else {
            return ApiResponseUtil.error("메뉴 제거에 실패했습니다.");
        }
    }

    /**
     * 역할에 여러 메뉴를 할당하는 AJAX 메소드
     * 
     * @param authVO 권한 정보를 담은 VO 객체
     * @return 할당 결과와 성공 상태를 담은 ResponseEntity 객체
     */
    @Operation(summary = "역할에 여러 메뉴 할당", description = "특정 역할에 여러 메뉴를 한 번에 할당합니다.")
    @ApiResponses(value = {
        @ApiResponse(responseCode = "200", description = "메뉴 할당 성공"),
        @ApiResponse(responseCode = "400", description = "메뉴 할당 실패"),
        @ApiResponse(description = "오류로 인한 실패")
    })
    @PostMapping("/roleMenu/assignMultiple.ajax")
    public ResponseEntity<?> assignMultipleMenusToRoleAjax(@ModelAttribute AuthVO authVO) {
        int result = authService.assignMenusToRole(authVO.getRoleId(), authVO.getMenuIds(), SessionUtil.getUserId());

        if (result >= 0) {
            return ApiResponseUtil.success(MessageConstants.Auth.MENU_ROLE_ASSIGN_SUCCESS);
        } else {
            return ApiResponseUtil.error("메뉴 할당에 실패했습니다.");
        }
    }

    /**
     * 그룹에 할당된 역할 목록을 조회하는 AJAX 메소드
     * 
     * @param groupId 그룹 ID
     * @return 그룹에 할당된 역할 목록과 성공 상태를 담은 ResponseEntity 객체
     */
    @Operation(summary = "그룹에 할당된 역할 목록 조회", description = "특정 그룹에 할당된 역할 목록을 조회합니다.")
    @ApiResponses(value = {
        @ApiResponse(responseCode = "200", description = "역할 목록 조회 성공"),
        @ApiResponse(responseCode = "400", description = "역할 목록 조회 실패"),
        @ApiResponse(description = "오류로 인한 실패")
    })
    @PostMapping("/groupRole/list.ajax")
    public ResponseEntity<?> getGroupRoleListAjax(@RequestParam String groupId) {
        List<GroupRoleVO> groupRoleList = authService.selectGroupRoleList(groupId);
        return ApiResponseUtil.success(groupRoleList);
    }

    /**
     * 그룹에 할당되지 않은 역할 목록을 조회하는 AJAX 메소드
     * 
     * @param groupId 그룹 ID
     * @return 그룹에 할당되지 않은 역할 목록과 성공 상태를 담은 ResponseEntity 객체
     */
    @Operation(summary = "그룹에 할당되지 않은 역할 목록 조회", description = "특정 그룹에 할당되지 않은 역할 목록을 조회합니다.")
    @ApiResponses(value = {
        @ApiResponse(responseCode = "200", description = "역할 목록 조회 성공"),
        @ApiResponse(responseCode = "400", description = "역할 목록 조회 실패"),
        @ApiResponse(description = "오류로 인한 실패")
    })
    @PostMapping("/groupRole/unassignedList.ajax")
    public ResponseEntity<?> getUnassignedRoleListAjax(@RequestParam String groupId) {
        List<RoleVO> unassignedRoleList = authService.selectUnassignedRoleList(groupId);
        return ApiResponseUtil.success(unassignedRoleList);
    }

    /**
     * 그룹에 역할을 할당하는 AJAX 메소드
     * 
     * @param groupId 그룹 ID
     * @param roleId 역할 ID
     * @return 할당 결과와 성공 상태를 담은 ResponseEntity 객체
     */
    @Operation(summary = "그룹에 역할 할당", description = "특정 그룹에 역할을 할당합니다.")
    @ApiResponses(value = {
        @ApiResponse(responseCode = "200", description = "역할 할당 성공"),
        @ApiResponse(responseCode = "400", description = "역할 할당 실패"),
        @ApiResponse(description = "오류로 인한 실패")
    })
    @PostMapping("/groupRole/assign.ajax")
    public ResponseEntity<?> assignRoleToGroupAjax(@RequestParam String groupId, @RequestParam String roleId) {
        GroupRoleVO groupRoleVO = new GroupRoleVO();
        groupRoleVO.setGroupId(groupId);
        groupRoleVO.setRoleId(roleId);
        groupRoleVO.setRgtr(SessionUtil.getUserId());

        int result = authService.insertGroupRole(groupRoleVO);

        if (result > 0) {
            return ApiResponseUtil.success(MessageConstants.Auth.ROLE_GROUP_ASSIGN_SUCCESS);
        } else {
            return ApiResponseUtil.error("역할 할당에 실패했습니다.");
        }
    }

    /**
     * 그룹에서 역할을 제거하는 AJAX 메소드
     * 
     * @param groupId 그룹 ID
     * @param roleId 역할 ID
     * @return 제거 결과와 성공 상태를 담은 ResponseEntity 객체
     */
    @Operation(summary = "그룹에서 역할 제거", description = "특정 그룹에서 역할을 제거합니다.")
    @ApiResponses(value = {
        @ApiResponse(responseCode = "200", description = "역할 제거 성공"),
        @ApiResponse(responseCode = "400", description = "역할 제거 실패"),
        @ApiResponse(description = "오류로 인한 실패")
    })
    @PostMapping("/groupRole/remove.ajax")
    public ResponseEntity<?> removeRoleFromGroupAjax(@RequestParam String groupId, @RequestParam String roleId) {
        int result = authService.deleteGroupRole(groupId, roleId);

        if (result > 0) {
            return ApiResponseUtil.success(MessageConstants.Auth.ROLE_GROUP_REMOVE_SUCCESS);
        } else {
            return ApiResponseUtil.error("역할 제거에 실패했습니다.");
        }
    }

    /**
     * 그룹에 여러 역할을 할당하는 AJAX 메소드
     * 
     * @param authVO 권한 정보를 담은 VO 객체
     * @return 할당 결과와 성공 상태를 담은 ResponseEntity 객체
     */
    @Operation(summary = "그룹에 여러 역할 할당", description = "특정 그룹에 여러 역할을 한 번에 할당합니다.")
    @ApiResponses(value = {
        @ApiResponse(responseCode = "200", description = "역할 할당 성공"),
        @ApiResponse(responseCode = "400", description = "역할 할당 실패"),
        @ApiResponse(description = "오류로 인한 실패")
    })
    @PostMapping("/groupRole/assignMultiple.ajax")
    public ResponseEntity<?> assignMultipleRolesToGroupAjax(@ModelAttribute AuthVO authVO) {
        int result = authService.assignRolesToGroup(authVO.getGroupId(), authVO.getRoleIds(), SessionUtil.getUserId());

        if (result >= 0) {
            return ApiResponseUtil.success(MessageConstants.Auth.ROLE_GROUP_ASSIGN_SUCCESS);
        } else {
            return ApiResponseUtil.error("역할 할당에 실패했습니다.");
        }
    }

    /**
     * 그룹 목록을 조회하는 AJAX 메소드
     * 
     * @param paramVO 검색 조건을 담은 VO 객체
     * @return 그룹 목록과 성공 상태를 담은 ResponseEntity 객체
     */
    @Operation(summary = "그룹 목록 조회", description = "그룹 목록을 조회합니다.")
    @ApiResponses(value = {
        @ApiResponse(responseCode = "200", description = "그룹 목록 조회 성공"),
        @ApiResponse(responseCode = "400", description = "그룹 목록 조회 실패"),
        @ApiResponse(description = "오류로 인한 실패")
    })
    @PostMapping("/group/list.ajax")
    public ResponseEntity<?> getGroupListAjax(@ModelAttribute GroupSearchVO paramVO) {

        // 그룹 목록 조회
        List<GroupVO> groupList = authService.selectGroupList(paramVO);
        return ApiResponseUtil.success(groupList);
    }

    /**
     * 역할 목록을 조회하는 AJAX 메소드
     * 
     * @param paramVO 검색 조건을 담은 VO 객체
     * @return 역할 목록과 성공 상태를 담은 ResponseEntity 객체
     */
    @Operation(summary = "역할 목록 조회", description = "역할 목록을 조회합니다.")
    @ApiResponses(value = {
        @ApiResponse(responseCode = "200", description = "역할 목록 조회 성공"),
        @ApiResponse(responseCode = "400", description = "역할 목록 조회 실패"),
        @ApiResponse(description = "오류로 인한 실패")
    })
    @PostMapping("/role/list.ajax")
    public ResponseEntity<?> getRoleListAjax(@ModelAttribute RoleSearchVO paramVO) {

        // 역할 목록 조회
        List<RoleVO> roleList = authService.selectRoleList(paramVO);
        return ApiResponseUtil.success(roleList);
    }

    /**
     * 메뉴 목록을 조회하는 AJAX 메소드
     * 
     * @param paramVO 검색 조건을 담은 VO 객체
     * @return 메뉴 목록과 성공 상태를 담은 ResponseEntity 객체
     */
    @Operation(summary = "메뉴 목록 조회", description = "메뉴 목록을 조회합니다.")
    @ApiResponses(value = {
        @ApiResponse(responseCode = "200", description = "메뉴 목록 조회 성공"),
        @ApiResponse(responseCode = "400", description = "메뉴 목록 조회 실패"),
        @ApiResponse(description = "오류로 인한 실패")
    })
    @PostMapping("/menu/list.ajax")
    public ResponseEntity<?> getMenuListAjax(@ModelAttribute MenuSearchVO paramVO) {

        // 메뉴 목록 조회
        List<MenuVO> menuList = authService.selectMenuList(paramVO);
        return ApiResponseUtil.success(menuList);
    }
}
