package incheon.sgp.rst.service.impl;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.web.client.RestTemplate;

import com.fasterxml.jackson.databind.JsonNode;

import incheon.sgp.rst.service.RstGeoServerService;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;

/**
 * Mapprime 연동 서비스 구현체
 * @author 관리자
 * @since 2024. 12. 19
 */
@Service
@RequiredArgsConstructor
@Slf4j
public class RstGeoServerServiceImpl implements RstGeoServerService {

    private final RestTemplate restTemplate;
	
    @Value("${gis.server.url:http://10.100.232.241/MapPrimeServer}")
    private String mapprimeUrl;

    @Value("${gis.server.prefix:incheon}")
    private String workspace;

    /**
     * GeoServer Capabilities 조회
     */
    @Override
    public Map<String, Object> getCapabilities() {
    	
//        try {
//            //String capabilitiesUrl = mapprimeUrl + "/" + workspace + "/wms?service=WMS&request=GetCapabilities";
//            String capabilitiesUrl = mapprimeUrl + "/map/wms?service=WMS&request=GetCapabilities";
//            log.info("Mapprime Capabilities 요청: {}", capabilitiesUrl);
//
//            // UTF-8 인코딩으로 요청 헤더 설정
//            org.springframework.http.HttpHeaders headers = new org.springframework.http.HttpHeaders();
//            headers.set("Accept-Charset", "UTF-8");
//            headers.set("Accept", "text/xml, application/xml, */*");
//            headers.set("User-Agent", "Mozilla/5.0");
//
//            org.springframework.http.HttpEntity<String> entity = new org.springframework.http.HttpEntity<>(headers);
//
//            // byte[]로 응답을 받아 UTF-8로 직접 변환
//            ResponseEntity<byte[]> byteResponse = restTemplate.exchange(capabilitiesUrl, org.springframework.http.HttpMethod.GET, entity, byte[].class);
//            ResponseEntity<String> response;
//
//            if (byteResponse.getStatusCode().is2xxSuccessful() && byteResponse.getBody() != null) {
//                // byte[]를 UTF-8로 변환
//                String responseBody = new String(byteResponse.getBody(), java.nio.charset.StandardCharsets.UTF_8);
//                response = ResponseEntity.status(byteResponse.getStatusCode())
//                        .headers(byteResponse.getHeaders())
//                        .body(responseBody);
//            } else {
//                response = ResponseEntity.status(byteResponse.getStatusCode()).build();
//            }
//
//            if (response.getStatusCode().is2xxSuccessful()) {
//                // UTF-8 인코딩으로 XML 파싱
//                XmlMapper xmlMapper = new XmlMapper();
//                xmlMapper.configure(com.fasterxml.jackson.core.JsonParser.Feature.ALLOW_UNQUOTED_CONTROL_CHARS, true);
//
//                // 응답 본문이 UTF-8로 올바르게 처리됨
//                String responseBody = response.getBody();
//
//                if (responseBody == null) {
//                    log.error("GeoServer 응답 본문이 null입니다");
//                    return createErrorResult("GeoServer 응답 본문이 null입니다");
//                }
//
//                // 디버깅을 위해 원본 응답 로깅 (간단하게)
//                log.info("GeoServer 응답 길이: {} bytes", responseBody.length());
//                log.debug("GeoServer 응답 샘플: {}", responseBody.substring(0, Math.min(200, responseBody.length())));
//
//                JsonNode capabilitiesJson = xmlMapper.readTree(responseBody);
//
//                Map<String, Object> result = new HashMap<>();
//                result.put("success", true);
//                result.put("data", capabilitiesJson);
//                result.put("layers", parseLayerList(capabilitiesJson));
//
//                return result;
//            } else {
//                log.error("GeoServer Capabilities 요청 실패: {}", response.getStatusCode());
//                return createErrorResult("Capabilities 조회 실패");
//            }
//
//        } catch (Exception e) {
//            log.error("GeoServer Capabilities 조회 중 오류 발생", e);
//            return createErrorResult("Capabilities 조회 중 오류 발생: " + e.getMessage());
//        }
    	
    	return null;
    }

    /**
     * 레이어 목록 조회 (트리 구조)
     */
    @Override
    public List<Map<String, Object>> getLayerList() {
        Map<String, Object> capabilities = getCapabilities();
        if (!(Boolean) capabilities.get("success")) {
            log.warn("Capabilities 조회 실패로 빈 레이어 목록 반환");
            return new ArrayList<>();
        }

        @SuppressWarnings("unchecked")
        List<Map<String, Object>> layers = (List<Map<String, Object>>) capabilities.get("layers");
        return layers != null ? layers : new ArrayList<>();
    }

