package incheon.uis.ums.service.impl;

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

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

import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;

import incheon.uis.ums.service.UisGeoServerService;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;

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

    private final RestTemplate restTemplate;
	
    private String mapprimeUrl = "/MapPrimeServer";

    @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();

        Object success = capabilities.get("success");
        if (!(success instanceof Boolean) || !((Boolean) 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) {
        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);
    }

    /**
     * WMS URL 생성
     */
    @Override
    public String generateWmsUrl(String layerName, String bbox, int width, int height) {
        return new StringBuilder()
                .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")
                .toString();
    }

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

        if (capabilities == null) {
            return layerList;
        }

        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> info = parseLayerNode(layerNode);
                if (info != null) {
                    layerList.add(info);
                }
            }
        } else if (!layers.isMissingNode()) {
            Map<String, Object> info = parseLayerNode(layers);
            if (info != null) {
                layerList.add(info);
            }
        }

        return layerList;
    }

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

            String name = layerNode.path("Name").asText("");
            String title = layerNode.path("Title").asText("");
            String abstractText = layerNode.path("Abstract").asText("");

            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 (RuntimeException 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;
    }
}
