package incheon.uis.ums.shp;

import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.HttpURLConnection;
import java.net.URL;
import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;
import java.time.LocalDate;
import java.time.format.DateTimeFormatter;
import java.util.zip.ZipEntry;
import java.util.zip.ZipOutputStream;

/**
 * 공통 SHP/WFS 다운로드 유틸
 */
public class ShapeDownloadUtil {

    /** 기존 시그니처 (호출 코드 유지용) */
    public static void addLayerFromWfs(
            ZipOutputStream zos,
            String wfsBaseUrl,
            String typeName,
            String cqlFilter
    ) throws IOException {
        // entryLabel 은 null로 넘김 → 엔트리 이름에는 사용 안 함
        addLayerFromWfs(zos, wfsBaseUrl, typeName, null, cqlFilter);
    }

    /**
     * 확장 시그니처 (entryLabel은 HTTP 파일명용, ZIP 안 엔트리명에는 사용 X)
     */
    public static void addLayerFromWfs(
            ZipOutputStream zos,
            String wfsBaseUrl,
            String typeName,
            String entryLabel,
            String cqlFilter
    ) throws IOException {

        if (typeName == null || typeName.isBlank()) return;

        // --- 1. URL 구성 ---
        StringBuilder q = new StringBuilder();
        q.append("SERVICE=WFS")
                .append("&REQUEST=GetFeature")
                .append("&VERSION=1.0.0")
                .append("&OUTPUTFORMAT=SHAPE-ZIP")
                .append("&maxFeatures=10000")
                .append("&TYPENAME=")
                .append(URLEncoder.encode(typeName, StandardCharsets.UTF_8));

        if (cqlFilter != null && !cqlFilter.isBlank()) {
            q.append("&CQL_FILTER=")
                    .append(URLEncoder.encode(cqlFilter, StandardCharsets.UTF_8));
        }

        String fullUrl = appendQuery(wfsBaseUrl+"/map/wfs", q.toString());

        // --- 2. WFS 서버 HTTP 호출 ---
        HttpURLConnection conn = (HttpURLConnection) new URL(fullUrl).openConnection();
        conn.setConnectTimeout(10_000);
        conn.setReadTimeout(60_000);
        conn.setRequestMethod("GET");

        int code = conn.getResponseCode();
        if (code != HttpURLConnection.HTTP_OK) {
            conn.disconnect();
            throw new IOException("WFS 요청 실패(HTTP " + code + "): " + fullUrl);
        }

        // --- 3. ZIP 엔트리 이름 ---
        // 내부 엔트리명은 항상 typeName 기준
        String baseName = typeName.replace(':', '_');
        baseName = toSafeFileName(baseName);
        if (baseName == null || baseName.isBlank()) {
            baseName = "layer";
        }

        // 내부 ZIP 파일 이름은 날짜 없이, 원래대로
        String entryName = baseName + ".zip";

        zos.putNextEntry(new ZipEntry(entryName));

        try (InputStream in = conn.getInputStream()) {
            byte[] buf = new byte[8192];
            int len;
            while ((len = in.read(buf)) != -1) {
                zos.write(buf, 0, len);
            }
        } finally {
            zos.closeEntry();
            conn.disconnect();
        }
    }

    /** baseUrl 뒤에 query 문자열 깨끗하게 붙여주는 함수 */
    private static String appendQuery(String baseUrl, String query) {
        if (baseUrl.contains("?")) {
            return baseUrl.endsWith("?") || baseUrl.endsWith("&")
                    ? baseUrl + query
                    : baseUrl + "&" + query;
        }
        return baseUrl + "?" + query;
    }

    /** 파일명에 쓸 수 있도록 위험 문자 제거 */
    public static String toSafeFileName(String src) {
        if (src == null) return null;
        String s = src.replaceAll("[\\\\/:*?\"<>|]", "_").trim();
        return s.isEmpty() ? null : s;
    }
}
