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

import gc.mda.signal_batch.domain.gis.dto.GisBoundaryResponse;
import gc.mda.signal_batch.domain.vessel.dto.CompactVesselTrack;
import gc.mda.signal_batch.domain.vessel.dto.VesselStatsResponse;
import gc.mda.signal_batch.domain.vessel.dto.VesselTracksRequest;
import gc.mda.signal_batch.domain.vessel.dto.RecentVesselPositionDto;
import gc.mda.signal_batch.domain.gis.service.GisService;
import gc.mda.signal_batch.domain.gis.service.GisServiceV2;
import gc.mda.signal_batch.domain.vessel.service.VesselPositionService;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.media.ArraySchema;
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 lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.*;

import java.util.List;
import java.util.Map;

/**
 * GIS API V2 - WebSocket과 동일한 응답 구조 (CompactVesselTrack)
 *
 * V1과의 차이점:
 * - 항적 조회 시 CompactVesselTrack 반환 (선박별 병합, 배열 기반)
 * - 통합선박 필터링 옵션 지원
 * - 선박 메타정보(shipName, shipType, nationalCode) 포함
 */
@Slf4j
@RestController
@RequestMapping("/api/v2")
@RequiredArgsConstructor
@Tag(name = "항적 조회 API V2", description = "해구/영역별 선박 항적 조회 API (WebSocket 호환 CompactVesselTrack 응답)")
public class GisControllerV2 {

    private final GisService gisService;
    private final GisServiceV2 gisServiceV2;
    private final VesselPositionService vesselPositionService;

    @GetMapping("/haegu/boundaries")
    @Operation(
        summary = "해구 경계 조회",
        description = "모든 해구의 경계 정보를 GeoJSON 형식으로 반환합니다."
    )
    @ApiResponses(value = {
        @ApiResponse(responseCode = "200", description = "조회 성공",
            content = @Content(array = @ArraySchema(schema = @Schema(implementation = GisBoundaryResponse.class))))
    })
    public List<GisBoundaryResponse> getHaeguBoundaries() {
        return gisService.getHaeguBoundaries();
    }

    @GetMapping("/haegu/vessel-stats")
    @Operation(
        summary = "해구별 선박 통계",
        description = "지정된 시간 범위 내의 해구별 선박 통계를 조회합니다."
    )
    @ApiResponses(value = {
        @ApiResponse(responseCode = "200", description = "조회 성공")
    })
    public Map<Integer, VesselStatsResponse> getHaeguVesselStats(
            @Parameter(description = "조회 시간 범위 (분)", example = "60")
            @RequestParam(defaultValue = "60") int minutes) {
        return gisService.getHaeguVesselStats(minutes);
    }

    @GetMapping("/areas/boundaries")
    @Operation(
        summary = "사용자 정의 영역 경계 조회",
        description = "모든 사용자 정의 영역의 경계 정보를 GeoJSON 형식으로 반환합니다."
    )
    @ApiResponses(value = {
        @ApiResponse(responseCode = "200", description = "조회 성공",
            content = @Content(array = @ArraySchema(schema = @Schema(implementation = GisBoundaryResponse.class))))
    })
    public List<GisBoundaryResponse> getAreaBoundaries() {
        return gisService.getAreaBoundaries();
    }

    @GetMapping("/areas/vessel-stats")
    @Operation(
        summary = "영역별 선박 통계",
        description = "지정된 시간 범위 내의 영역별 선박 통계를 조회합니다."
    )
    @ApiResponses(value = {
        @ApiResponse(responseCode = "200", description = "조회 성공")
    })
    public Map<String, VesselStatsResponse> getAreaVesselStats(
            @Parameter(description = "조회 시간 범위 (분)", example = "60")
            @RequestParam(defaultValue = "60") int minutes) {
        return gisService.getAreaVesselStats(minutes);
    }

