package incheon.product.geoview2d.flight.web;

import incheon.com.cmm.api.DefaultApiResponse;
import incheon.com.cmm.exception.BusinessException;
import incheon.com.security.util.SecurityUtil;
import incheon.product.geoview2d.flight.service.FlightPhotoService;
import incheon.product.geoview2d.flight.vo.FlightPhotoDownloadRequestVO;
import incheon.product.geoview2d.flight.vo.FlightPhotoLayerVO;
import incheon.product.geoview2d.flight.vo.FlightPhotoSearchVO;
import lombok.extern.slf4j.Slf4j;
import org.geotools.ows.ServiceException;
import org.geotools.ows.wmts.WebMapTileServer;
import org.springframework.http.HttpHeaders;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
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.RestController;
import org.springframework.web.servlet.mvc.method.annotation.StreamingResponseBody;

import javax.annotation.Resource;
import javax.validation.Valid;
import java.io.IOException;
import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * 항공 사진 레이어 REST API 컨트롤러.
 *
 * 엔드포인트:
 *   - /api/v1/product/g2d/flight           (목록 조회)
 *   - /api/v1/product/g2d/flight/{id}      (상세 조회)
 *   - /api/v1/product/g2d/flight/download   (이미지 다운로드)
 */
@Slf4j
@RestController
@RequestMapping("/api/v1/product/g2d/flight")
public class FlightPhotoApiController {

    @Resource(name = "productFlightPhotoService")
    private FlightPhotoService flightPhotoService;

    /**
     * 항공 사진 레이어 목록 조회.
     */
    @GetMapping
    public ResponseEntity<DefaultApiResponse<Map<String, Object>>> getFlightPhotoLayerList(FlightPhotoSearchVO searchVO) {
        if (searchVO.getPageIndex() < 1) {
            searchVO.setPageIndex(1);
        }

        boolean otsdRlsEn = SecurityUtil.hasPermission("AGS", "PERM_FUNC_FLIGHT_DATA");
        List<FlightPhotoLayerVO> content = flightPhotoService.getFlightPhotoLayerList(searchVO, otsdRlsEn);

        Map<String, Object> response = new HashMap<>();
        response.put("content", content);
        if (searchVO.getPageSize() > 0) {
            response.put("page", searchVO.getPageIndex());
            response.put("size", searchVO.getPageSize());
            long total = flightPhotoService.getFlightPhotoLayerListTotCnt(searchVO, otsdRlsEn);
            response.put("totalElements", total);
            response.put("totalPages", (int) Math.ceil((double) total / searchVO.getPageSize()));
        }

        return ResponseEntity.ok(DefaultApiResponse.success(response));
    }

    /**
     * 항공 사진 레이어 상세 조회.
     */
    @GetMapping("/{flightPhotoLyrId}")
    public ResponseEntity<DefaultApiResponse<FlightPhotoLayerVO>> getFlightPhotoLayer(@PathVariable int flightPhotoLyrId) {
        FlightPhotoLayerVO layer = flightPhotoService.getFlightPhotoLayerById(flightPhotoLyrId);
        return ResponseEntity.ok(DefaultApiResponse.success(layer));
    }

    /**
     * 항공 사진 이미지 다운로드 (StreamingResponseBody).
     */
    @PostMapping("/download")
    public ResponseEntity<StreamingResponseBody> downloadFlightPhoto(@Valid @RequestBody FlightPhotoDownloadRequestVO request) {
        boolean hasPermission = SecurityUtil.hasPermission("AGS", "PERM_FUNC_FLIGHT_DATA");

        WebMapTileServer wmts;
        try {
            flightPhotoService.validateDownloadRequest(request);
            wmts = flightPhotoService.createWebMapTileServer();
        } catch (ServiceException | IOException e) {
            log.error("WMTS 서버 연결 실패", e);
            return ResponseEntity.internalServerError().body(null);
        }

        String timestamp = LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyyMMddHHmmss"));
        String filename = "flight_images_" + timestamp + ".zip";
        String encoded = URLEncoder.encode(filename, StandardCharsets.UTF_8);

        HttpHeaders headers = new HttpHeaders();
        headers.add(HttpHeaders.CONTENT_DISPOSITION, "attachment; filename*=UTF-8''" + encoded);
        headers.setContentType(MediaType.APPLICATION_OCTET_STREAM);
        headers.add(HttpHeaders.CACHE_CONTROL, "no-cache");

        StreamingResponseBody stream = outputStream -> {
            try {
                flightPhotoService.writeFlightPhotoZip(outputStream, request, hasPermission, wmts);
            } catch (ServiceException e) {
                throw new BusinessException("항공사진 ZIP 생성 실패", e);
            }
        };

        return ResponseEntity.ok().headers(headers).body(stream);
    }
}
