package com.bio.bio_backend.domain.admin.common_code.controller;

import com.bio.bio_backend.domain.admin.common_code.dto.*;
import com.bio.bio_backend.domain.admin.common_code.service.CommonCodeService;
import com.bio.bio_backend.domain.admin.common_code.mapper.CommonCodeMapper;
import com.bio.bio_backend.domain.admin.common_code.mapper.CommonGroupCodeMapper;
import com.bio.bio_backend.global.dto.ApiResponseDto;
import com.bio.bio_backend.global.constants.ApiResponseCode;
import com.bio.bio_backend.global.annotation.LogExecution;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import io.swagger.v3.oas.annotations.responses.ApiResponse;
import io.swagger.v3.oas.annotations.responses.ApiResponses;
import io.swagger.v3.oas.annotations.media.Content;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;

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

@Slf4j
@RestController
@RequestMapping("/admin/common-codes")
@RequiredArgsConstructor
@Tag(name = "공통 코드 관리", description = "공통 코드 및 그룹 코드 관리 API")
public class CommonCodeController {
    
    private final CommonCodeService commonCodeService;
    private final CommonCodeMapper commonCodeMapper;
    private final CommonGroupCodeMapper commonGroupCodeMapper;
    
    // 그룹 코드 관련 API
    @LogExecution("그룹 코드 생성")
    @Operation(summary = "그룹 코드 생성", description = "새로운 그룹 코드를 생성합니다.")
    @ApiResponses({
        @ApiResponse(responseCode = "201", description = "그룹 코드 생성 성공"),
        @ApiResponse(responseCode = "400", description = "잘못된 요청 데이터", content = @Content),
        @ApiResponse(responseCode = "409", description = "중복된 그룹 코드", content = @Content)
    })
    @PostMapping("/group")
    public ResponseEntity<ApiResponseDto<CreateCommonGroupCodeResponseDto>> createGroupCode(@RequestBody @Valid CreateCommonGroupCodeRequestDto requestDto) {
        CommonGroupCodeDto groupCodeDto = commonGroupCodeMapper.toCommonGroupCodeDto(requestDto);
        CommonGroupCodeDto createdGroupCode = commonCodeService.createGroupCode(groupCodeDto);
        CreateCommonGroupCodeResponseDto responseDto = commonGroupCodeMapper.toCreateCommonGroupCodeResponseDto(createdGroupCode);
        ApiResponseDto<CreateCommonGroupCodeResponseDto> apiResponse = ApiResponseDto.success(ApiResponseCode.COMMON_SUCCESS_CREATED, responseDto);
        
        return ResponseEntity.status(HttpStatus.CREATED).body(apiResponse);
    }
    
    @LogExecution("그룹 코드 수정")
    @Operation(summary = "그룹 코드 수정", description = "기존 그룹 코드를 수정합니다.")
    @ApiResponses({
        @ApiResponse(responseCode = "200", description = "그룹 코드 수정 성공"),
        @ApiResponse(responseCode = "400", description = "잘못된 요청 데이터", content = @Content),
        @ApiResponse(responseCode = "404", description = "그룹 코드를 찾을 수 없음", content = @Content)
    })
    @PutMapping("/group/{code}")
    public ResponseEntity<ApiResponseDto<String>> updateGroupCode(
            @PathVariable String code, 
            @RequestBody @Valid UpdateCommonGroupCodeRequestDto requestDto) {
        CommonGroupCodeDto groupCodeDto = commonGroupCodeMapper.toCommonGroupCodeDto(requestDto);
        commonCodeService.updateGroupCode(code, groupCodeDto);
        return ResponseEntity.ok(ApiResponseDto.success(ApiResponseCode.COMMON_SUCCESS_UPDATED));
    }
    
    @LogExecution("그룹 코드 삭제")
    @Operation(summary = "그룹 코드 삭제", description = "그룹 코드를 삭제합니다.")
    @ApiResponses({
        @ApiResponse(responseCode = "200", description = "그룹 코드 삭제 성공"),
        @ApiResponse(responseCode = "400", description = "하위 공통 코드가 존재하여 삭제할 수 없음", content = @Content),
        @ApiResponse(responseCode = "404", description = "그룹 코드를 찾을 수 없음", content = @Content)
    })
    @DeleteMapping("/group/{code}")
    public ResponseEntity<ApiResponseDto<Void>> deleteGroupCode(@PathVariable String code) {
        commonCodeService.deleteGroupCode(code);
        return ResponseEntity.ok(ApiResponseDto.success(ApiResponseCode.COMMON_SUCCESS_DELETED));
    }
    
