package hr.com.port.ips.eracun.helper;

import com.google.gson.Gson;
import com.google.gson.JsonArray;
import com.google.gson.JsonElement;
import com.google.gson.JsonObject;

import java.util.Arrays;
import java.util.Collections;
import java.util.LinkedHashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;

public final class JsonLogSanitizer {
	
	// KAKO KORISTITI	
	// 1) Objekt → siguran JSON
	//final String safeJson = JsonLogSanitizer.toSafeJson(gson, request);
	//logger.debug("MER queryOutbox request body JSON: " + safeJson);

	// 2) Dodatno maskiranje npr. 'companyId'
	//final String safeJson2 = JsonLogSanitizer.toSafeJson(gson, request,
	//        new java.util.HashSet<>(java.util.Arrays.asList("companyid")));

	// 3) Već gotov JSON string
	//final String safeRaw = JsonLogSanitizer.toSafeJson(gson, rawJsonString);
	//logger.debug("MER send body JSON: " + safeRaw);

	// 4) Headere (npr. iz OkHttp klijenta)
	//Map<String, String> hdrs = new java.util.LinkedHashMap<>();
	//hdrs.put("Authorization", "Bearer abc123");
	//hdrs.put("Content-Type", "application/json");
	///Map<String, String> safeHdrs = JsonLogSanitizer.maskHeaders(hdrs);
	//logger.debug("HTTP headers: " + safeHdrs);	

    private JsonLogSanitizer() {}

    private static final String MASK = "***";
    private static final Set<String> DEFAULT_SENSITIVE_KEYS = new HashSet<>(Arrays.asList(
            "password", "pass", "pwd", "lozinka",
            "token", "authorization", "auth",
            "apikey", "api_key",
            "secret"
    ));

    // Pretvori objekt u JSON i zamaskiraj osjetljiva polja.
    public static String toSafeJson(Gson gson, Object request) {
        return toSafeJson(gson, request, Collections.emptySet());
    }

    // Pretvori objekt u JSON i zamaskiraj osjetljiva polja, uz dodatne ključeve.
    public static String toSafeJson(Gson gson, Object request, Set<String> extraSensitiveKeys) {
        try {
            JsonElement root = gson.toJsonTree(request);
            maskRecursive(root, extraSensitiveKeys);
            return gson.toJson(root);
        } catch (Exception ex) {
            // Namjerno ne logiramo originalne podatke; vraćamo “redacted” placeholder
            return "{\"redacted\":true}";
        }
    }

    // Sanitiziraj već gotov JSON string (ako ga već imaš).
    public static String toSafeJson(Gson gson, String rawJson) {
        return toSafeJson(gson, rawJson, Collections.emptySet());
    }

    public static String toSafeJson(Gson gson, String rawJson, Set<String> extraSensitiveKeys) {
        try {
            JsonElement root = gson.fromJson(rawJson, JsonElement.class);
            maskRecursive(root, extraSensitiveKeys);
            return gson.toJson(root);
        } catch (Exception ex) {
            return "{\"redacted\":true}";
        }
    }

    // Maskiraj HTTP headere (Authorization, ApiKey, Token, …).
    public static Map<String, String> maskHeaders(Map<String, String> headers) {
        if (headers == null) return Collections.emptyMap();
        Map<String, String> safe = new LinkedHashMap<>();
        for (Map.Entry<String, String> e : headers.entrySet()) {
            String k = e.getKey();
            String v = e.getValue();
            if (isSensitiveKey(k, Collections.<String>emptySet())) {
                safe.put(k, MASK);
            } else {
                safe.put(k, v);
            }
        }
        return safe;
    }

    // --- internal ---

    private static void maskRecursive(JsonElement el, Set<String> extraSensitiveKeys) {
        if (el == null || el.isJsonNull()) return;

        if (el.isJsonObject()) {
            JsonObject obj = el.getAsJsonObject();
            for (Map.Entry<String, JsonElement> e : obj.entrySet()) {
                String key = e.getKey();
                if (isSensitiveKey(key, extraSensitiveKeys)) {
                    // Prepisujemo kao string s maskom, neovisno o originalnom tipu
                    obj.addProperty(key, MASK);
                } else {
                    maskRecursive(e.getValue(), extraSensitiveKeys);
                }
            }
        } else if (el.isJsonArray()) {
            JsonArray arr = el.getAsJsonArray();
            for (int i = 0; i < arr.size(); i++) {
                maskRecursive(arr.get(i), extraSensitiveKeys);
            }
        }
        // primitivi se maskiraju samo ako su “sensitive” po ključu roditelja
    }

    private static boolean isSensitiveKey(String key, Set<String> extra) {
        if (key == null) return false;
        String k = key.toLowerCase();
        if (DEFAULT_SENSITIVE_KEYS.contains(k)) return true;
        if (extra != null && extra.contains(k)) return true;

        // Heuristike na sufikse
        return k.endsWith("password")
            || k.endsWith("token")
            || k.endsWith("secret");
    }
}