package incheon.ags.ias.comCd.web;

import incheon.ags.ias.comCd.service.ComCdService;
import incheon.ags.ias.comCd.vo.ComCdVO;
import incheon.ags.ias.comCd.vo.ComGroupCdVO;
import incheon.ags.ias.comCd.web.dto.ComCdRequestDTO;
import incheon.ags.ias.comCd.web.dto.ComGroupCdRequestDTO;
import incheon.com.cmm.api.DefaultApiResponse;
import incheon.com.cmm.exception.EntityNotFoundException;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.tags.Tag;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.http.ResponseEntity;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;

import javax.validation.Valid;
import java.util.List;

/**
 * 공통코드 REST API Controller
 * Base URL: /api/v1/comCd
 */
@Tag(name = "공통코드 API", description = "공통코드(그룹코드 + 상세코드) 관리 API")
@Slf4j
@RestController
@RequestMapping("/api/v1/comCd")
@RequiredArgsConstructor
@Validated
public class ComCdApiController {

    private final ComCdService comCdService;

    /* ========================================
     * 그룹코드 관련 API
     * ======================================== */

    /**
     * 1.0 그룹코드 목록 조회
     * GET /api/v1/comCd/group/list
     */
    @Operation(summary = "그룹코드 목록 조회", description = "전체 그룹코드 목록을 조회합니다")
    @GetMapping("/group/list")
    public ResponseEntity<List<ComGroupCdVO>> getComGroupCdList() throws Exception {
        ComGroupCdVO searchVO = new ComGroupCdVO();
        searchVO.setRecordCountPerPage(1000); // 전체 조회
        searchVO.setFirstIndex(0);

        List<ComGroupCdVO> result = comCdService.selectComGroupCdList(searchVO);
        return ResponseEntity.ok(result);
    }

    /**
     * 1.1 그룹코드별 상세코드 목록 조회 (일반용 - 순수 공통코드만)
     * GET /api/v1/comCd/groupCd/{groupCd}
     */
    @Operation(summary = "그룹코드별 상세코드 목록 조회", description = "특정 그룹코드에 속한 모든 상세코드를 조회합니다 (COM_CD 테이블만)")
    @GetMapping("/groupCd/{groupCd}")
    public ResponseEntity<List<ComCdVO>> getComCdByGroupCd(
            @Parameter(description = "그룹코드", required = true, example = "TRMS_STCD")
            @PathVariable String groupCd) throws Exception {

        List<ComCdVO> result = comCdService.getComCdByGroupCd(groupCd);
        return ResponseEntity.ok(result);
    }

    /**
     * 1.1-1 그룹코드별 상세코드 목록 조회 (뷰용 - 시스템코드 포함)
     * GET /api/v1/comCd/view/groupCd/{groupCd}
     */
    @Operation(summary = "그룹코드별 상세코드 목록 조회 (뷰용)",
               description = "그룹코드가 'SYS_CD'인 경우 SYS 테이블 데이터를 반환하고, 그 외는 일반 공통코드를 반환합니다")
    @GetMapping("/view/groupCd/{groupCd}")
    public ResponseEntity<List<ComCdVO>> getComCdByGroupCdForView(
            @Parameter(description = "그룹코드", required = true, example = "SYS_CD")
            @PathVariable String groupCd) throws Exception {

        List<ComCdVO> result;

        // 시스템 코드인 경우 SYS 테이블에서 조회
        if ("SYS_CD".equals(groupCd)) {
            result = comCdService.getSystemCodeList();
        } else {
            // 일반 공통코드
            result = comCdService.getComCdByGroupCd(groupCd);
        }

        return ResponseEntity.ok(result);
    }

    /**
     * 1.2 그룹코드 등록
     * POST /api/v1/comCd/group
     */
    @Operation(summary = "그룹코드 등록", description = "새로운 그룹코드를 등록합니다")
    @PostMapping("/group")
    public ResponseEntity<DefaultApiResponse<Object>> insertComGroupCd(
            @Valid @RequestBody ComGroupCdRequestDTO dto) throws Exception {

        ComGroupCdVO vo = dto.toEntity();
        comCdService.insertComGroupCd(vo);
        return ResponseEntity.ok(DefaultApiResponse.success(null, "그룹코드가 등록되었습니다."));
    }

    /**
     * 1.3 그룹코드 수정
     * PUT /api/v1/comCd/group/{groupCd}
     */
    @Operation(summary = "그룹코드 수정", description = "기존 그룹코드를 수정합니다")
    @PutMapping("/group/{groupCd}")
    public ResponseEntity<DefaultApiResponse<Object>> updateGroupCd(
            @Parameter(description = "그룹코드", required = true, example = "MENU_TYPE")
            @PathVariable String groupCd,
            @Valid @RequestBody ComGroupCdRequestDTO dto) throws Exception {

        // 존재 여부 확인
        ComGroupCdVO existingGroupCd = comCdService.selectComGroupCdDetail(groupCd);
        if (existingGroupCd == null) {
            throw new EntityNotFoundException("공통그룹코드");
        }

        // 수정
        ComGroupCdVO vo = dto.toEntity();
        vo.setGroupCd(groupCd);  // Path Variable의 groupCd로 설정
        comCdService.updateComGroupCd(vo);

        return ResponseEntity.ok(DefaultApiResponse.success(null, "그룹코드가 수정되었습니다."));
    }