    @LogExecution("그룹 코드 조회")
    @Operation(summary = "그룹 코드 조회", description = "특정 그룹 코드를 조회합니다.")
    @ApiResponses({
        @ApiResponse(responseCode = "200", description = "그룹 코드 조회 성공"),
        @ApiResponse(responseCode = "404", description = "그룹 코드를 찾을 수 없음", content = @Content)
    })
    @GetMapping("/group/{code}")
    public ResponseEntity<ApiResponseDto<CommonGroupCodeDto>> getGroupCode(@PathVariable String code) {
        CommonGroupCodeDto groupCode = commonCodeService.getGroupCode(code);
        return ResponseEntity.ok(ApiResponseDto.success(ApiResponseCode.COMMON_SUCCESS_RETRIEVED, groupCode));
    }
    
    @LogExecution("전체 그룹 코드 조회")
    @Operation(summary = "전체 그룹 코드 조회", description = "모든 그룹 코드를 조회합니다.")
    @ApiResponses({
        @ApiResponse(responseCode = "200", description = "전체 그룹 코드 조회 성공")
    })
    @GetMapping("/group")
    public ResponseEntity<ApiResponseDto<List<CommonGroupCodeDto>>> getAllGroupCodes() {
        List<CommonGroupCodeDto> groupCodes = commonCodeService.getAllGroupCodes();
        return ResponseEntity.ok(ApiResponseDto.success(ApiResponseCode.COMMON_SUCCESS_RETRIEVED, groupCodes));
    }
    
    @LogExecution("활성 그룹 코드 조회")
    @Operation(summary = "활성 그룹 코드 조회", description = "사용 중인 그룹 코드만 조회합니다.")
    @ApiResponses({
        @ApiResponse(responseCode = "200", description = "활성 그룹 코드 조회 성공")
    })
    @GetMapping("/group/active")
    public ResponseEntity<ApiResponseDto<List<CommonGroupCodeDto>>> getActiveGroupCodes() {
        List<CommonGroupCodeDto> groupCodes = commonCodeService.getActiveGroupCodes();
        return ResponseEntity.ok(ApiResponseDto.success(ApiResponseCode.COMMON_SUCCESS_RETRIEVED, groupCodes));
    }
    
    // 공통 코드 관련 API
    @LogExecution("공통 코드 생성")
    @Operation(summary = "공통 코드 생성", description = "새로운 공통 코드를 생성합니다.")
    @ApiResponses({
        @ApiResponse(responseCode = "201", description = "공통 코드 생성 성공"),
        @ApiResponse(responseCode = "400", description = "잘못된 요청 데이터", content = @Content),
        @ApiResponse(responseCode = "409", description = "중복된 공통 코드", content = @Content)
    })
    @PostMapping
    public ResponseEntity<ApiResponseDto<CreateCommonCodeResponseDto>> createCode(@RequestBody @Valid CreateCommonCodeRequestDto requestDto) {
        CommonCodeDto commonCodeDto = commonCodeMapper.toCommonCodeDto(requestDto);
        CommonCodeDto createdCommonCode = commonCodeService.createCode(commonCodeDto);
        CreateCommonCodeResponseDto responseDto = commonCodeMapper.toCreateCommonCodeResponseDto(createdCommonCode);
        ApiResponseDto<CreateCommonCodeResponseDto> apiResponse = ApiResponseDto.success(ApiResponseCode.COMMON_SUCCESS_CREATED, responseDto);
        
        return ResponseEntity.status(HttpStatus.CREATED).body(apiResponse);
    }
    
    @LogExecution("공통 코드 수정")
    @Operation(summary = "공통 코드 수정", description = "기존 공통 코드를 수정합니다.")
    @ApiResponses({
        @ApiResponse(responseCode = "200", description = "공통 코드 수정 성공"),
        @ApiResponse(responseCode = "400", description = "잘못된 요청 데이터", content = @Content),
        @ApiResponse(responseCode = "404", description = "공통 코드를 찾을 수 없음", content = @Content)
    })
    @PutMapping("/{code}")
    public ResponseEntity<ApiResponseDto<String>> updateCode(
            @PathVariable String code, 
            @RequestBody @Valid UpdateCommonCodeRequestDto requestDto) {
        CommonCodeDto commonCodeDto = commonCodeMapper.toCommonCodeDto(requestDto);
        commonCodeService.updateCode(code, commonCodeDto);
        return ResponseEntity.ok(ApiResponseDto.success(ApiResponseCode.COMMON_SUCCESS_UPDATED));
    }
    
