<?php
declare(strict_types=1);

namespace Itdatex\Rechnungseingang;

if ( ! defined( 'ABSPATH' ) ) { exit; }

/**
 * Erkennt das Format einer Eingangsdatei.
 *
 * - PDF mit eingebettetem XML  -> ZUGFERD
 * - PDF ohne eingebettetes XML -> PDF_LEGACY  (Kandidat fuer KI-Extraktion)
 * - XML mit Root <Invoice>          -> XRECHNUNG_UBL
 * - XML mit Root <CrossIndustryInvoice> -> XRECHNUNG_CII
 *
 * Erkennung ist bewusst tolerant — wir verlassen uns nicht auf
 * MIME-Typen vom Webserver, sondern auf den tatsaechlichen Inhalt.
 */
final class FormatDetector
{
    public static function detect(string $filePath): Format
    {
        if (! is_file($filePath) || ! is_readable($filePath)) {
            throw new \RuntimeException("Datei nicht lesbar: {$filePath}");
        }

        $head = (string) file_get_contents($filePath, false, null, 0, 4096);

        if (str_starts_with($head, '%PDF')) {
            return self::detectFromPdf($filePath);
        }

        if (str_contains($head, '<?xml') || str_starts_with(ltrim($head), '<')) {
            return self::detectFromXml($filePath);
        }

        return Format::UNKNOWN;
    }

    private static function detectFromPdf(string $filePath): Format
    {
        // PdfReader::getXmlFromFile wirft, wenn kein XML eingebettet
        try {
            $xml = \Itdatex\Rechnungseingang\Vendor\horstoeko\zugferd\ZugferdDocumentPdfReader::getXmlFromFile($filePath);
            if ($xml !== '') {
                return Format::ZUGFERD;
            }
        } catch (\Throwable) {
            // Kein eingebettetes XML — Alt-Format
        }
        return Format::PDF_LEGACY;
    }

    private static function detectFromXml(string $filePath): Format
    {
        $previous = libxml_use_internal_errors(true);
        try {
            $doc = new \DOMDocument();
            // LIBXML_NONET schuetzt vor External-Entity-Attacken
            $doc->load($filePath, LIBXML_NONET | LIBXML_NOERROR | LIBXML_NOWARNING);
            $root = $doc->documentElement?->localName ?? '';

            return match ($root) {
                'Invoice'              => Format::XRECHNUNG_UBL,
                'CrossIndustryInvoice' => Format::XRECHNUNG_CII,
                default                => Format::UNKNOWN,
            };
        } finally {
            libxml_clear_errors();
            libxml_use_internal_errors($previous);
        }
    }
}
