package incheon.cmm.g3f.util;

import com.fasterxml.jackson.databind.ObjectMapper;
import lombok.extern.slf4j.Slf4j;
import org.springframework.http.*;
import org.springframework.web.client.HttpClientErrorException;
import org.springframework.web.client.RestClientException;
import org.springframework.web.client.RestTemplate;
import org.springframework.web.util.UriComponentsBuilder;

import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;

@Slf4j
public class GisManagerUtils {

    private final RestTemplate restTemplate;
    private final String baseUrl;

    public GisManagerUtils(RestTemplate restTemplate, String baseUrl) {
        this.restTemplate = restTemplate;
        this.baseUrl = baseUrl;
    }

    public Map<String, Object> createStorage(Map<String, Object> body) {
        return postForMap(baseUrl + "/api/storage", body);
    }

    public boolean updateStorage(Integer id, Map<String, Object> body) {
        return postForBoolean(baseUrl + "/api/storage/" + id, body);
    }

    public boolean deleteStorage(Integer id) {
        return postForBoolean(baseUrl + "/api/storage/delete/" + id, null);
    }

    // Asset API
    public Map<String, Object> createAsset(Map<String, Object> assetData) {
        try {
            ObjectMapper mapper = new ObjectMapper();
            
            HttpHeaders headers = new HttpHeaders();
            MediaType mediaType = new MediaType("application", "json", StandardCharsets.UTF_8);
            headers.setContentType(mediaType);
            headers.set("Accept", "application/json");
            headers.set("Accept", "*/*");
            // JSON 문자열로 직접 변환 (타입 보존 보장)
            String jsonBody = mapper.writeValueAsString(assetData);
            
            log.info("\n========== SENDING TO ASSET API ==========");
            log.info("POST {}/api/asset", baseUrl);
            log.info("Body (raw string):\n{}", jsonBody);
            log.info("Body length: {} bytes", jsonBody.length());
            
            HttpEntity<String> entity = new HttpEntity<>(jsonBody, headers);
            
            String url = baseUrl + "/api/asset";
            
            ResponseEntity<String> response = restTemplate.postForEntity(url, entity, String.class);
            
            log.info("\n========== RESPONSE ==========");
            log.info("Status: {}", response.getStatusCode());
            log.info("Body: {}", response.getBody());
            log.info("==============================\n");
            
            // String → Map 변환
            Map<String, Object> result = mapper.readValue(response.getBody(), 
                new com.fasterxml.jackson.core.type.TypeReference<Map<String, Object>>() {});
            
            return result;
            
        } catch (HttpClientErrorException e) {
            log.error("\n========== API ERROR ==========");
            log.error("Status: {} {}", e.getStatusCode(), e.getStatusText());
            log.error("Response: {}", e.getResponseBodyAsString());
            log.error("===============================\n");
            throw new RuntimeException(e);
            
        } catch (Exception e) {
            log.error("Asset API 호출 실패", e);
            throw new RuntimeException(e);
        }
    }

    public boolean updateAsset(Integer id, Map<String, Object> updateData) {
        try {
            if (updateData.containsKey("buildOptions")) {
                Object b = updateData.remove("buildOptions");
                updateData.put("buildoptions", b);
            }

            ObjectMapper mapper = new ObjectMapper();
            String json = mapper.writerWithDefaultPrettyPrinter().writeValueAsString(updateData);
            log.info("\n[Asset API Update Body] (ID={})\n{}", id, json);

            HttpHeaders headers = new HttpHeaders();
            headers.setContentType(MediaType.APPLICATION_JSON);
            HttpEntity<Map<String, Object>> entity = new HttpEntity<>(updateData, headers);

            String url = baseUrl + "/api/asset/" + id;
            ResponseEntity<String> res = restTemplate.postForEntity(url, entity, String.class);

            if (res.getStatusCode().is2xxSuccessful()) {
                log.info("Update 성공 [{}] {}", res.getStatusCode(), res.getBody());
                return true;
            } else {
                log.error("Update 실패 [{}] {}", res.getStatusCode(), res.getBody());
                return false;
            }
        } catch (HttpClientErrorException e) {
            log.error("HTTP 오류: {} {}", e.getStatusCode(), e.getResponseBodyAsString());
            return false;
        } catch (Exception e) {
            log.error("Update 예외: {}", e.getMessage(), e);
            return false;
        }
    }

    public boolean deleteAsset(Integer id) {
        return postForBoolean(baseUrl + "/api/asset/delete/" + id, null);
    }

    // 공통 POST/GET
    private Map<String, Object> postForMap(String url, Object body) {
        try {
            HttpHeaders h = new HttpHeaders();
            h.setContentType(MediaType.APPLICATION_JSON);
            HttpEntity<Object> entity = new HttpEntity<>(body, h);
            ResponseEntity<Map> r = restTemplate.postForEntity(url, entity, Map.class);
            return r.getBody();
        } catch (Exception e) {
            log.error("postForMap 실패 {}", e.getMessage());
            return Collections.emptyMap();
        }
    }

    private boolean postForBoolean(String url, Object body) {
        try {
            HttpHeaders h = new HttpHeaders();
            h.setContentType(MediaType.APPLICATION_JSON);
            HttpEntity<Object> entity = new HttpEntity<>(body, h);
            ResponseEntity<String> r = restTemplate.postForEntity(url, entity, String.class);
            return r.getStatusCode().is2xxSuccessful();
        } catch (Exception e) {
            log.error("postForBoolean 실패 {}", e.getMessage());
            return false;
        }
    }
    public Map<String, Object> checkStoragePath(String path) {
        Map<String, Object> result = new HashMap<>();

        try {
            // URLEncoder 제거하고 UriComponentsBuilder 사용
            String url = UriComponentsBuilder
                .fromHttpUrl(baseUrl + "/api/storage")
                .queryParam("path", path)  // 자동으로 적절하게 인코딩
                .build(false)  // 인코딩 안 함
                .toUriString();

            log.info("=== Storage Path Check ===");
            log.info("GET {}", url);

            HttpHeaders headers = new HttpHeaders();
            headers.setAccept(Collections.singletonList(MediaType.APPLICATION_JSON));

            HttpEntity<Void> entity = new HttpEntity<>(headers);

            ResponseEntity<String> response =
                    restTemplate.exchange(url, HttpMethod.GET, entity, String.class);
            
            log.info("Status: {}", response.getStatusCode());
            log.info("Body: {}", response.getBody());

            int statusCode = response.getStatusCode().value();
            
            result.put("statusCode", statusCode);
            result.put("success", true);
            
            if (statusCode == 200) {
                result.put("message", "파일이 존재합니다");
            }
            
            return result;

        } catch (HttpClientErrorException e) {
            int statusCode = e.getStatusCode().value();
            log.warn("Storage Path 체크 [{}]", statusCode);
            
            result.put("statusCode", statusCode);
            
            if (statusCode == 404) {
                result.put("success", true);
                result.put("message", "파일이 존재하지 않습니다 (등록 불가능)");
            } else {
                result.put("success", false);
                result.put("message", "경로 확인 실패");
            }
            
            return result;

        } catch (Exception e) {
            log.error("Storage Path API 호출 실패", e);
            result.put("statusCode", 500);
            result.put("success", false);
            result.put("message", "API 호출 실패: " + e.getMessage());
            return result;
        }
    }
}