    @GetMapping("/tracks/haegu/{haeguNo}")
    @Operation(
        summary = "해구별 선박 항적 조회",
        description = """
            특정 해구 내 선박 항적을 CompactVesselTrack 형식으로 반환합니다.

            **V1과의 차이점:**
            - 선박별로 병합된 단일 객체 반환 (V1은 세그먼트별 분리)
            - geometry: [[lon, lat], ...] 배열 형태 (V1은 WKT)
            - timestamps, speeds 배열 포함
            - 선박 정보(shipName, shipType, nationalCode) 포함
            - 통합선박 필터링 지원
            """
    )
    @ApiResponses(value = {
        @ApiResponse(responseCode = "200", description = "조회 성공",
            content = @Content(array = @ArraySchema(schema = @Schema(implementation = CompactVesselTrack.class))))
    })
    public List<CompactVesselTrack> getHaeguTracks(
            @Parameter(description = "해구 번호", example = "1", required = true)
            @PathVariable Integer haeguNo,
            @Parameter(description = "조회 시간 범위 (분, 최대 1440)", example = "60")
            @RequestParam(defaultValue = "60") int minutes,
            @Parameter(description = "통합선박 필터링 (0: 미적용, 1: 적용)", example = "0",
                schema = @Schema(allowableValues = {"0", "1"}))
            @RequestParam(defaultValue = "0") String isIntegration) {

        boolean filterByIntegration = "1".equals(isIntegration);
        return gisServiceV2.getHaeguTracks(haeguNo, minutes, filterByIntegration);
    }

    @GetMapping("/tracks/area/{areaId}")
    @Operation(
        summary = "영역별 선박 항적 조회",
        description = """
            특정 영역 내 선박 항적을 CompactVesselTrack 형식으로 반환합니다.

            **V1과의 차이점:**
            - 선박별로 병합된 단일 객체 반환 (V1은 세그먼트별 분리)
            - geometry: [[lon, lat], ...] 배열 형태 (V1은 WKT)
            - timestamps, speeds 배열 포함
            - 선박 정보(shipName, shipType, nationalCode) 포함
            - 통합선박 필터링 지원
            """
    )
    @ApiResponses(value = {
        @ApiResponse(responseCode = "200", description = "조회 성공",
            content = @Content(array = @ArraySchema(schema = @Schema(implementation = CompactVesselTrack.class))))
    })
    public List<CompactVesselTrack> getAreaTracks(
            @Parameter(description = "영역 ID", example = "AREA_001", required = true)
            @PathVariable String areaId,
            @Parameter(description = "조회 시간 범위 (분, 최대 1440)", example = "60")
            @RequestParam(defaultValue = "60") int minutes,
            @Parameter(description = "통합선박 필터링 (0: 미적용, 1: 적용)", example = "0",
                schema = @Schema(allowableValues = {"0", "1"}))
            @RequestParam(defaultValue = "0") String isIntegration) {

        boolean filterByIntegration = "1".equals(isIntegration);
        return gisServiceV2.getAreaTracks(areaId, minutes, filterByIntegration);
    }

    @PostMapping("/tracks/vessels")
    @Operation(
        summary = "선박별 항적 조회",
        description = """
            지정된 선박 목록의 항적을 시간 범위 내에서 조회합니다.

            **응답 구조:** CompactVesselTrack (WebSocket과 동일)
            - 선박별 병합된 단일 객체
            - geometry/timestamps/speeds 배열 포함
            - 선박 메타정보 포함
            """
    )
    @ApiResponses(value = {
        @ApiResponse(responseCode = "200", description = "조회 성공",
            content = @Content(array = @ArraySchema(schema = @Schema(implementation = CompactVesselTrack.class))))
    })
    public List<CompactVesselTrack> getVesselTracks(
            @io.swagger.v3.oas.annotations.parameters.RequestBody(
                description = "선박 항적 조회 요청",
                required = true,
                content = @Content(schema = @Schema(implementation = VesselTracksRequest.class))
            )
            @RequestBody VesselTracksRequest request) {
        return gisServiceV2.getVesselTracksV2(request);
    }

    @GetMapping("/vessels/recent-positions")
    @Operation(
        summary = "최근 위치 업데이트된 선박 조회",
        description = "지정된 시간(분) 이내에 위치가 업데이트된 모든 선박의 최신 위치 정보를 반환합니다."
    )
    @ApiResponses(value = {
        @ApiResponse(responseCode = "200", description = "조회 성공",
            content = @Content(array = @ArraySchema(schema = @Schema(implementation = RecentVesselPositionDto.class)))),
        @ApiResponse(responseCode = "400", description = "잘못된 파라미터 (minutes: 1~1440)")
    })
    public List<RecentVesselPositionDto> getRecentVesselPositions(
            @Parameter(description = "조회 시간 범위 (분, 1~1440)", example = "5")
            @RequestParam(defaultValue = "5") int minutes) {

        if (minutes <= 0 || minutes > 1440) {
            throw new IllegalArgumentException("Minutes must be between 1 and 1440");
        }

        return vesselPositionService.getRecentVesselPositions(minutes);
    }
}