    @LogExecution("공통 코드 삭제")
    @Operation(summary = "공통 코드 삭제", description = "공통 코드를 삭제합니다.")
    @ApiResponses({
        @ApiResponse(responseCode = "200", description = "공통 코드 삭제 성공"),
        @ApiResponse(responseCode = "400", description = "하위 공통 코드가 존재하여 삭제할 수 없음", content = @Content),
        @ApiResponse(responseCode = "404", description = "공통 코드를 찾을 수 없음", content = @Content)
    })
    @DeleteMapping("/{code}")
    public ResponseEntity<ApiResponseDto<Void>> deleteCode(@PathVariable String code) {
        commonCodeService.deleteCode(code);
        return ResponseEntity.ok(ApiResponseDto.success(ApiResponseCode.COMMON_SUCCESS_DELETED));
    }
    
    @LogExecution("공통 코드 조회")
    @Operation(summary = "공통 코드 조회", description = "특정 공통 코드를 조회합니다.")
    @ApiResponses({
        @ApiResponse(responseCode = "200", description = "공통 코드 조회 성공"),
        @ApiResponse(responseCode = "404", description = "공통 코드를 찾을 수 없음", content = @Content)
    })
    @GetMapping("/{code}")
    public ResponseEntity<ApiResponseDto<GetCommonCodeResponseDto>> getCode(@PathVariable String code) {
        GetCommonCodeResponseDto commonCode = commonCodeService.getCodeWithJoinInfo(code);
        return ResponseEntity.ok(ApiResponseDto.success(ApiResponseCode.COMMON_SUCCESS_RETRIEVED, commonCode));
    }
    
    @LogExecution("그룹별 공통 코드 조회")
    @Operation(summary = "그룹별 공통 코드 조회", description = "특정 그룹에 속한 공통 코드들을 조회합니다.")
    @ApiResponses({
        @ApiResponse(responseCode = "200", description = "그룹별 공통 코드 조회 성공")
    })
    @GetMapping("/group/{groupCode}/codes")
    public ResponseEntity<ApiResponseDto<List<CommonCodeDto>>> getCodesByGroupCode(@PathVariable String groupCode) {
        List<CommonCodeDto> commonCodes = commonCodeService.getActiveCodesByGroupCode(groupCode);
        return ResponseEntity.ok(ApiResponseDto.success(ApiResponseCode.COMMON_SUCCESS_RETRIEVED, commonCodes));
    }
    
    @LogExecution("상위 코드별 공통 코드 조회")
    @Operation(summary = "상위 코드별 공통 코드 조회", description = "특정 상위 코드에 속한 공통 코드들을 조회합니다.")
    @ApiResponses({
        @ApiResponse(responseCode = "200", description = "상위 코드별 공통 코드 조회 성공")
    })
    @GetMapping("/parent/{parentCode}/codes")
    public ResponseEntity<ApiResponseDto<List<CommonCodeDto>>> getCodesByParentCode(@PathVariable String parentCode) {
        List<CommonCodeDto> commonCodes = commonCodeService.getActiveCodesByParentCode(parentCode);
        return ResponseEntity.ok(ApiResponseDto.success(ApiResponseCode.COMMON_SUCCESS_RETRIEVED, commonCodes));
    }
    
    @LogExecution("전체 공통 코드 조회")
    @Operation(summary = "전체 공통 코드 조회", description = "모든 공통 코드를 조회합니다.")
    @ApiResponses({
        @ApiResponse(responseCode = "200", description = "전체 공통 코드 조회 성공")
    })
    @GetMapping
    public ResponseEntity<ApiResponseDto<List<CommonCodeDto>>> getAllCodes() {
        List<CommonCodeDto> commonCodes = commonCodeService.getAllCodes();
        return ResponseEntity.ok(ApiResponseDto.success(ApiResponseCode.COMMON_SUCCESS_RETRIEVED, commonCodes));
    }
}
