package com.kamco.cd.kamcoback.zoo; import com.kamco.cd.kamcoback.config.api.ApiResponseDto; import com.kamco.cd.kamcoback.zoo.dto.AnimalDto; import com.kamco.cd.kamcoback.zoo.dto.AnimalDto.Basic; import com.kamco.cd.kamcoback.zoo.dto.AnimalDto.Category; import com.kamco.cd.kamcoback.zoo.dto.AnimalDto.Species; import com.kamco.cd.kamcoback.zoo.service.AnimalService; import io.swagger.v3.oas.annotations.Hidden; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.Parameter; import io.swagger.v3.oas.annotations.media.Content; import io.swagger.v3.oas.annotations.media.Schema; 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 org.springframework.data.domain.Page; import org.springframework.web.bind.annotation.DeleteMapping; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.bind.annotation.RestController; @Hidden @Tag(name = "Animal", description = "동물 관리 API") @RequiredArgsConstructor @RestController @RequestMapping({"/api/animals", "/v1/api/animals"}) public class AnimalApiController { private final AnimalService animalService; /** * 동물 생성 * * @param req 동물 생성 요청 * @return 생성된 동물 정보 */ @Operation(summary = "동물 생성", description = "새로운 동물 정보를 등록합니다.") @ApiResponses( value = { @ApiResponse( responseCode = "201", description = "동물 생성 성공", content = @Content( mediaType = "application/json", schema = @Schema(implementation = AnimalDto.Basic.class))), @ApiResponse(responseCode = "400", description = "잘못된 요청 데이터", content = @Content), @ApiResponse(responseCode = "500", description = "서버 오류", content = @Content) }) @PostMapping public ApiResponseDto createAnimal( @io.swagger.v3.oas.annotations.parameters.RequestBody( description = "동물 생성 요청 정보", required = true, content = @Content( mediaType = "application/json", schema = @Schema(implementation = AnimalDto.AddReq.class))) @RequestBody AnimalDto.AddReq req) { AnimalDto.Basic created = animalService.createAnimal(req); return ApiResponseDto.createOK(created); } /** * UUID로 동물 조회 * * @param uuid 동물 UUID * @return 동물 정보 */ @Operation(summary = "동물 단건 조회", description = "UUID로 특정 동물의 상세 정보를 조회합니다.") @ApiResponses( value = { @ApiResponse( responseCode = "200", description = "조회 성공", content = @Content( mediaType = "application/json", schema = @Schema(implementation = AnimalDto.Basic.class))), @ApiResponse(responseCode = "404", description = "동물을 찾을 수 없음", content = @Content), @ApiResponse(responseCode = "500", description = "서버 오류", content = @Content) }) @GetMapping("/{uuid}") public ApiResponseDto getAnimal( @Parameter( description = "조회할 동물의 UUID", required = true, example = "550e8400-e29b-41d4-a716-446655440000") @PathVariable String uuid) { Long id = animalService.getAnimalByUuid(uuid); AnimalDto.Basic animal = animalService.getAnimal(id); return ApiResponseDto.ok(animal); } /** * UUID로 동물 삭제 (논리 삭제) * * @param uuid 동물 UUID * @return 삭제 성공 메시지 */ @Operation(summary = "동물 삭제", description = "UUID로 특정 동물을 삭제합니다 (논리 삭제).") @ApiResponses( value = { @ApiResponse(responseCode = "204", description = "삭제 성공", content = @Content), @ApiResponse(responseCode = "404", description = "동물을 찾을 수 없음", content = @Content), @ApiResponse(responseCode = "500", description = "서버 오류", content = @Content) }) @DeleteMapping("/{uuid}") public ApiResponseDto deleteAnimal( @Parameter( description = "삭제할 동물의 UUID", required = true, example = "550e8400-e29b-41d4-a716-446655440000") @PathVariable String uuid) { Long id = animalService.getAnimalByUuid(uuid); animalService.deleteAnimal(id); return ApiResponseDto.deleteOk(uuid); } /** * 동물 검색 (페이징) * * @param name 동물 이름 (선택) * @param category 서식지 타입 (선택) * @param species 동물종 (선택) 개, 고양이등. * @param page 페이지 번호 (기본값: 0) * @param size 페이지 크기 (기본값: 20) * @param sort 정렬 조건 (예: "name,asc") * @return 페이징 처리된 동물 목록 */ @Operation( summary = "동물 검색", description = "다양한 조건으로 동물을 검색하고 페이징된 결과를 반환합니다. 모든 검색 조건은 선택적이며, 조건 없이 호출하면 전체 동물 목록을 반환합니다.") @ApiResponses( value = { @ApiResponse( responseCode = "200", description = "검색 성공", content = @Content( mediaType = "application/json", schema = @Schema(implementation = Page.class))), @ApiResponse(responseCode = "400", description = "잘못된 검색 조건", content = @Content), @ApiResponse(responseCode = "500", description = "서버 오류", content = @Content) }) @GetMapping public ApiResponseDto> searchAnimals( @Parameter(description = "동물 이름 (부분 일치 검색)", example = "호랑이") @RequestParam(required = false) String name, @Parameter(description = "서식지 카테고리", example = "MAMMAL") @RequestParam(required = false) Category category, @Parameter(description = "동물 종", example = "TIGER") @RequestParam(required = false) Species species, @Parameter(description = "페이지 번호 (0부터 시작)", example = "0") @RequestParam(defaultValue = "0") int page, @Parameter(description = "페이지 크기", example = "20") @RequestParam(defaultValue = "20") int size, @Parameter(description = "정렬 조건 (형식: 필드명,방향)", example = "name,asc") @RequestParam(required = false) String sort) { AnimalDto.SearchReq searchReq = new AnimalDto.SearchReq(name, category, species, page, size, sort); Page animals = animalService.search(searchReq); return ApiResponseDto.ok(animals); } }