package de.roko.genalogy.downloader.database;

import org.jsoup.Jsoup;
import org.jsoup.nodes.Document;
import org.jsoup.nodes.Element;
import org.jsoup.select.Elements;

import java.sql.*;
import java.util.ArrayList;
import java.util.List;

public class KirchenkreisExtractor {

    private static final String DB = "archion.db";

    public void readNwrite() throws Exception {
        try (Connection conn = DriverManager.getConnection("jdbc:sqlite:" + DB)) {
            String sql = "SELECT id, name, link FROM archive ORDER BY id";
            try (PreparedStatement stmt = conn.prepareStatement(sql);
                 ResultSet rs = stmt.executeQuery()) {

                while (rs.next()) {
                    int id = rs.getInt("id");
                    String name = rs.getString("name");
                    String link = rs.getString("link");

                    System.out.println("\n🔍 Lade Struktur für Archiv: " + name);

                    Document doc = Jsoup.connect(link).get();
                    Elements items = doc.select("#archive-nav li.item a");

                    List<Kirchenkreis> kreise = new ArrayList<>();
                    List<Ort> orte = new ArrayList<>();

                    for (Element linkEl : items) {
                        String eintragName = linkEl.text().trim();
                        String href = linkEl.absUrl("href").trim();
                        if (eintragName.isEmpty() || href.isEmpty()) continue;

                        if (isKirchenkreisebene(eintragName)) {
                            kreise.add(new Kirchenkreis(id, eintragName, href));
                        } else {
                            orte.add(new Ort(id, null, eintragName, href));
                        }
                    }

                    saveKirchenkreise(kreise, conn);
                    saveOrte(orte, conn);

                    System.out.println("→ " + kreise.size() + " Kirchenkreise gespeichert.");
                    System.out.println("→ " + orte.size() + " direkte Orte gespeichert.");
                }
            }
        }
    }

    private boolean isKirchenkreisebene(String name) {
        String n = name.toLowerCase();
        return n.contains("kirchenkreis") ||
                n.contains("dekanat") ||
                n.contains("juden") ||
                n.contains("mennoiten") ||
                n.contains("militärseelsorge") ||
                n.contains("reformierte kirche") ||
                n.contains("auslandsgemeinde") ||
                n.contains("thüringen") ||
                n.contains("israeliten") ||
                n.contains("krankenhausseelsorge") ||
                n.contains("kreis") ||
                n.contains("reformierter kirchenkreis") ||
                n.contains("sonderbestände") ||
                n.contains("allgemeine hilfsmittel") ||
                n.contains("allgemeines ortschaftsverzeichnis") ||
                n.contains("kirchenbezirk") ||
                n.contains("hinterpommern") ||
                n.contains("Kirchenbücher der Garnisonen und Militärgemeinden") ||
                n.contains("Regimentskirchenbücher") ||
                n.contains("Zivilregister") ||
                n.contains("militärkirchenbücher");
    }

    public static void saveKirchenkreise(List<Kirchenkreis> list, Connection conn) throws SQLException {
        String sql = """
            INSERT INTO kreis (archiv_id, name, link)
            VALUES (?, ?, ?)
            ON CONFLICT(archiv_id, name)
            DO UPDATE SET link = excluded.link;
            """;

        try (PreparedStatement stmt = conn.prepareStatement(sql)) {
            for (Kirchenkreis k : list) {
                stmt.setInt(1, k.archivId());
                stmt.setString(2, k.name());
                stmt.setString(3, k.link());
                stmt.addBatch();
            }
            stmt.executeBatch();
        }
    }

    public static void saveOrte(List<Ort> list, Connection conn) throws SQLException {
        String sql = """
            INSERT INTO ort (archiv_id, kreis_id, name, link)
            VALUES (?, ?, ?, ?)
            ON CONFLICT(archiv_id, name)
            DO UPDATE SET link = excluded.link;
            """;

        try (PreparedStatement stmt = conn.prepareStatement(sql)) {
            for (Ort o : list) {
                stmt.setInt(1, o.archivId());
                if (o.kreisId() != null)
                    stmt.setInt(2, o.kreisId());
                else
                    stmt.setNull(2, Types.INTEGER);
                stmt.setString(3, o.name());
                stmt.setString(4, o.link());
                stmt.addBatch();
            }
            stmt.executeBatch();
        }
    }

    public record Kirchenkreis(int archivId, String name, String link) {}

    public record Ort(int archivId, Integer kreisId, String name, String link) {}
}
