package gc.mda.signal_batch.domain.gis.controller;

import gc.mda.signal_batch.domain.gis.dto.AreaSearchRequest;
import gc.mda.signal_batch.domain.gis.dto.AreaSearchResponse;
import gc.mda.signal_batch.domain.gis.service.AreaSearchService;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.media.Content;
import io.swagger.v3.oas.annotations.media.ExampleObject;
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 jakarta.validation.Valid;
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 java.util.Map;

@Slf4j
@RestController
@RequestMapping("/api/v2/tracks")
@RequiredArgsConstructor
@Tag(name = "항적 조회 API V2", description = "해구/영역별 선박 항적 조회 API (WebSocket 호환 CompactVesselTrack 응답)")
public class AreaSearchController {

    private final AreaSearchService areaSearchService;

    @PostMapping("/area-search")
    @Operation(
        summary = "다중 폴리곤 영역 내 선박 탐색",
        description = """
            인메모리 캐시(D-1~D-7)를 활용하여 사용자 지정 다중 폴리곤 영역 내 선박을 탐색합니다.

            **검색 모드 (폴리곤 2개 이상 시):**
            - **ANY**: 합집합 - 어느 한 영역이라도 통과한 선박
            - **ALL**: 교집합 - 모든 영역을 통과한 선박
            - **SEQUENTIAL**: 순차 통과 - 모든 영역을 지정된 순서대로 통과한 선박

            **폴리곤 1개일 때:** mode는 무시되며, 해당 영역 히트 선박 + 전체 트랙 반환

            **응답 구조:**
            - `tracks`: 기존 V2 API와 동일한 CompactVesselTrack 배열 (프론트엔드 렌더링 호환)
            - `hitDetails`: 선박별 영역 히트 메타데이터 (진입/진출 시간, 히트 포인트 수)
            - `summary`: 검색 요약 (선박 수, 포인트 수, 처리 시간 등)

            **제약사항:**
            - 캐시된 날짜 범위만 조회 가능 (D-1 ~ D-7, 오늘 제외)
            - 폴리곤 최대 10개
            - 폴리곤 좌표는 닫힌 형태 (첫점 == 끝점)
            - 캐시 미준비 시 503 반환
            """
    )
    @ApiResponses(value = {
        @ApiResponse(responseCode = "200", description = "탐색 성공",
            content = @Content(
                mediaType = "application/json",
                schema = @Schema(implementation = AreaSearchResponse.class)
            )),
        @ApiResponse(responseCode = "400", description = "잘못된 요청 (날짜 범위 초과, 잘못된 폴리곤 등)",
            content = @Content(
                mediaType = "application/json",
                examples = @ExampleObject(value = "{\"error\": \"폴리곤 'zone_A'이 유효하지 않습니다 (자기 교차 등)\"}")
            )),
        @ApiResponse(responseCode = "503", description = "캐시 미준비 (LOADING 상태)",
            content = @Content(
                mediaType = "application/json",
                examples = @ExampleObject(value = "{\"error\": \"캐시가 아직 준비되지 않았습니다 (상태: LOADING)\"}")
            ))
    })
    public ResponseEntity<AreaSearchResponse> searchArea(
            @io.swagger.v3.oas.annotations.parameters.RequestBody(
                description = "다중 폴리곤 영역 탐색 요청",
                required = true,
                content = @Content(
                    schema = @Schema(implementation = AreaSearchRequest.class),
                    examples = @ExampleObject(
                        name = "순차 통과 예시",
                        value = """
                            {
                              "startTime": "2026-02-01T00:00:00",
                              "endTime": "2026-02-07T23:59:59",
                              "mode": "SEQUENTIAL",
                              "polygons": [
                                {
                                  "id": "zone_A", "name": "대한해협 서수도",
                                  "coordinates": [[128.5,34.0],[129.5,34.0],[129.5,35.0],[128.5,35.0],[128.5,34.0]]
                                },
                                {
                                  "id": "zone_B", "name": "제주해협",
                                  "coordinates": [[126.0,33.0],[127.0,33.0],[127.0,34.0],[126.0,34.0],[126.0,33.0]]
                                }
                              ]
                            }
                            """
                    )
                )
            )
            @Valid @RequestBody AreaSearchRequest request) {

        log.info("Area search request: mode={}, polygons={}, timeRange={} ~ {}",
                request.getMode(), request.getPolygons().size(),
                request.getStartTime(), request.getEndTime());

        return ResponseEntity.ok(areaSearchService.search(request));
    }

    @ExceptionHandler(IllegalArgumentException.class)
    public ResponseEntity<Map<String, String>> handleBadRequest(IllegalArgumentException e) {
        log.warn("Area search bad request: {}", e.getMessage());
        return ResponseEntity.badRequest()
                .body(Map.of("error", e.getMessage()));
    }

    @ExceptionHandler(AreaSearchService.CacheNotReadyException.class)
    public ResponseEntity<Map<String, String>> handleCacheNotReady(AreaSearchService.CacheNotReadyException e) {
        log.warn("Area search cache not ready: {}", e.getMessage());
        return ResponseEntity.status(HttpStatus.SERVICE_UNAVAILABLE)
                .body(Map.of("error", e.getMessage()));
    }
}