    /**
     * 1.4 그룹코드 삭제
     * DELETE /api/v1/comCd/group/{groupCd}
     */
    @Operation(summary = "그룹코드 삭제", description = "그룹코드를 삭제합니다 (하위 상세코드가 없어야 함)")
    @DeleteMapping("/group/{groupCd}")
    public ResponseEntity<DefaultApiResponse<Object>> deleteGroupCd(
            @Parameter(description = "그룹코드", required = true, example = "MENU_TYPE")
            @PathVariable String groupCd) throws Exception {

        // 존재 여부 확인
        ComGroupCdVO existingCd = comCdService.selectComGroupCdDetail(groupCd);
        if (existingCd == null) {
            throw new EntityNotFoundException("공통그룹코드");
        }

        comCdService.deleteComGroupCd(groupCd);
        return ResponseEntity.ok(DefaultApiResponse.success(null, "그룹코드가 삭제되었습니다."));
    }

    /* ========================================
     * 상세코드 관련 API
     * ======================================== */

    /**
     * 2.2 상세코드 단건 조회
     * GET /api/v1/comCd/{groupCd}/{cd}
     */
    @Operation(summary = "상세코드 단건 조회", description = "특정 상세코드의 상세 정보를 조회합니다")
    @GetMapping("/{groupCd}/{cd}")
    public ResponseEntity<ComCdVO> getComCdDetail(
            @Parameter(description = "그룹코드", required = true, example = "TRMS_STCD")
            @PathVariable String groupCd,
            @Parameter(description = "상세코드", required = true, example = "A")
            @PathVariable String cd) throws Exception {

        ComCdVO result = comCdService.getComCdDetail(groupCd, cd);
        if (result == null) {
            throw new EntityNotFoundException("상세코드");
        }

        return ResponseEntity.ok(result);
    }

    /**
     * 2.3 상세코드 등록
     * POST /api/v1/comCd
     */
    @Operation(summary = "상세코드 등록", description = "새로운 상세코드를 등록합니다")
    @PostMapping
    public ResponseEntity<DefaultApiResponse<Object>> insertComCd(
            @Valid @RequestBody ComCdRequestDTO dto) throws Exception {

        ComCdVO vo = dto.toEntity();
        comCdService.insertComCd(vo);
        return ResponseEntity.ok(DefaultApiResponse.success(null, "상세코드가 등록되었습니다."));
    }

    /**
     * 2.4 상세코드 수정
     * PUT /api/v1/comCd/{groupCd}/{cd}
     */
    @Operation(summary = "상세코드 수정", description = "기존 상세코드를 수정합니다 (PK는 수정 불가)")
    @PutMapping("/{groupCd}/{cd}")
    public ResponseEntity<DefaultApiResponse<Object>> updateComCd(
            @Parameter(description = "그룹코드", required = true, example = "TRMS_STCD")
            @PathVariable String groupCd,
            @Parameter(description = "상세코드", required = true, example = "A")
            @PathVariable String cd,
            @Valid @RequestBody ComCdRequestDTO dto) throws Exception {

        // 존재 여부 확인
        ComCdVO existingData = comCdService.getComCdDetail(groupCd, cd);
        if (existingData == null) {
            throw new EntityNotFoundException("상세코드");
        }

        // 수정 (PK는 Path Variable에서 가져옴)
        ComCdVO vo = dto.toEntity();
        vo.setGroupCd(groupCd);
        vo.setCd(cd);
        comCdService.updateComCd(vo);

        return ResponseEntity.ok(DefaultApiResponse.success(null, "상세코드가 수정되었습니다."));
    }

    /**
     * 2.5 상세코드 삭제
     * DELETE /api/v1/comCd/{groupCd}/{cd}
     */
    @Operation(summary = "상세코드 삭제", description = "상세코드를 삭제합니다")
    @DeleteMapping("/{groupCd}/{cd}")
    public ResponseEntity<DefaultApiResponse<Object>> deleteComCd(
            @Parameter(description = "그룹코드", required = true, example = "TRMS_STCD")
            @PathVariable String groupCd,
            @Parameter(description = "상세코드", required = true, example = "A")
            @PathVariable String cd) throws Exception {

        int deleteResult = comCdService.deleteComCd(cd, groupCd);
        if (deleteResult == 0) {
            throw new EntityNotFoundException("상세코드");
        }

        return ResponseEntity.ok(DefaultApiResponse.success(null, "상세코드가 삭제되었습니다."));
    }

}
