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

import egovframework.constant.MessageConstants;
import egovframework.constant.TilesConstants;
import egovframework.util.ApiResponseUtil;
import go.kr.project.system.code.model.*;
import go.kr.project.system.code.service.CodeService;
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.code.controller
 * fileName       : CodeController
 * author         : 개발자
 * date           : 2025-05-09
 * description    : 공통 코드 관련 요청을 처리하는 컨트롤러
 * ===========================================================
 * DATE              AUTHOR             NOTE
 * -----------------------------------------------------------
 * 2025-05-09        개발자       최초 생성
 * 2025-05-13        개발자       CodeMaster를 CodeGroup으로 변경
 */
@RequestMapping("/system/code")
@Controller
@RequiredArgsConstructor
@Slf4j
@Tag(name = "시스템: 코드 관리", description = "코드 관리 관련 API")
public class CodeController {

    private final CodeService codeService;

    /**
     * 코드 그룹 목록을 조회하는 AJAX 메소드
     * 
     * @param paramVO 검색 조건을 담은 VO 객체
     * @return 코드 그룹 목록과 성공 상태를 담은 ResponseEntity 객체
     * @throws Exception 조회 중 발생할 수 있는 예외
     */
    @Operation(summary = "코드 그룹 목록 조회", description = "코드 그룹 목록을 조회합니다.")
    @ApiResponses(value = {
        @ApiResponse(responseCode = "200", description = "코드 그룹 목록 조회 성공"),
        @ApiResponse(responseCode = "400", description = "코드 그룹 목록 조회 실패"),
        @ApiResponse(description = "오류로 인한 실패")
    })
    @PostMapping("/group/list.ajax")
    public ResponseEntity<?> getCodeGroupListAjax(@ModelAttribute CodeSearchVO paramVO) {
        // 총 코드 그룹 수 조회
        int totalCount = codeService.selectCodeGroupListTotalCount(paramVO);
        paramVO.setTotalCount(totalCount);

        // 페이징 처리를 위한 설정
        paramVO.setPagingYn("Y");

        // 페이징 처리된 코드 그룹 목록 조회
        List<CodeGroupVO> codeGroupList = codeService.selectCodeGroupList(paramVO);
        return ApiResponseUtil.successWithGrid(codeGroupList, paramVO);
    }

    /**
     * 코드 상세 목록을 조회하는 AJAX 메소드
     * 
     * @param paramVO 검색 조건을 담은 VO 객체
     * @return 코드 상세 목록과 성공 상태를 담은 ResponseEntity 객체
     * @throws Exception 조회 중 발생할 수 있는 예외
     */
    @Operation(summary = "코드 상세 목록 조회", description = "코드 상세 목록을 조회합니다.")
    @ApiResponses(value = {
        @ApiResponse(responseCode = "200", description = "코드 상세 목록 조회 성공"),
        @ApiResponse(responseCode = "400", description = "코드 상세 목록 조회 실패"),
        @ApiResponse(description = "오류로 인한 실패")
    })
    @PostMapping("/detail/list.ajax")
    public ResponseEntity<?> getCodeDetailListAjax(@ModelAttribute CodeSearchVO paramVO) {
        // 총 코드 상세 수 조회
        int totalCount = codeService.selectCodeDetailListTotalCount(paramVO);
        paramVO.setTotalCount(totalCount);

        // 페이징 처리된 코드 상세 목록 조회
        List<CodeDetailVO> codeDetailList = codeService.selectCodeDetailList(paramVO);
        return ApiResponseUtil.successWithGrid(codeDetailList, paramVO);
    }

    /**
     * 코드 상세 정보를 일괄 저장하는 AJAX 메소드
     * 생성, 수정, 삭제된 코드 상세 데이터를 처리합니다.
     * 공통 응답 형식(ApiResponse)을 사용하여 응답합니다.
     *
     * @param modifyData 생성/수정/삭제할 코드 상세 정보를 담은 VO 객체
     * @return 저장 결과 메시지와 성공/실패 상태를 담은 ResponseEntity 객체
     */
    @Operation(summary = "코드 상세 정보 일괄 저장", description = "생성, 수정, 삭제된 코드 상세 데이터를 일괄 처리합니다.")
    @ApiResponses(value = {
        @ApiResponse(responseCode = "200", description = "코드 상세 정보 저장 성공"),
        @ApiResponse(responseCode = "400", description = "코드 상세 정보 저장 실패"),
        @ApiResponse(description = "오류로 인한 실패")
    })
    @PostMapping("/detail/saveAll.ajax")
    public ResponseEntity<?> saveAllDetailAjax(@RequestBody CodeDetailModifiedDataVO modifyData) {
        // 신규 등록 데이터에 대한 중복 체크
        List<CodeDetailVO> createdRows = modifyData.getCreatedRows();
        if (createdRows != null && !createdRows.isEmpty()) {
            for (CodeDetailVO codeDetailVO : createdRows) {
                // 코드ID 중복 체크
                if (codeService.isCodeDetailDuplicated(codeDetailVO)) {
                    return ApiResponseUtil.error("이미 존재하는 상세코드ID입니다: " + codeDetailVO.getCdId());
                }
            }
        }

        int result = codeService.saveCodeDetails(modifyData);
        if (result > 0) {
            return ApiResponseUtil.success(MessageConstants.Code.DETAIL_SAVE_SUCCESS);
        } else {
            return ApiResponseUtil.error("코드 상세 정보 저장에 실패했습니다.");
        }
    }

    /**
     * 코드 통합 관리 페이지를 조회합니다.
     * 
     * @param model 뷰에 전달할 데이터를 담는 모델 객체
     * @return 코드 통합 관리 페이지 뷰 이름
     * @throws Exception 조회 중 발생할 수 있는 예외
     */
    @Operation(summary = "코드 통합 관리 페이지 조회", description = "코드 통합 관리 페이지를 조회합니다.")
    @ApiResponses(value = {
        @ApiResponse(responseCode = "200", description = "코드 통합 관리 페이지 조회 성공")
    })
    @GetMapping("/integrated/manage.do")
    public String codeIntegratedManage(Model model) {
        return "system/code/integrated/manage"+ TilesConstants.BASE;
    }

    /**
     * 코드 그룹 정보를 일괄 저장하는 AJAX 메소드
     * 생성, 수정, 삭제된 코드 그룹 데이터를 처리합니다.
     * 공통 응답 형식(ApiResponse)을 사용하여 응답합니다.
     *
     * @param modifyData 생성/수정/삭제할 코드 그룹 정보를 담은 VO 객체
     * @return 저장 결과 메시지와 성공/실패 상태를 담은 ResponseEntity 객체
     */
    @Operation(summary = "코드 그룹 정보 일괄 저장", description = "생성, 수정, 삭제된 코드 그룹 데이터를 일괄 처리합니다.")
    @ApiResponses(value = {
        @ApiResponse(responseCode = "200", description = "코드 그룹 정보 저장 성공"),
        @ApiResponse(responseCode = "400", description = "코드 그룹 정보 저장 실패"),
        @ApiResponse(description = "오류로 인한 실패")
    })
    @PostMapping("/group/saveAll.ajax")
    public ResponseEntity<?> saveAllGroupAjax(@RequestBody CodeGroupModifiedDataVO modifyData) {
        int result = codeService.saveCodeGroups(modifyData);
        if (result > 0) {
            return ApiResponseUtil.success(MessageConstants.Code.GROUP_SAVE_SUCCESS);
        } else {
            return ApiResponseUtil.error("그룹코드 정보 저장에 실패했습니다.");
        }
    }
}
