package eu.mulk.aendggner.aenderung.parse;

import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Path;
import org.apache.pdfbox.Loader;
import org.apache.tika.Tika;
import org.jboss.logging.Logger;

/**
 * Extrahiert den linearen Text eines Änderungsgesetzes aus einer Eingabedatei.
 *
 * <p>Klartextdateien werden wörtlich übernommen (der dokumentierte Ausweg, wenn die PDF-Extraktion
 * versagt). PDFs werden mit PDFBox in Content-Stream-Reihenfolge extrahiert — BGBl-PDFs zeichnen
 * ihren Text spaltenweise, sodass die Stream-Reihenfolge in der Regel der Lesereihenfolge
 * entspricht, während Positionssortierung die beiden Spalten verschränken würde.
 */
public final class PatchTextExtraktor {

  private static final Logger log = Logger.getLogger(PatchTextExtraktor.class);

  private final Tika tika = new Tika();
  private final SuperskriptModus superskriptModus;

  public PatchTextExtraktor() {
    this(SuperskriptModus.ENTFERNEN);
  }

  public PatchTextExtraktor(SuperskriptModus superskriptModus) {
    this.superskriptModus = superskriptModus;
  }

  public String extrahiere(Path datei) throws IOException {
    var mimeType = tika.detect(datei);
    log.infof("Datei %s hat Typ %s.", datei, mimeType);

    return switch (mimeType) {
      case "application/pdf" -> extrahierePdf(datei);
      case "text/plain" -> Files.readString(datei, StandardCharsets.UTF_8);
      default ->
          throw new IOException(
              "Nicht unterstützter Dateityp %s für %s (unterstützt: PDF, Klartext)"
                  .formatted(mimeType, datei));
    };
  }

  private String extrahierePdf(Path datei) throws IOException {
    try (var dokument = Loader.loadPDF(datei.toFile())) {
      return FontgroessenFilter.extrahiere(dokument, superskriptModus);
    }
  }

  /**
   * Extrahiert die beiden Spalten einer zweispaltigen Seite getrennt und in Lesereihenfolge.
   *
   * <p>Nur für Layouts nötig, deren Spalten im Inhaltsstrom verschränkt stehen — die
   * Zusammenstellung einer Beschlussempfehlung. BGBl- und GVBl-Spalten kommen bereits nacheinander
   * und brauchen das nicht.
   *
   * @return links = Entwurfsspalte, rechts = Ausschussspalte.
   */
  public Spalten extrahiereSpalten(Path datei) throws IOException {
    try (var dokument = Loader.loadPDF(datei.toFile())) {
      return new Spalten(
          FontgroessenFilter.extrahiere(
              dokument, superskriptModus, FontgroessenFilter.Spalte.LINKS),
          FontgroessenFilter.extrahiere(
              dokument, superskriptModus, FontgroessenFilter.Spalte.RECHTS));
    }
  }

  public record Spalten(String links, String rechts) {}
}
