package com.arms.api.languageconfig.util;

import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.dataformat.yaml.YAMLFactory;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;

import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.net.HttpURLConnection;
import java.net.URL;
import java.util.*;
import java.util.regex.Pattern;

@Slf4j
@RequiredArgsConstructor
public class LanguagePackFileReader {

    private static final Pattern LANGUAGE_FILE_PATTERN = Pattern.compile("^[a-z]{2}\\.json$");

    /**
     * Gitea에서 파일 정보 조회 (HttpURLConnection 사용)
     */
    @SuppressWarnings("java:S2647")
    public static Map<String, Object> getFileInfoFromGitea(String fileUrl, String username, String password) throws Exception {
        log.info("[ GiteaService :: getFileInfoFromGitea ] :: fileUrl => {}", fileUrl);

        try {
            HttpURLConnection connection = (HttpURLConnection) new URL(fileUrl).openConnection();
            String auth = username + ":" + password;
            String encodedAuth = Base64.getEncoder().encodeToString(auth.getBytes());
            connection.setRequestProperty("Authorization", "Basic " + encodedAuth);
            connection.setRequestProperty("Accept", "application/json");

            int responseCode = connection.getResponseCode();
            if (responseCode == HttpURLConnection.HTTP_OK) {
                try (BufferedReader reader = new BufferedReader(new InputStreamReader(connection.getInputStream()))) {
                    ObjectMapper mapper = new ObjectMapper(new YAMLFactory());
                    return mapper.readValue(reader, new TypeReference<Map<String, Object>>() {});
                } catch (Exception e) {
                    log.error("JSON 파싱 오류: {}", e.getMessage(), e);
                }
            } else {
                log.error("HTTP 요청 실패. 응답 코드: {}", responseCode);
            }
            connection.disconnect();
        } catch (Exception e) {
            log.error("URL 연결 오류: {}", e.getMessage(), e);
        }
        return null;
    }

    /**
     * 특정 언어팩 파일을 읽어서 파싱
     */
    @SuppressWarnings("java:S2647")
    public static Map<String, Object> readLanguagePackFile(String fileUrl, String username, String password) throws Exception {
        log.info("[ LanguagePackFileReader :: readLanguagePackFile ] :: fileUrl => {}", fileUrl);

        try {
            HttpURLConnection connection = (HttpURLConnection) new URL(fileUrl).openConnection();
            String auth = username + ":" + password;
            String encodedAuth = Base64.getEncoder().encodeToString(auth.getBytes());
            connection.setRequestProperty("Authorization", "Basic " + encodedAuth);
            connection.setRequestProperty("Accept", "application/json");

            int responseCode = connection.getResponseCode();
            if (responseCode == HttpURLConnection.HTTP_OK) {
                try (BufferedReader reader = new BufferedReader(new InputStreamReader(connection.getInputStream()))) {
                    ObjectMapper mapper = new ObjectMapper();
                    Map<String, Object> response = mapper.readValue(reader, new TypeReference<Map<String, Object>>() {});

                    String content = (String) response.get("content");
                    if (content != null) {
                        // base64 디코딩
                        byte[] decodedBytes = Base64.getDecoder().decode(content);
                        String jsonContent = new String(decodedBytes);

                        return mapper.readValue(jsonContent, new TypeReference<Map<String, Object>>() {});
                    }
                }
            } else {
                log.error("HTTP 요청 실패. 응답 코드: {}", responseCode);
            }
            connection.disconnect();
        } catch (Exception e) {
            log.error("언어팩 파일 읽기 오류: {}", e.getMessage(), e);
        }

        return new HashMap<>();
    }

    /**
     * 중첩된 키-값을 평면화된 형태로 변환
     */
    public static Map<String, String> flattenLanguagePack(Map<String, Object> languagePack) {
        Map<String, String> flattened = new HashMap<>();
        flattenMap(languagePack, "", flattened);
        return flattened;
    }

    private static void flattenMap(Map<String, Object> map, String prefix, Map<String, String> result) {
        for (Map.Entry<String, Object> entry : map.entrySet()) {
            String key = prefix.isEmpty() ? entry.getKey() : prefix + "." + entry.getKey();
            Object value = entry.getValue();

            if (value instanceof Map) {
                @SuppressWarnings("unchecked")
                Map<String, Object> nestedMap = (Map<String, Object>) value;
                flattenMap(nestedMap, key, result);
            } else {
                result.put(key, value != null ? value.toString() : null);
            }
        }
    }

    /**
     * 평면화된 키-값을 중첩된 형태로 변환
     */
    public static Map<String, Object> unflattenLanguagePack(Map<String, String> flattenedPack) {
        Map<String, Object> result = new HashMap<>();

        for (Map.Entry<String, String> entry : flattenedPack.entrySet()) {
            String[] keyParts = entry.getKey().split("\\.");
            Map<String, Object> current = result;

            for (int i = 0; i < keyParts.length - 1; i++) {
                current = (Map<String, Object>) current.computeIfAbsent(keyParts[i], k -> new HashMap<>());
            }

            current.put(keyParts[keyParts.length - 1], entry.getValue());
        }

        return result;
    }
}