    /**
     * 특정 레이어 정보 조회
     */
    @Override
    public Map<String, Object> getLayerInfo(String layerName) {
        try {
            List<Map<String, Object>> layerList = getLayerList();

            for (Map<String, Object> layer : layerList) {
                if (layerName.equals(layer.get("name"))) {
                    return layer;
                }
                // 하위 레이어 검색
                @SuppressWarnings("unchecked")
                List<Map<String, Object>> children = (List<Map<String, Object>>) layer.get("children");
                if (children != null) {
                    for (Map<String, Object> child : children) {
                        if (layerName.equals(child.get("name"))) {
                            return child;
                        }
                    }
                }
            }

            return createErrorResult("레이어를 찾을 수 없습니다: " + layerName);

        } catch (Exception e) {
            log.error("레이어 정보 조회 중 오류 발생", e);
            return createErrorResult("레이어 정보 조회 중 오류 발생: " + e.getMessage());
        }
    }

    /**
     * WMS URL 생성 (GeoServer 실제 URL 형식에 맞춤)
     */
    @Override
    public String generateWmsUrl(String layerName, String bbox, int width, int height) {
        StringBuilder url = new StringBuilder();
        url.append(mapprimeUrl)
           .append("/map/wms?service=WMS&request=GetMap")
           .append("&layers=").append(layerName)
           .append("&styles=")  // 스타일 파라미터를 먼저 배치
           .append("&width=").append(width)
           .append("&height=").append(height)
           .append("&crs=EPSG:5186")  // 좌표계 설정
           .append("&bbox=").append(bbox)
           .append("&format=image/png")
           .append("&transparent=true");

        return url.toString();
    }

    /**
     * XML Capabilities에서 레이어 목록 파싱
     */
    @SuppressWarnings("unchecked")
    private List<Map<String, Object>> parseLayerList(JsonNode capabilities) {
        List<Map<String, Object>> layerList = new ArrayList<>();

        try {
            JsonNode capability = capabilities.path("Capability");
            if (capability.isMissingNode()) return layerList;

            JsonNode layer = capability.path("Layer");
            if (layer.isMissingNode()) return layerList;

            // 최상위 레이어들 파싱
            JsonNode layers = layer.path("Layer");
            if (layers.isArray()) {
                for (JsonNode layerNode : layers) {
                    Map<String, Object> layerInfo = parseLayerNode(layerNode);
                    if (layerInfo != null) {
                        layerList.add(layerInfo);
                    }
                }
            } else if (!layers.isMissingNode()) {
                Map<String, Object> layerInfo = parseLayerNode(layers);
                if (layerInfo != null) {
                    layerList.add(layerInfo);
                }
            }

        } catch (Exception e) {
            log.error("레이어 목록 파싱 중 오류 발생", e);
        }

        return layerList;
    }

    /**
     * 개별 레이어 노드 파싱
     */
    private Map<String, Object> parseLayerNode(JsonNode layerNode) {
        try {
            Map<String, Object> layerInfo = new HashMap<>();

            // 기본 정보 (UTF-8 보장)
            String name = layerNode.path("Name").asText("");
            String title = layerNode.path("Title").asText("");
            String abstractText = layerNode.path("Abstract").asText("");

            // UTF-8로 다시 인코딩하여 깨짐 방지
            if (!name.isEmpty()) {
                name = new String(name.getBytes(java.nio.charset.StandardCharsets.UTF_8), java.nio.charset.StandardCharsets.UTF_8);
            }
            if (!title.isEmpty()) {
                title = new String(title.getBytes(java.nio.charset.StandardCharsets.UTF_8), java.nio.charset.StandardCharsets.UTF_8);
            }
            if (!abstractText.isEmpty()) {
                abstractText = new String(abstractText.getBytes(java.nio.charset.StandardCharsets.UTF_8), java.nio.charset.StandardCharsets.UTF_8);
            }

            layerInfo.put("name", name);
            layerInfo.put("title", title);
            layerInfo.put("abstract", abstractText);

            // 스타일 정보
            JsonNode style = layerNode.path("Style");
            if (!style.isMissingNode()) {
                layerInfo.put("style", style.path("Name").asText(""));
            }

            // 하위 레이어들
            JsonNode childLayers = layerNode.path("Layer");
            if (childLayers.isArray() && childLayers.size() > 0) {
                List<Map<String, Object>> children = new ArrayList<>();
                for (JsonNode childNode : childLayers) {
                    Map<String, Object> childInfo = parseLayerNode(childNode);
                    if (childInfo != null) {
                        children.add(childInfo);
                    }
                }
                layerInfo.put("children", children);
                layerInfo.put("hasChildren", true);
            } else {
                layerInfo.put("hasChildren", false);
            }

            return layerInfo;

        } catch (Exception e) {
            log.error("레이어 노드 파싱 중 오류 발생", e);
            return null;
        }
    }

    /**
     * 오류 결과 생성
     */
    private Map<String, Object> createErrorResult(String message) {
        Map<String, Object> result = new HashMap<>();
        result.put("success", false);
        result.put("message", message);
        return result;
    }
}
