package com.lingniu.ingest.eventhistory.config;

import org.junit.jupiter.api.Test;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.NodeList;

import javax.xml.parsers.DocumentBuilderFactory;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.ArrayList;
import java.util.List;

import static org.assertj.core.api.Assertions.assertThat;

class EventHistoryPomBoundaryTest {

    @Test
    void tdengineJdbcDriverIsOwnedByTdengineHistoryStoreModule() throws Exception {
        assertThat(directDependencies(modulePom()))
                .doesNotContain("com.taosdata.jdbc:taos-jdbcdriver");
    }

    @Test
    void kafkaClientsIsOwnedByKafkaSinkModule() throws Exception {
        for (Path pom : servicePoms()) {
            assertThat(directDependencies(readPom(pom)))
                    .as(pom.toString())
                    .doesNotContain("org.apache.kafka:kafka-clients");
        }
    }

    private static Document modulePom() throws Exception {
        return readPom(repositoryRoot().resolve("modules/services/event-history-service/pom.xml"));
    }

    private static Document readPom(Path pom) throws Exception {
        DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
        factory.setFeature("http://apache.org/xml/features/disallow-doctype-decl", true);
        return factory.newDocumentBuilder().parse(Files.newInputStream(pom));
    }

    private static List<Path> servicePoms() {
        Path services = repositoryRoot().resolve("modules/services");
        return List.of(
                services.resolve("event-history-service/pom.xml"),
                services.resolve("vehicle-state-service/pom.xml"),
                services.resolve("vehicle-stat-service/pom.xml"));
    }

    private static List<String> directDependencies(Document pom) {
        Element dependencies = firstDirectChild(pom.getDocumentElement(), "dependencies");
        if (dependencies == null) {
            return List.of();
        }
        List<String> coordinates = new ArrayList<>();
        NodeList children = dependencies.getChildNodes();
        for (int i = 0; i < children.getLength(); i++) {
            if (!(children.item(i) instanceof Element dependency) || !"dependency".equals(dependency.getTagName())) {
                continue;
            }
            Element groupId = firstDirectChild(dependency, "groupId");
            Element artifactId = firstDirectChild(dependency, "artifactId");
            if (groupId != null && artifactId != null) {
                coordinates.add(groupId.getTextContent().trim() + ":" + artifactId.getTextContent().trim());
            }
        }
        return List.copyOf(coordinates);
    }

    private static Element firstDirectChild(Element parent, String tagName) {
        NodeList children = parent.getChildNodes();
        for (int i = 0; i < children.getLength(); i++) {
            if (children.item(i) instanceof Element child && tagName.equals(child.getTagName())) {
                return child;
            }
        }
        return null;
    }

    private static Path repositoryRoot() {
        Path current = Path.of(System.getProperty("user.dir")).toAbsolutePath();
        while (current != null) {
            if (Files.exists(current.resolve("pom.xml")) && Files.exists(current.resolve("modules"))) {
                return current;
            }
            current = current.getParent();
        }
        throw new IllegalStateException("repository root not found");
    }
}
