package com.clanstop.healing.locator;

import org.openqa.selenium.json.Json;

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

/**
 * Serialises {@link Fingerprint} to/from JSON for the {@code element_fingerprint.fingerprint}
 * JSONB column, using Selenium's bundled JSON library (no extra dependency).
 */
public final class FingerprintJson {

    private static final Json JSON = new Json();

    private FingerprintJson() {}

    public static String toJson(Fingerprint fp) {
        Map<String, Object> m = new LinkedHashMap<>();
        m.put("tag", fp.tag());
        m.put("id", fp.id());
        m.put("name", fp.name());
        m.put("classList", fp.classList());
        m.put("visibleText", fp.visibleText());
        m.put("attrs", fp.attrs());
        m.put("cssPath", fp.cssPath());
        m.put("xpath", fp.xpath());
        m.put("centerX", fp.centerX());
        m.put("centerY", fp.centerY());
        m.put("domDepth", fp.domDepth());
        return JSON.toJson(m);
    }

    @SuppressWarnings("unchecked")
    public static Fingerprint fromJson(String json) {
        Map<String, Object> m = JSON.toType(json, Map.class);

        List<String> classes = new ArrayList<>();
        if (m.get("classList") instanceof List<?> cl) {
            for (Object c : cl) {
                classes.add(String.valueOf(c));
            }
        }
        Map<String, String> attrs = new LinkedHashMap<>();
        if (m.get("attrs") instanceof Map<?, ?> am) {
            for (Map.Entry<?, ?> e : am.entrySet()) {
                attrs.put(String.valueOf(e.getKey()), String.valueOf(e.getValue()));
            }
        }
        return new Fingerprint(
                str(m.get("tag")),
                str(m.get("id")),
                str(m.get("name")),
                classes,
                str(m.get("visibleText")),
                attrs,
                str(m.get("cssPath")),
                str(m.get("xpath")),
                dbl(m.get("centerX")),
                dbl(m.get("centerY")),
                (int) Math.round(dbl(m.get("domDepth")))
        );
    }

    private static String str(Object o) { return o == null ? "" : o.toString(); }

    private static double dbl(Object o) {
        return o instanceof Number n ? n.doubleValue() : 0;
    }
}
