<?php
/* Copyright (C) 2026 ZUGFeRD Import Module
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 3 of the License, or
 * (at your option) any later version.
 */

/**
 * \file    import.php
 * \ingroup importzugferd
 * \brief   Manual ZUGFeRD import page with persistent workflow
 */

// Load Dolibarr environment
$res = 0;
if (!$res && !empty($_SERVER["CONTEXT_DOCUMENT_ROOT"])) {
    $res = @include $_SERVER["CONTEXT_DOCUMENT_ROOT"]."/main.inc.php";
}
$tmp = empty($_SERVER['SCRIPT_FILENAME']) ? '' : $_SERVER['SCRIPT_FILENAME'];
$tmp2 = realpath(__FILE__);
$i = strlen($tmp) - 1;
$j = strlen($tmp2) - 1;
while ($i > 0 && $j > 0 && isset($tmp[$i]) && isset($tmp2[$j]) && $tmp[$i] == $tmp2[$j]) {
    $i--;
    $j--;
}
if (!$res && $i > 0 && file_exists(substr($tmp, 0, ($i + 1))."/main.inc.php")) {
    $res = @include substr($tmp, 0, ($i + 1))."/main.inc.php";
}
if (!$res && $i > 0 && file_exists(dirname(substr($tmp, 0, ($i + 1)))."/main.inc.php")) {
    $res = @include dirname(substr($tmp, 0, ($i + 1)))."/main.inc.php";
}
if (!$res && file_exists("../main.inc.php")) {
    $res = @include "../main.inc.php";
}
if (!$res && file_exists("../../main.inc.php")) {
    $res = @include "../../main.inc.php";
}
if (!$res && file_exists("../../../main.inc.php")) {
    $res = @include "../../../main.inc.php";
}
if (!$res) {
    die("Include of main fails");
}

require_once DOL_DOCUMENT_ROOT.'/core/lib/files.lib.php';
require_once DOL_DOCUMENT_ROOT.'/core/class/html.formfile.class.php';
require_once DOL_DOCUMENT_ROOT.'/societe/class/societe.class.php';
require_once DOL_DOCUMENT_ROOT.'/product/class/product.class.php';
require_once DOL_DOCUMENT_ROOT.'/fourn/class/fournisseur.facture.class.php';

dol_include_once('/importzugferd/class/zugferdparser.class.php');
dol_include_once('/importzugferd/class/zugferdimport.class.php');
dol_include_once('/importzugferd/class/importline.class.php');
dol_include_once('/importzugferd/class/productmapping.class.php');
dol_include_once('/importzugferd/class/actions_importzugferd.class.php');
dol_include_once('/importzugferd/class/datanorm.class.php');
dol_include_once('/importzugferd/class/datanormparser.class.php');
dol_include_once('/importzugferd/class/importnotification.class.php');
dol_include_once('/importzugferd/lib/importzugferd.lib.php');

// Load translation files
$langs->loadLangs(array("importzugferd@importzugferd", "bills", "products", "companies"));

// Security check
if (!$user->hasRight('importzugferd', 'import', 'write')) {
    accessforbidden();
}

// Get parameters
$action = GETPOST('action', 'aZ09');
$confirm = GETPOST('confirm', 'alpha');
$id = GETPOST('id', 'int');  // Import ID for editing existing imports
$supplier_id = GETPOST('supplier_id', 'int');
$line_id = GETPOST('line_id', 'int');
$product_id = GETPOST('product_id', 'int');
$template_product_id = GETPOST('template_product_id', 'int');
// Zeilenspezifische Produkt-IDs (wegen eindeutiger select2-IDs pro Zeile)
if (empty($product_id) && $line_id > 0) {
    $product_id = GETPOST('product_id_'.$line_id, 'int');
}
if (empty($template_product_id) && $line_id > 0) {
    $template_product_id = GETPOST('template_product_id_'.$line_id, 'int');
}

// Initialize objects
$form = new Form($db);
$formfile = new FormFile($db);
$actions = new ActionsImportZugferd($db);
$import = new ZugferdImport($db);
$importLine = new ImportLine($db);
$notification = new ImportNotification($db);

$error = 0;
$message = '';

/*
 * Helper-Funktionen (DRY)
 */

/**
 * Parse Aderanzahl und Querschnitt aus Kabelbezeichnung
 * Erkennt Formate wie: NYM-J 3x2,5 / NYM-J 5x1.5 / H07V-K 1x4 / J-Y(ST)Y 2x2x0,8 etc.
 *
 * @param string $text Kabelbezeichnung (z.B. "NYM-J 3x2,5 Eca Ri100")
 * @return array|null Array mit 'aderanzahl', 'querschnitt' oder null wenn kein Kabel
 */
function parseCableSpecsFromText($text)
{
    // Spezialfall: Fernmeldekabel wie J-Y(ST)Y 2x2x0,8 (Paare x Adern pro Paar x Querschnitt)
    // Pattern: Zahl x Zahl x Zahl (z.B. 2x2x0,8 = 4 Adern mit 0,8mm²)
    if (preg_match('/(\d+)\s*[xX]\s*(\d+)\s*[xX]\s*(\d+(?:[,\.]\d+)?)/', $text, $matches)) {
        $paare = (int) $matches[1];
        $adernProPaar = (int) $matches[2];
        $querschnitt = (float) str_replace(',', '.', $matches[3]);
        $aderanzahl = $paare * $adernProPaar;

        // Plausibilitätsprüfung
        if ($aderanzahl >= 1 && $aderanzahl <= 200 && $querschnitt >= 0.14 && $querschnitt <= 400) {
            return array(
                'aderanzahl' => $aderanzahl,
                'querschnitt' => $querschnitt
            );
        }
    }

    // Standard: NYM-J 3x2,5 (Adern x Querschnitt)
    // Pattern: Zahl x Zahl (mit Komma oder Punkt als Dezimaltrenner)
    if (preg_match('/(\d+)\s*[xX]\s*(\d+(?:[,\.]\d+)?)/', $text, $matches)) {
        $aderanzahl = (int) $matches[1];
        $querschnitt = (float) str_replace(',', '.', $matches[2]);

        // Plausibilitätsprüfung
        if ($aderanzahl >= 1 && $aderanzahl <= 100 && $querschnitt >= 0.5 && $querschnitt <= 400) {
            return array(
                'aderanzahl' => $aderanzahl,
                'querschnitt' => $querschnitt
            );
        }
    }
    return null;
}

/**
 * Berechne Kupfergehalt aus Aderanzahl und Querschnitt
 * Formel: Aderanzahl × Querschnitt × 8.9 (Dichte Kupfer) = kg/km
 *
 * @param int $aderanzahl Anzahl der Adern
 * @param float $querschnitt Querschnitt in mm²
 * @return float Kupfergehalt in kg/km
 */
function calculateKupfergehalt($aderanzahl, $querschnitt)
{
    // Kupferdichte: 8.9 g/cm³ = 8.9 kg/dm³
    // 1 mm² × 1 km = 1 mm² × 1000m = 1000 mm³ = 1 cm³
    // Also: 1 mm² Querschnitt × 1 km Länge = 1000 cm³ = 1 dm³ = 8.9 kg
    return $aderanzahl * $querschnitt * 8.9;
}

/**
 * Hole aktuellen Kupferpreis aus Metallzuschlag-Modul
 *
 * @param DoliDB $db Datenbank
 * @param int $supplierId Lieferanten-ID (optional, für lieferantenspezifischen Preis)
 * @return float CU-Notiz in EUR/100kg oder 0 wenn nicht verfügbar
 */
function getCurrentCopperPrice($db, $supplierId = 0)
{
    // Erst prüfen ob Metallzuschlag-Modul aktiv ist
    if (!isModEnabled('metallzuschlag')) {
        return 0;
    }

    // Lieferanten-spezifischer CU-Wert (aus societe_extrafields)
    if ($supplierId > 0) {
        $sql = "SELECT metallzuschlag_cu FROM ".MAIN_DB_PREFIX."societe_extrafields";
        $sql .= " WHERE fk_object = ".(int)$supplierId;
        $resql = $db->query($sql);
        if ($resql && $db->num_rows($resql) > 0) {
            $obj = $db->fetch_object($resql);
            if (!empty($obj->metallzuschlag_cu) && (float)$obj->metallzuschlag_cu > 0) {
                return (float)$obj->metallzuschlag_cu;
            }
        }
    }

    // Fallback: Aktuellster CU-Wert aus History
    $sql = "SELECT value FROM ".MAIN_DB_PREFIX."metallzuschlag_history";
    $sql .= " WHERE metal = 'CU' ORDER BY date_notiz DESC LIMIT 1";
    $resql = $db->query($sql);
    if ($resql && $db->num_rows($resql) > 0) {
        $obj = $db->fetch_object($resql);
        return (float)$obj->value;
    }

    return 0;
}

/**
 * Berechne Kupferzuschlag für eine bestimmte Menge
 * Formel: Kupfergehalt (kg/km) × CU (EUR/100kg) / 100000 × Menge
 *
 * @param float $kupfergehalt Kupfergehalt in kg/km
 * @param float $cuPrice CU-Notiz in EUR/100kg
 * @param float $quantity Menge (z.B. 100 für 100m)
 * @return float Kupferzuschlag in EUR
 */
function calculateKupferzuschlag($kupfergehalt, $cuPrice, $quantity = 1)
{
    if ($kupfergehalt <= 0 || $cuPrice <= 0) {
        return 0;
    }
    // kg/km × EUR/100kg / 100000 × m = EUR
    return round($kupfergehalt * $cuPrice / 100000 * $quantity, 2);
}

/**
 * Prüft ob ein Produkt ein Kabel ist (basierend auf Warengruppe oder Bezeichnung)
 *
 * @param Datanorm $datanorm Datanorm-Objekt
 * @return bool True wenn Kabel
 */
function isCableProduct($datanorm)
{
    // Warengruppen die typisch für Kabel sind
    $cableGroups = array('KAB', 'KABEL', 'LEI', 'LEIT', 'LEITUNG');

    if (!empty($datanorm->product_group)) {
        $group = strtoupper(substr($datanorm->product_group, 0, 5));
        foreach ($cableGroups as $cg) {
            if (strpos($group, $cg) !== false) {
                return true;
            }
        }
    }

    // Typische Kabelbezeichnungen
    $cablePatterns = array(
        '/NYM[-\s]?[JYOA]/i',
        '/NYY[-\s]?[JO]/i',
        '/H0[357]V[-\s]?[KUR]/i',
        '/H0[357]RN[-\s]?F/i',
        '/NHXH/i',
        '/J[-\s]?Y\(ST\)Y/i',
        '/LiYCY/i',
        '/ÖLFLEX/i',
    );

    $text = $datanorm->short_text1 . ' ' . $datanorm->short_text2;
    foreach ($cablePatterns as $pattern) {
        if (preg_match($pattern, $text)) {
            return true;
        }
    }

    return false;
}

/**
 * Ringgröße aus Kabel-Bezeichnung extrahieren
 * Erkennt Muster wie: Ri100, Ri.50, Ri 100, Ring100, Tr500, Fol.25m, "Ring 100m", "Trommel 500m"
 *
 * WICHTIG: Nur verwenden wenn price_unit = 1!
 * Bei price_unit > 1 ist das bereits die korrekte Preiseinheit (z.B. 100 für 100m)
 *
 * @param string $text Produktbezeichnung
 * @return int Ringgröße in Metern (0 wenn nicht gefunden)
 */
function extractCableRingSize($text)
{
    // Muster für Ringgröße: Ri100, Ri.50, Ri 100, Ring100, Ring 50
    if (preg_match('/Ri(?:ng)?[.\s]?(\d+)/i', $text, $matches)) {
        return (int)$matches[1];
    }
    // Muster für "Ring 100m", "Ring 50 m"
    if (preg_match('/Ring\s+(\d+)\s*m/i', $text, $matches)) {
        return (int)$matches[1];
    }
    // Muster für Trommel: Tr500, Tr.500, Trommel500, "Trommel 500m"
    if (preg_match('/Tr(?:ommel)?[.\s]?(\d+)/i', $text, $matches)) {
        return (int)$matches[1];
    }
    if (preg_match('/Trommel\s+(\d+)\s*m/i', $text, $matches)) {
        return (int)$matches[1];
    }
    // Muster für Folie/Rolle: Fol.25m, Fol25, Rol.50m
    if (preg_match('/(?:Fol|Rol)[.\s]?(\d+)/i', $text, $matches)) {
        return (int)$matches[1];
    }
    return 0;
}

/**
 * Berechne Kabelpreis unter Berücksichtigung unterschiedlicher Lieferanten-Formate
 *
 * Logik:
 * - Kluxen/Witte/eltric: price_unit > 1 (z.B. 100) → Preis ist für 100m
 * - Sonepar: price_unit = 1 → Preis ist für kompletten Ring (Größe aus Name)
 *
 * @param Datanorm $datanorm Datanorm-Objekt
 * @param float $minQty Mindestbestellmenge (default 1)
 * @return array Array mit 'unitPrice', 'totalPrice', 'priceUnit'
 */
function calculateCablePricing($datanorm, $minQty = 1)
{
    $priceUnit = $datanorm->price_unit > 0 ? $datanorm->price_unit : 1;
    $cableText = $datanorm->short_text1 . ' ' . $datanorm->short_text2;

    if ($priceUnit > 1) {
        // Kluxen/Witte-Format: price_unit gibt die Preiseinheit an (z.B. 100m)
        $unitPrice = $datanorm->price / $priceUnit;
        $effectivePriceUnit = $priceUnit;
    } else {
        // Sonepar-Format: price_unit = 1, aber Preis ist für kompletten Ring
        $ringSize = extractCableRingSize($cableText);
        if ($ringSize > 0) {
            $unitPrice = $datanorm->price / $ringSize;
            $effectivePriceUnit = $ringSize;
        } else {
            // Einzelstück
            $unitPrice = $datanorm->price;
            $effectivePriceUnit = 1;
        }
    }

    // Schutz gegen Division durch Null
    $effectivePriceUnit = max(1, $effectivePriceUnit);

    return array(
        'unitPrice' => $unitPrice,
        'totalPrice' => $unitPrice * $minQty,
        'priceUnit' => $effectivePriceUnit
    );
}

/**
 * Extrafields fuer Lieferantenpreis aus Datanorm-Daten zusammenstellen
 *
 * @param Datanorm $datanorm Datanorm-Objekt
 * @param ImportLine|null $lineObj Import-Zeile (optional, fuer ZUGFeRD-Daten)
 * @return array Extrafields-Array
 */
function datanormBuildSupplierPriceExtrafields($datanorm, $lineObj = null)
{
    $extrafields = array();

    // Produktpreis (reiner Materialpreis ohne Kupferzuschlag) - nur bei Kabeln mit Metallzuschlag
    // Der Preis ist bereits auf Mindestmenge (price_unit) bezogen
    if (!empty($datanorm->metal_surcharge) && $datanorm->metal_surcharge > 0 && !empty($datanorm->price)) {
        $extrafields['options_produktpreis'] = $datanorm->price;
    }

    // Preiseinheit
    if (!empty($datanorm->price_unit) && $datanorm->price_unit > 1) {
        $extrafields['options_preiseinheit'] = $datanorm->price_unit;
    } elseif ($lineObj && !empty($lineObj->basis_quantity) && $lineObj->basis_quantity > 1) {
        $extrafields['options_preiseinheit'] = $lineObj->basis_quantity;
    }
    // Warengruppe
    if (!empty($datanorm->product_group)) {
        $extrafields['options_warengruppe'] = $datanorm->product_group;
    }
    return $extrafields;
}

/**
 * Lieferantenpreis aus Datanorm hinzufuegen
 *
 * @param DoliDB $db Datenbank
 * @param int $productId Produkt-ID
 * @param Datanorm $datanorm Datanorm-Objekt
 * @param Societe $supplier Lieferant-Objekt
 * @param User $user Benutzer
 * @param float $purchasePrice Einkaufspreis
 * @param float $taxPercent MwSt-Satz
 * @param array $extrafields Extrafields
 * @return int >0 bei Erfolg, <0 bei Fehler
 */
function datanormAddSupplierPrice($db, $productId, $datanorm, $supplier, $user, $purchasePrice, $taxPercent = 19, $extrafields = array())
{
    require_once DOL_DOCUMENT_ROOT.'/fourn/class/fournisseur.product.class.php';

    $prodfourn = new ProductFournisseur($db);
    $prodfourn->id = $productId;

    $supplierEan = !empty($datanorm->ean) ? $datanorm->ean : '';
    $supplierEanType = !empty($datanorm->ean) ? 2 : 0;
    $description = trim($datanorm->short_text1 . ($datanorm->short_text2 ? ' ' . $datanorm->short_text2 : ''));

    // Mindestbestellmenge und Verpackungseinheit vom bestehenden Lieferantenpreis übernehmen
    // (gleiches Produkt = gleiche Mengen, nur anderer Lieferant)
    $minQty = 1;
    $packaging = null;

    $sqlExisting = "SELECT quantity, packaging FROM " . MAIN_DB_PREFIX . "product_fournisseur_price";
    $sqlExisting .= " WHERE fk_product = " . (int)$productId;
    $sqlExisting .= " AND quantity > 0";
    $sqlExisting .= " ORDER BY rowid ASC LIMIT 1";
    $resExisting = $db->query($sqlExisting);
    if ($resExisting && $db->num_rows($resExisting) > 0) {
        $objExisting = $db->fetch_object($resExisting);
        if ($objExisting->quantity > 0) {
            $minQty = $objExisting->quantity;
        }
        if (!empty($objExisting->packaging)) {
            $packaging = $objExisting->packaging;
        }
    }

    // Preis berechnen mit zentraler Funktion
    $pricing = calculateCablePricing($datanorm, $minQty);
    $totalPrice = $pricing['totalPrice'];

    $result = $prodfourn->update_buyprice(
        $minQty, $totalPrice, $user, 'HT', $supplier, 0,
        $datanorm->article_number, $taxPercent,
        0, 0, 0, 0, 0, 0, array(), '',
        0, 'HT', 1, '',
        $description, $supplierEan, $supplierEanType,
        $extrafields
    );

    // Verpackungseinheit nachträglich setzen (nicht in update_buyprice verfügbar)
    if ($result > 0 && !empty($packaging)) {
        $sqlPkg = "UPDATE " . MAIN_DB_PREFIX . "product_fournisseur_price";
        $sqlPkg .= " SET packaging = " . (float)$packaging;
        $sqlPkg .= " WHERE rowid = " . (int)$result;
        $db->query($sqlPkg);
    }

    return $result;
}

/**
 * Extrafields in product_fournisseur_price_extrafields einfuegen
 *
 * @param DoliDB $db Datenbank
 * @param int $priceId ID des Lieferantenpreises
 * @param array $extrafields Extrafields-Array
 */
function datanormInsertPriceExtrafields($db, $priceId, $extrafields)
{
    if (empty($priceId) || empty($extrafields)) {
        return;
    }
    // Note: kupferzuschlag is NOT set here - it's calculated by a separate module
    // based on copper content (kupfergehalt) and current copper price
    $produktpreis = !empty($extrafields['options_produktpreis']) ? (float)$extrafields['options_produktpreis'] : 'NULL';
    $preiseinheit = !empty($extrafields['options_preiseinheit']) ? (int)$extrafields['options_preiseinheit'] : 1;
    $warengruppe = !empty($extrafields['options_warengruppe']) ? "'".$db->escape($extrafields['options_warengruppe'])."'" : 'NULL';

    // Pruefen ob bereits vorhanden
    $sqlCheck = "SELECT rowid FROM ".MAIN_DB_PREFIX."product_fournisseur_price_extrafields WHERE fk_object = ".(int)$priceId;
    $resCheck = $db->query($sqlCheck);
    if ($resCheck && $db->num_rows($resCheck) > 0) {
        // Update statt Insert wenn bereits vorhanden
        $sql = "UPDATE ".MAIN_DB_PREFIX."product_fournisseur_price_extrafields SET ";
        $sql .= "produktpreis = ".($produktpreis === 'NULL' ? "NULL" : $produktpreis).", ";
        $sql .= "preiseinheit = ".$preiseinheit.", ";
        $sql .= "warengruppe = ".$warengruppe." ";
        $sql .= "WHERE fk_object = ".(int)$priceId;
        if (!$db->query($sql)) {
            dol_syslog('ImportZugferd: Fehler beim Update der Extrafields: '.$db->lasterror(), LOG_ERR);
        }
        return;
    }

    $sql = "INSERT INTO ".MAIN_DB_PREFIX."product_fournisseur_price_extrafields";
    $sql .= " (fk_object, produktpreis, preiseinheit, warengruppe) VALUES (";
    $sql .= (int)$priceId.", ";
    $sql .= ($produktpreis === 'NULL' ? "NULL" : $produktpreis).", ";
    $sql .= $preiseinheit.", ";
    $sql .= $warengruppe.")";
    if (!$db->query($sql)) {
        dol_syslog('ImportZugferd: Fehler beim Einfuegen der Extrafields: '.$db->lasterror(), LOG_ERR);
    }
}

/*
 * Actions
 */

// AJAX: Get raw Datanorm lines for debugging
if ($action == 'get_raw_lines' && GETPOST('article_number', 'alphanohtml')) {
    header('Content-Type: application/json');
    $article_number = GETPOST('article_number', 'alphanohtml');
    $ajax_fk_soc = GETPOSTINT('fk_soc');

    $result = array(
        'datanorm_line' => '',
        'datpreis_line' => '',
        'article_number' => $article_number
    );

    // Get the upload directory for this supplier
    $upload_dir = $conf->importzugferd->dir_output.'/datanorm/'.$ajax_fk_soc;

    if (is_dir($upload_dir)) {
        $allFiles = glob($upload_dir . '/*');

        // Search in DATANORM files
        foreach ($allFiles as $file) {
            $basename = strtoupper(basename($file));
            if (preg_match('/^DATANORM\.\d{3}$/', $basename)) {
                $handle = fopen($file, 'r');
                if ($handle) {
                    while (($line = fgets($handle)) !== false) {
                        // A-Satz starts with A; and contains the article number
                        if (preg_match('/^A;/', $line)) {
                            $parts = explode(';', $line);
                            if (isset($parts[2]) && trim($parts[2]) == $article_number) {
                                $result['datanorm_line'] = trim($line);
                                break;
                            }
                        }
                    }
                    fclose($handle);
                }
                if (!empty($result['datanorm_line'])) break;
            }
        }

        // Search in DATPREIS files
        foreach ($allFiles as $file) {
            $basename = strtoupper(basename($file));
            if (preg_match('/^DATPREIS\.\d{3}$/', $basename)) {
                $handle = fopen($file, 'r');
                if ($handle) {
                    while (($line = fgets($handle)) !== false) {
                        // P-Satz contains article numbers at various positions
                        if (preg_match('/^P;/', $line) && strpos($line, $article_number) !== false) {
                            $result['datpreis_line'] = trim($line);
                            break;
                        }
                    }
                    fclose($handle);
                }
                if (!empty($result['datpreis_line'])) break;
            }
        }

        $result['upload_dir'] = $upload_dir;
    } else {
        $result['error'] = 'Upload directory not found: ' . $upload_dir;
    }

    echo json_encode($result);
    exit;
}

// Upload and parse PDF - creates import record immediately
if ($action == 'upload') {
    if (!empty($_FILES['zugferd_file']['tmp_name'])) {
        $upload_dir = $conf->importzugferd->dir_output.'/temp';
        if (!is_dir($upload_dir)) {
            dol_mkdir($upload_dir);
        }

        $filename = dol_sanitizeFileName($_FILES['zugferd_file']['name']);
        $destfile = $upload_dir.'/'.$filename;

        if (move_uploaded_file($_FILES['zugferd_file']['tmp_name'], $destfile)) {
            $force_reimport = GETPOST('force_reimport', 'int');

            // Check for duplicate
            $file_hash = hash_file('sha256', $destfile);
            $isDuplicate = $import->isDuplicate($file_hash);

            if ($isDuplicate && !$force_reimport) {
                $error++;
                $message = $langs->trans('ErrorDuplicateInvoice');
                @unlink($destfile);
            } else {
                // If force reimport, delete the old record first
                if ($isDuplicate && $force_reimport) {
                    $oldImport = new ZugferdImport($db);
                    $oldImport->fetch(0, null, $file_hash);
                    if ($oldImport->id > 0) {
                        $db->begin();
                        // Alten Import-Datensatz komplett loeschen (Transaktion)
                        $oldLines = new ImportLine($db);
                        $oldLines->deleteAllByImport($oldImport->id);
                        $old_dir = $conf->importzugferd->dir_output.'/imports/'.$oldImport->id;
                        if (is_dir($old_dir)) {
                            dol_delete_dir_recursive($old_dir);
                        }
                        $oldImport->delete($user);
                        $db->commit();
                    }
                }
                // Parse the file
                $parser = new ZugferdParser($db);
                $res = $parser->extractFromPdf($destfile);

                if ($res > 0) {
                    $res = $parser->parse();
                    if ($res > 0) {
                        $parsed_data = $parser->getInvoiceData();

                        // Create import record immediately
                        $import->invoice_number = $parsed_data['invoice_number'];
                        $import->invoice_date = $parsed_data['invoice_date'];
                        $import->seller_name = $parsed_data['seller']['name'];
                        $import->seller_vat = $parsed_data['seller']['vat_id'];
                        $import->buyer_reference = $parsed_data['buyer']['reference'] ?: $parsed_data['buyer']['id'];
                        $import->total_ht = $parsed_data['totals']['net'];
                        $import->total_ttc = $parsed_data['totals']['gross'];
                        $import->currency = $parsed_data['totals']['currency'];
                        $import->xml_content = $parser->getXmlContent();
                        $import->pdf_filename = $filename;
                        $import->file_hash = $file_hash;

                        // Find supplier
                        $supplier_id = $actions->findSupplier($parsed_data);
                        $import->fk_soc = $supplier_id;

                        // Process line items to find products
                        $processed_lines = $actions->processLineItems($parsed_data['lines'], $supplier_id);

                        // Check if all lines have products
                        $all_have_products = true;
                        $has_any_product = false;
                        $total_lines = count($processed_lines);
                        foreach ($processed_lines as $line) {
                            if ($line['fk_product'] <= 0) {
                                $all_have_products = false;
                            } else {
                                $has_any_product = true;
                            }
                        }

                        // Set status based on product matching
                        // STATUS_IMPORTED only if: supplier found, has lines, ALL lines have products
                        if ($all_have_products && $supplier_id > 0 && $total_lines > 0 && $has_any_product) {
                            $import->status = ZugferdImport::STATUS_IMPORTED;
                        } else {
                            $import->status = ZugferdImport::STATUS_PENDING;
                        }

                        $import->date_creation = dol_now();
                        $result = $import->create($user);

                        if ($result > 0) {
                            // Store line items in database
                            foreach ($processed_lines as $line) {
                                $importLineObj = new ImportLine($db);
                                $importLineObj->fk_import = $import->id;
                                $importLineObj->line_id = $line['line_id'];
                                $importLineObj->supplier_ref = $line['supplier_ref'];
                                $importLineObj->product_name = $line['name'];
                                $importLineObj->description = $line['description'];
                                $importLineObj->quantity = $line['quantity'];
                                $importLineObj->unit_code = $line['unit_code'];
                                $importLineObj->unit_price = $line['unit_price'];
                                $importLineObj->unit_price_raw = $line['unit_price_raw'];
                                $importLineObj->basis_quantity = $line['basis_quantity'];
                                $importLineObj->basis_quantity_unit = $line['basis_quantity_unit'];
                                $importLineObj->line_total = $line['line_total'];
                                $importLineObj->tax_percent = $line['tax_percent'];
                                $importLineObj->ean = $line['ean'];
                                $importLineObj->fk_product = $line['fk_product'];
                                $importLineObj->match_method = $line['match_method'];
                                $importLineObj->create($user);
                            }

                            // Move PDF to permanent storage
                            $final_dir = $conf->importzugferd->dir_output.'/imports/'.$import->id;
                            if (!is_dir($final_dir)) {
                                dol_mkdir($final_dir);
                            }
                            if (!@rename($destfile, $final_dir.'/'.$filename)) {
                                // Fallback: copy + delete (z.B. bei verschiedenen Dateisystemen)
                                if (@copy($destfile, $final_dir.'/'.$filename)) {
                                    @unlink($destfile);
                                } else {
                                    dol_syslog('ImportZugferd: Fehler beim Verschieben der PDF nach '.$final_dir, LOG_ERR);
                                }
                            }

                            // Send notification if manual intervention required
                            if ($import->status == ZugferdImport::STATUS_PENDING) {
                                $storedLines = $importLine->fetchAllByImport($import->id);
                                $notification->sendManualInterventionNotification($import, $storedLines);
                            }

                            // Check for price differences
                            if ($import->status == ZugferdImport::STATUS_IMPORTED) {
                                $storedLines = $importLine->fetchAllByImport($import->id);
                                $notification->checkAndNotifyPriceDifferences($import, $storedLines);
                            }

                            // Redirect to edit page
                            $id = $import->id;
                            $action = 'edit';
                            setEventMessages($langs->trans('ImportRecordCreated'), null, 'mesgs');
                        } else {
                            $error++;
                            $message = $import->error;
                            @unlink($destfile);
                            // Send error notification
                            $notification->sendErrorNotification($import, $message, $filename);
                        }
                    } else {
                        $error++;
                        $message = $parser->error;
                        @unlink($destfile);
                    }
                } else {
                    $error++;
                    $message = $parser->error;
                    @unlink($destfile);
                }
            }
        } else {
            $error++;
            $message = $langs->trans('ErrorFileUploadFailed');
        }
    } else {
        $error++;
        $message = $langs->trans('ErrorNoFileUploaded');
    }
}

// Load existing import for editing
if ($id > 0 && empty($action)) {
    $action = 'edit';
}

if ($action == 'edit' && $id > 0) {
    $result = $import->fetch($id);
    if ($result <= 0) {
        $error++;
        $message = $langs->trans('ErrorRecordNotFound');
        $action = '';
    }
}

// Assign product to line
if ($action == 'assignproduct' && $line_id > 0 && $product_id > 0) {
    $lineObj = new ImportLine($db);
    $result = $lineObj->fetch($line_id);
    if ($result > 0) {
        $lineObj->setProduct($product_id, $langs->trans('ManualAssignment'), $user);
        setEventMessages($langs->trans('ProductAssigned'), null, 'mesgs');

        // Get import ID to reload
        $id = $lineObj->fk_import;

        // Check if all lines now have products
        $allHaveProducts = $importLine->allLinesHaveProducts($id);
        if ($allHaveProducts) {
            // Update import status
            $import->fetch($id);
            if ($import->status == ZugferdImport::STATUS_PENDING) {
                $import->status = ZugferdImport::STATUS_IMPORTED;
                $import->update($user);

                // Check for price differences now that all products are assigned
                $storedLines = $importLine->fetchAllByImport($id);
                $notification->checkAndNotifyPriceDifferences($import, $storedLines);
            }
        }
    }
    $action = 'edit';
    $import->fetch($id);
}

// Remove product assignment from line
if ($action == 'removeproduct' && $line_id > 0) {
    $lineObj = new ImportLine($db);
    $result = $lineObj->fetch($line_id);
    if ($result > 0) {
        $id = $lineObj->fk_import;
        $lineObj->setProduct(0, '', $user);
        setEventMessages($langs->trans('ProductRemoved'), null, 'mesgs');

        // Update import status to pending
        $import->fetch($id);
        if ($import->status == ZugferdImport::STATUS_IMPORTED) {
            $import->status = ZugferdImport::STATUS_PENDING;
            $import->update($user);
        }
    }
    $action = 'edit';
    $import->fetch($id);
}

// Fehlende Lieferantenpreise aus anderen Katalogen hinzufuegen
if ($action == 'addmissingprices' && $id > 0) {
    $import->fetch($id);
    $selectedPrices = GETPOST('add_prices', 'array');

    if (!empty($selectedPrices)) {
        $addedCount = 0;
        $errorCount = 0;
        $processedKeys = array();

        foreach ($selectedPrices as $entry) {
            // Duplikate ueberspringen
            if (isset($processedKeys[$entry])) {
                continue;
            }
            $processedKeys[$entry] = true;

            $parts = explode(',', $entry);
            if (count($parts) !== 3) {
                continue;
            }
            $productId = (int) $parts[0];
            $socId = (int) $parts[1];
            $datanormId = (int) $parts[2];

            if ($productId <= 0 || $socId <= 0 || $datanormId <= 0) {
                continue;
            }

            $datanorm = new Datanorm($db);
            if ($datanorm->fetch($datanormId) > 0) {
                $altSupplier = new Societe($db);
                $altSupplier->fetch($socId);

                $priceExtrafields = datanormBuildSupplierPriceExtrafields($datanorm);
                $result = datanormAddSupplierPrice($db, $productId, $datanorm, $altSupplier, $user, 0, 19, $priceExtrafields);

                if ($result > 0) {
                    datanormInsertPriceExtrafields($db, $result, $priceExtrafields);

                    $mapping = new ProductMapping($db);
                    $mapping->fk_soc = $socId;
                    $mapping->supplier_ref = $datanorm->article_number;
                    $mapping->fk_product = $productId;
                    $mapping->ean = $datanorm->ean;
                    $mapping->manufacturer_ref = $datanorm->manufacturer_ref;
                    $mapping->description = $datanorm->short_text1;
                    $mapping->create($user);

                    $addedCount++;
                } else {
                    $errorCount++;
                    dol_syslog('ImportZugferd addmissingprices: Fehler bei Lieferantenpreis product='.$productId.' supplier='.$socId, LOG_ERR);
                }
            }
        }

        if ($addedCount > 0) {
            setEventMessages($langs->trans('SupplierPricesAdded', $addedCount), null, 'mesgs');
        }
        if ($errorCount > 0) {
            setEventMessages($addedCount.' hinzugefuegt, '.$errorCount.' Fehler', null, 'warnings');
        }
    } else {
        setEventMessages('Keine Preise ausgewählt', null, 'warnings');
    }
    $action = 'edit';
}

// Update supplier
if ($action == 'setsupplier' && $id > 0) {
    $import->fetch($id);
    $import->fk_soc = $supplier_id;
    $import->update($user);
    setEventMessages($langs->trans('SupplierUpdated'), null, 'mesgs');
    $action = 'edit';
}

// Duplicate product from template
if ($action == 'duplicateproduct' && $template_product_id > 0 && $line_id > 0) {
    $lineObj = new ImportLine($db);
    $result = $lineObj->fetch($line_id);

    if ($result > 0) {
        // Load template product
        $template = new Product($db);
        if ($template->fetch($template_product_id) > 0) {
            // Create new product as copy
            $newproduct = new Product($db);

            // Copy basic properties from template
            $newproduct->type = $template->type;
            $newproduct->status = $template->status;
            $newproduct->status_buy = $template->status_buy;
            $newproduct->status_batch = $template->status_batch;
            $newproduct->fk_product_type = $template->fk_product_type;
            $newproduct->price = $lineObj->unit_price;
            $newproduct->price_base_type = 'HT';
            $newproduct->tva_tx = $lineObj->tax_percent ?: $template->tva_tx;
            $newproduct->weight = $template->weight;
            $newproduct->weight_units = $template->weight_units;
            $newproduct->fk_unit = $template->fk_unit;

            // Set label from ZUGFeRD
            $newproduct->label = $lineObj->product_name;

            // Generate unique ref
            $newproduct->ref = 'NEW-'.dol_print_date(dol_now(), '%Y%m%d%H%M%S');

            // Build description with ZUGFeRD data
            $zugferd_info = '';
            if (!empty($lineObj->supplier_ref)) {
                $zugferd_info .= $langs->trans('SupplierRef').': '.$lineObj->supplier_ref."\n";
            }
            if (!empty($lineObj->unit_code)) {
                $zugferd_info .= $langs->trans('Unit').': '.zugferdGetUnitLabel($lineObj->unit_code)."\n";
            }
            if (!empty($lineObj->ean)) {
                $zugferd_info .= 'EAN: '.$lineObj->ean."\n";
            }
            $zugferd_info .= "---\n";
            $newproduct->description = $zugferd_info . ($template->description ?: '');

            // Create the product
            $result = $newproduct->create($user);
            if ($result > 0) {
                setEventMessages($langs->trans('ProductCreated'), null, 'mesgs');
                // Redirect to product card for editing
                header('Location: '.DOL_URL_ROOT.'/product/card.php?id='.$result);
                exit;
            } else {
                setEventMessages($newproduct->error, $newproduct->errors, 'errors');
            }
        }
        $id = $lineObj->fk_import;
    }
    $action = 'edit';
    $import->fetch($id);
}

// Create product from Datanorm
if ($action == 'createfromdatanorm' && $line_id > 0) {
    $lineObj = new ImportLine($db);
    $result = $lineObj->fetch($line_id);

    if ($result > 0) {
        $id = $lineObj->fk_import;
        $import->fetch($id);

        // Get Datanorm settings
        $markup = getDolGlobalString('IMPORTZUGFERD_DATANORM_MARKUP', 30);
        $searchAll = getDolGlobalString('IMPORTZUGFERD_DATANORM_SEARCH_ALL', 0);

        // Search in Datanorm database
        $datanorm = new Datanorm($db);
        $results = $datanorm->searchByArticleNumber($lineObj->supplier_ref, $import->fk_soc, $searchAll, 1);

        if (empty($results)) {
            // Try with EAN if available
            if (!empty($lineObj->ean)) {
                $results = $datanorm->searchByArticleNumber($lineObj->ean, $import->fk_soc, $searchAll, 1);
            }
        }

        if (!empty($results)) {
            $datanormArticle = $results[0];
            $datanorm->fetch($datanormArticle['id']);

            // Load supplier for ref prefix
            $supplier = new Societe($db);
            $supplier->fetch($import->fk_soc);
            $supplierPrefix = strtoupper(substr(preg_replace('/[^a-zA-Z]/', '', $supplier->name), 0, 3));

            // Create new product
            $newproduct = new Product($db);
            $newproduct->type = 0; // Product
            $newproduct->status = 1; // On sale
            $newproduct->status_buy = 1; // On purchase

            // Generate reference
            $newproduct->ref = 'NEW-'.$supplierPrefix.'-'.$datanorm->article_number;

            // Set default accounting codes from module settings
            $newproduct->accountancy_code_sell = getDolGlobalString('IMPORTZUGFERD_ACCOUNTING_CODE_SELL', '');
            $newproduct->accountancy_code_sell_intra = getDolGlobalString('IMPORTZUGFERD_ACCOUNTING_CODE_SELL_INTRA', '');
            $newproduct->accountancy_code_sell_export = getDolGlobalString('IMPORTZUGFERD_ACCOUNTING_CODE_SELL_EXPORT', '');
            $newproduct->accountancy_code_buy = getDolGlobalString('IMPORTZUGFERD_ACCOUNTING_CODE_BUY', '');
            $newproduct->accountancy_code_buy_intra = getDolGlobalString('IMPORTZUGFERD_ACCOUNTING_CODE_BUY_INTRA', '');
            $newproduct->accountancy_code_buy_export = getDolGlobalString('IMPORTZUGFERD_ACCOUNTING_CODE_BUY_EXPORT', '');

            // Label from Datanorm
            $newproduct->label = $datanorm->short_text1;
            if (!empty($datanorm->short_text2) && strlen($newproduct->label) < 100) {
                $newproduct->label .= ' '.$datanorm->short_text2;
            }

            // Description
            $newproduct->description = $datanorm->getFullDescription();

            // Preise und Kupferzuschlag
            // Datanorm liefert den reinen Materialpreis (ohne Kupferzuschlag)
            // WICHTIG: Bei Kabeln ist der Preis bereits für die Ringgröße (z.B. 49,20€ für 100m Ring)
            $materialPrice = $datanorm->price;
            $priceUnit = $datanorm->price_unit > 0 ? $datanorm->price_unit : 1;

            // Prüfen ob es ein Kabel ist
            $isCable = isCableProduct($datanorm);

            // Preiseinheit bestimmen - unterschiedliche Logik je nach Lieferant-Datenformat:
            // - Kluxen/Witte/eltric: price_unit > 1 (z.B. 100) → Preis ist für 100m
            // - Sonepar: price_unit = 1, aber Preis ist für kompletten Ring → Größe aus Name extrahieren
            $cableText = $datanorm->short_text1 . ' ' . $datanorm->short_text2;
            if ($priceUnit == 1) {
                // Sonepar-Format: Ringgröße aus Bezeichnung extrahieren
                $ringSize = extractCableRingSize($cableText);
                if ($ringSize > 0) {
                    $priceUnit = $ringSize; // z.B. 100 für Ri100
                }
            }
            // Bei price_unit > 1 (Kluxen/Witte) bleibt priceUnit unverändert
            $cableSpecs = null;
            $kupfergehalt = 0;
            $kupferzuschlag = 0;
            $cuPrice = 0;

            if ($isCable) {
                // Parse Aderanzahl und Querschnitt aus Bezeichnung
                $cableSpecs = parseCableSpecsFromText($datanorm->short_text1 . ' ' . $datanorm->short_text2);

                if ($cableSpecs) {
                    // Kupfergehalt berechnen
                    $kupfergehalt = calculateKupfergehalt($cableSpecs['aderanzahl'], $cableSpecs['querschnitt']);

                    // Aktuellen Kupferpreis holen
                    $cuPrice = getCurrentCopperPrice($db, $import->fk_soc);

                    if ($cuPrice > 0 && $kupfergehalt > 0) {
                        // Kupferzuschlag für die Preiseinheit berechnen (z.B. 100m)
                        $kupferzuschlag = calculateKupferzuschlag($kupfergehalt, $cuPrice, $priceUnit);
                    }
                }
            }

            // Einkaufspreis = Materialpreis + Kupferzuschlag (für die Preiseinheit)
            $totalPurchasePrice = $materialPrice + $kupferzuschlag;

            // Stückpreis (pro 1 Einheit, z.B. pro Meter)
            $purchasePricePerUnit = $totalPurchasePrice / $priceUnit;

            // Verkaufspreis mit Aufschlag
            $sellingPrice = $purchasePricePerUnit * (1 + $markup / 100);
            $newproduct->price = $sellingPrice;
            $newproduct->price_base_type = 'HT';
            $newproduct->tva_tx = $lineObj->tax_percent ?: 19;

            // Weight if available
            if (!empty($datanorm->weight)) {
                $newproduct->weight = $datanorm->weight;
                $newproduct->weight_units = 0; // kg
            }

            // Let Dolibarr auto-generate barcode if configured
            // Setting barcode to '-1' triggers automatic generation
            if (isModEnabled('barcode') && getDolGlobalString('BARCODE_PRODUCT_ADDON_NUM')) {
                $newproduct->barcode = '-1';
            }

            // Create the product
            $result = $newproduct->create($user);

            if ($result > 0) {
                // Bei Kabeln: Produkt-Extrafields für Aderanzahl, Querschnitt und Kupfergehalt setzen
                if ($isCable && $cableSpecs && $kupfergehalt > 0) {
                    $sqlProdExtra = "INSERT INTO ".MAIN_DB_PREFIX."product_extrafields";
                    $sqlProdExtra .= " (fk_object, aderanzahl, querschnitt, kupfergehalt)";
                    $sqlProdExtra .= " VALUES (".(int)$newproduct->id.", ";
                    $sqlProdExtra .= (int)$cableSpecs['aderanzahl'].", ";
                    $sqlProdExtra .= (float)$cableSpecs['querschnitt'].", ";
                    $sqlProdExtra .= (float)$kupfergehalt.")";
                    $sqlProdExtra .= " ON DUPLICATE KEY UPDATE";
                    $sqlProdExtra .= " aderanzahl = ".(int)$cableSpecs['aderanzahl'].",";
                    $sqlProdExtra .= " querschnitt = ".(float)$cableSpecs['querschnitt'].",";
                    $sqlProdExtra .= " kupfergehalt = ".(float)$kupfergehalt;
                    if (!$db->query($sqlProdExtra)) {
                        dol_syslog("ImportZugferd: Fehler beim Setzen der Kabel-Extrafields: ".$db->lasterror(), LOG_WARNING);
                    } else {
                        dol_syslog("ImportZugferd: Kabel-Extrafields gesetzt - Adern: ".$cableSpecs['aderanzahl'].", Querschnitt: ".$cableSpecs['querschnitt'].", Kupfergehalt: ".$kupfergehalt." kg/km", LOG_INFO);
                    }
                }

                // Add supplier price
                require_once DOL_DOCUMENT_ROOT.'/fourn/class/fournisseur.product.class.php';
                $prodfourn = new ProductFournisseur($db);
                $prodfourn->id = $newproduct->id;
                $prodfourn->fourn_ref = $datanorm->article_number;

                // Determine EAN for supplier price
                $supplierEan = '';
                $supplierEanType = 0;
                if (!empty($datanorm->ean)) {
                    $supplierEan = $datanorm->ean;
                    $supplierEanType = 2; // EAN13
                } elseif (!empty($lineObj->ean)) {
                    $supplierEan = $lineObj->ean;
                    $supplierEanType = 2; // EAN13
                }

                // Prepare extrafields for supplier price
                $supplierPriceExtrafields = array();
                // Produktpreis (reiner Materialpreis ohne Kupferzuschlag) - nur bei Kabeln
                if ($isCable && $materialPrice > 0) {
                    $supplierPriceExtrafields['options_produktpreis'] = $materialPrice;
                }
                // Preiseinheit
                if ($priceUnit > 1) {
                    $supplierPriceExtrafields['options_preiseinheit'] = $priceUnit;
                } elseif (!empty($lineObj->basis_quantity) && $lineObj->basis_quantity > 1) {
                    $supplierPriceExtrafields['options_preiseinheit'] = $lineObj->basis_quantity;
                }
                // Warengruppe aus Datanorm
                if (!empty($datanorm->product_group)) {
                    $supplierPriceExtrafields['options_warengruppe'] = $datanorm->product_group;
                }

                // Lieferantenpreis speichern (Gesamtpreis inkl. Kupferzuschlag für die Preiseinheit)
                $res = $prodfourn->update_buyprice(
                    $priceUnit, // Quantity (Mindestmenge, z.B. 100 für 100m)
                    $totalPurchasePrice, // Price (Gesamtpreis für die Mindestmenge inkl. Kupfer)
                    $user,
                    'HT', // Price base
                    $supplier, // Supplier
                    0, // Availability
                    $datanorm->article_number, // Supplier ref
                    $lineObj->tax_percent ?: 19, // VAT
                    0, // Charges
                    0, // Remise
                    0, // Remise percentage
                    0, // No price minimum
                    0, // Delivery delay
                    0, // Reputation
                    array(), // Localtaxes array
                    '', // Default VAT code
                    0, // Multicurrency price
                    'HT', // Multicurrency price base type
                    1, // Multicurrency tx
                    '', // Multicurrency code
                    trim($datanorm->short_text1 . ($datanorm->short_text2 ? ' ' . $datanorm->short_text2 : '')), // Description from Datanorm
                    $supplierEan, // Barcode/EAN in supplier price
                    $supplierEanType, // Barcode type (EAN13)
                    $supplierPriceExtrafields // Extra fields
                );

                dol_syslog("ImportZugferd: Lieferantenpreis - Material: ".$materialPrice.", Kupfer: ".$kupferzuschlag.", Gesamt: ".$totalPurchasePrice." (für ".$priceUnit." Einheiten)", LOG_INFO);

                // Manually ensure extrafields record exists for supplier price
                // (Dolibarr update_buyprice doesn't always create it properly)
                $sqlGetPrice = "SELECT rowid FROM ".MAIN_DB_PREFIX."product_fournisseur_price";
                $sqlGetPrice .= " WHERE fk_product = ".(int)$newproduct->id;
                $sqlGetPrice .= " AND fk_soc = ".(int)$supplier->id;
                $sqlGetPrice .= " ORDER BY rowid DESC LIMIT 1";
                $resGetPrice = $db->query($sqlGetPrice);
                if ($resGetPrice && $db->num_rows($resGetPrice) > 0) {
                    $objPrice = $db->fetch_object($resGetPrice);
                    $priceId = $objPrice->rowid;

                    // Check if extrafields record exists
                    $sqlCheckExtra = "SELECT rowid FROM ".MAIN_DB_PREFIX."product_fournisseur_price_extrafields";
                    $sqlCheckExtra .= " WHERE fk_object = ".(int)$priceId;
                    $resCheckExtra = $db->query($sqlCheckExtra);

                    // Werte für Extrafields vorbereiten
                    $produktpreisVal = $isCable && $materialPrice > 0 ? (float)$materialPrice : 'NULL';
                    $kupferzuschlagVal = $kupferzuschlag > 0 ? (float)$kupferzuschlag : 'NULL';
                    $preiseinheitVal = $priceUnit > 1 ? (int)$priceUnit : 1;
                    $warengruppeVal = !empty($datanorm->product_group) ? "'".$db->escape($datanorm->product_group)."'" : 'NULL';

                    if ($resCheckExtra && $db->num_rows($resCheckExtra) == 0) {
                        // Insert extrafields record
                        $sqlInsertExtra = "INSERT INTO ".MAIN_DB_PREFIX."product_fournisseur_price_extrafields";
                        $sqlInsertExtra .= " (fk_object, produktpreis, kupferzuschlag, preiseinheit, warengruppe) VALUES (";
                        $sqlInsertExtra .= (int)$priceId.", ";
                        $sqlInsertExtra .= ($produktpreisVal === 'NULL' ? "NULL" : $produktpreisVal).", ";
                        $sqlInsertExtra .= ($kupferzuschlagVal === 'NULL' ? "NULL" : $kupferzuschlagVal).", ";
                        $sqlInsertExtra .= $preiseinheitVal.", ";
                        $sqlInsertExtra .= $warengruppeVal.")";
                        if (!$db->query($sqlInsertExtra)) {
                            dol_syslog('ImportZugferd: Fehler beim Einfuegen der Extrafields: '.$db->lasterror(), LOG_ERR);
                        }
                    } else {
                        // Update extrafields record
                        $sqlUpdateExtra = "UPDATE ".MAIN_DB_PREFIX."product_fournisseur_price_extrafields SET ";
                        $sqlUpdateExtra .= "produktpreis = ".($produktpreisVal === 'NULL' ? "NULL" : $produktpreisVal).", ";
                        $sqlUpdateExtra .= "kupferzuschlag = ".($kupferzuschlagVal === 'NULL' ? "NULL" : $kupferzuschlagVal).", ";
                        $sqlUpdateExtra .= "preiseinheit = ".$preiseinheitVal.", ";
                        $sqlUpdateExtra .= "warengruppe = ".$warengruppeVal." ";
                        $sqlUpdateExtra .= "WHERE fk_object = ".(int)$priceId;
                        if (!$db->query($sqlUpdateExtra)) {
                            dol_syslog('ImportZugferd: Fehler beim Update der Extrafields: '.$db->lasterror(), LOG_ERR);
                        }
                    }
                }

                // Create product mapping for future imports
                $mapping = new ProductMapping($db);
                $mapping->fk_soc = $import->fk_soc;
                $mapping->supplier_ref = $datanorm->article_number;
                $mapping->fk_product = $newproduct->id;
                $mapping->ean = $datanorm->ean;
                $mapping->manufacturer_ref = $datanorm->manufacturer_ref;
                $mapping->description = $datanorm->short_text1;
                $mapping->create($user);

                // Assign to import line
                $lineObj->setProduct($newproduct->id, 'datanorm', $user);

                setEventMessages($langs->trans('ProductCreatedFromDatanorm', $newproduct->ref), null, 'mesgs');

                // Check if all lines now have products
                $allHaveProducts = $importLine->allLinesHaveProducts($id);
                if ($allHaveProducts) {
                    $import->status = ZugferdImport::STATUS_IMPORTED;
                    $import->update($user);
                }
            } else {
                setEventMessages($newproduct->error, $newproduct->errors, 'errors');
            }
        } else {
            setEventMessages($langs->trans('DatanormArticleNotFound', $lineObj->supplier_ref), null, 'errors');
        }
    }
    $action = 'edit';
    $import->fetch($id);
}

// "Alle zuordnen" - Assign Datanorm matches to import lines
if ($action == 'assignallfromdatanorm' && $id > 0) {
    $import->fetch($id);

    if ($import->fk_soc > 0) {
        $searchAll = getDolGlobalString('IMPORTZUGFERD_DATANORM_SEARCH_ALL', 0);

        // Get all lines without product
        $lines = $importLine->fetchAllByImport($import->id);
        $datanorm = new Datanorm($db);
        $mapping = new ProductMapping($db);
        $assignedCount = 0;
        $datanormFoundCount = 0;

        foreach ($lines as $lineObj) {
            // Skip lines that already have a product
            if ($lineObj->fk_product > 0) {
                continue;
            }

            // Skip lines without supplier_ref
            if (empty($lineObj->supplier_ref)) {
                continue;
            }

            // Search in Datanorm database
            $results = $datanorm->searchByArticleNumber($lineObj->supplier_ref, $import->fk_soc, $searchAll, 1);

            if (empty($results) && !empty($lineObj->ean)) {
                $results = $datanorm->searchByArticleNumber($lineObj->ean, $import->fk_soc, $searchAll, 1);
            }

            if (!empty($results)) {
                $datanormFoundCount++;
                $datanormMatch = $results[0];
                // Get Datanorm ID and article number (array access)
                $datanormId = isset($datanormMatch['id']) ? $datanormMatch['id'] : (isset($datanormMatch['rowid']) ? $datanormMatch['rowid'] : 0);
                $articleNumber = isset($datanormMatch['article_number']) ? $datanormMatch['article_number'] : '';

                // Check if product already exists for this supplier ref
                $existingProductId = $mapping->findProductBySupplierRef($import->fk_soc, $articleNumber);

                if ($existingProductId > 0) {
                    // Product exists - assign both product and Datanorm to the line
                    $lineObj->fk_product = $existingProductId;
                    $lineObj->fk_datanorm = $datanormId;
                    $lineObj->match_method = 'datanorm_assign';
                    $lineObj->update($user);
                    $assignedCount++;
                } else {
                    // No product yet - save Datanorm reference for later product creation
                    $lineObj->fk_datanorm = $datanormId;
                    $lineObj->match_method = 'datanorm_pending';
                    $lineObj->update($user);
                }
            }
        }

        if ($assignedCount > 0) {
            setEventMessages($langs->trans('ProductsAssignedFromDatanorm', $assignedCount), null, 'mesgs');
        }
        if ($datanormFoundCount > $assignedCount) {
            $pendingCount = $datanormFoundCount - $assignedCount;
            setEventMessages($langs->trans('DatanormMatchesFoundNotAssigned', $pendingCount), null, 'mesgs');
        }
        if ($datanormFoundCount == 0) {
            setEventMessages($langs->trans('DatanormBatchNoMatches'), null, 'warnings');
        }
    }

    header('Location: '.$_SERVER['PHP_SELF'].'?action=edit&id='.$id.'&token='.newToken());
    exit;
}

// Create ALL products from Datanorm (batch)
if ($action == 'createallfromdatanorm' && $id > 0) {
    $import->fetch($id);

    if ($import->fk_soc > 0) {
        // Get Datanorm settings
        $markup = getDolGlobalString('IMPORTZUGFERD_DATANORM_MARKUP', 30);
        $searchAll = getDolGlobalString('IMPORTZUGFERD_DATANORM_SEARCH_ALL', 0);

        // Load supplier
        $supplier = new Societe($db);
        $supplier->fetch($import->fk_soc);
        $supplierPrefix = strtoupper(substr(preg_replace('/[^a-zA-Z]/', '', $supplier->name), 0, 3));

        // Get all lines without product
        $lines = $importLine->fetchAllByImport($import->id);
        $datanorm = new Datanorm($db);
        $createdCount = 0;
        $assignedCount = 0;
        $errorCount = 0;

        require_once DOL_DOCUMENT_ROOT.'/fourn/class/fournisseur.product.class.php';

        foreach ($lines as $lineObj) {
            // Skip lines that already have a product
            if ($lineObj->fk_product > 0) {
                continue;
            }

            // Skip lines without supplier_ref
            if (empty($lineObj->supplier_ref)) {
                continue;
            }

            // Search in Datanorm database
            $results = $datanorm->searchByArticleNumber($lineObj->supplier_ref, $import->fk_soc, $searchAll, 1);

            if (empty($results) && !empty($lineObj->ean)) {
                $results = $datanorm->searchByArticleNumber($lineObj->ean, $import->fk_soc, $searchAll, 1);
            }

            if (!empty($results)) {
                $datanormArticle = $results[0];
                $datanorm->fetch($datanormArticle['id']);

                $purchasePrice = $datanorm->price;
                if ($datanorm->price_unit > 1) {
                    $purchasePrice = $datanorm->price / $datanorm->price_unit;
                }

                // Get copper surcharge for selling price calculation
                // Priority: 1. Datanorm, 2. ZUGFeRD
                $copperSurchargeForPrice = 0;
                if (!empty($datanorm->metal_surcharge) && $datanorm->metal_surcharge > 0) {
                    $copperSurchargeForPrice = $datanorm->metal_surcharge;
                    // Normalize to per-unit if price_unit > 1
                    if ($datanorm->price_unit > 1) {
                        $copperSurchargeForPrice = $datanorm->metal_surcharge / $datanorm->price_unit;
                    }
                } elseif (!empty($lineObj->copper_surcharge) && $lineObj->copper_surcharge > 0) {
                    $copperSurchargeForPrice = $lineObj->copper_surcharge;
                    // Normalize based on copper_surcharge_basis_qty
                    if (!empty($lineObj->copper_surcharge_basis_qty) && $lineObj->copper_surcharge_basis_qty > 1) {
                        $copperSurchargeForPrice = $lineObj->copper_surcharge / $lineObj->copper_surcharge_basis_qty;
                    }
                }

                // Check if product already exists in Dolibarr
                $existingProduct = new Product($db);
                $productExists = false;
                $existingProductId = 0;

                // 1. Check by supplier reference (ProductFournisseur)
                $sqlCheck = "SELECT DISTINCT pf.fk_product FROM ".MAIN_DB_PREFIX."product_fournisseur_price as pf";
                $sqlCheck .= " WHERE pf.fk_soc = ".(int)$import->fk_soc;
                $sqlCheck .= " AND pf.ref_fourn = '".$db->escape($datanorm->article_number)."'";
                $sqlCheck .= " AND pf.entity IN (".getEntity('product').")";
                $resqlCheck = $db->query($sqlCheck);
                if ($resqlCheck && $db->num_rows($resqlCheck) > 0) {
                    $objCheck = $db->fetch_object($resqlCheck);
                    $existingProductId = $objCheck->fk_product;
                    $productExists = true;
                }

                // 2. Check by product reference pattern
                if (!$productExists) {
                    $expectedRef = 'NEW-'.$supplierPrefix.'-'.$datanorm->article_number;
                    $fetchResult = $existingProduct->fetch(0, $expectedRef);
                    if ($fetchResult > 0) {
                        $existingProductId = $existingProduct->id;
                        $productExists = true;
                    }
                }

                // 3. Check by EAN if available
                if (!$productExists && !empty($datanorm->ean)) {
                    $sqlEan = "SELECT rowid FROM ".MAIN_DB_PREFIX."product";
                    $sqlEan .= " WHERE barcode = '".$db->escape($datanorm->ean)."'";
                    $sqlEan .= " AND entity IN (".getEntity('product').")";
                    $resqlEan = $db->query($sqlEan);
                    if ($resqlEan && $db->num_rows($resqlEan) > 0) {
                        $objEan = $db->fetch_object($resqlEan);
                        $existingProductId = $objEan->rowid;
                        $productExists = true;
                    }
                }

                if ($productExists && $existingProductId > 0) {
                    // Product exists - just assign it to the line
                    $lineObj->setProduct($existingProductId, 'datanorm', $user);

                    // Add additional supplier prices from selected alternatives (for existing products too)
                    $supplierPricesPost = GETPOST('supplier_prices', 'array');
                    if (!empty($supplierPricesPost[$lineObj->id])) {
                        foreach ($supplierPricesPost[$lineObj->id] as $altSocId => $altDatanormId) {
                            // Check if supplier price already exists for this product/supplier
                            $sqlCheckSupplier = "SELECT rowid FROM ".MAIN_DB_PREFIX."product_fournisseur_price";
                            $sqlCheckSupplier .= " WHERE fk_product = ".(int)$existingProductId;
                            $sqlCheckSupplier .= " AND fk_soc = ".(int)$altSocId;
                            $resCheckSupplier = $db->query($sqlCheckSupplier);
                            if ($resCheckSupplier && $db->num_rows($resCheckSupplier) > 0) {
                                continue; // Skip if supplier price already exists
                            }

                            // Fetch the alternative Datanorm article
                            $altDatanorm = new Datanorm($db);
                            if ($altDatanorm->fetch($altDatanormId) > 0) {
                                $altSupplier = new Societe($db);
                                $altSupplier->fetch($altSocId);

                                // Prepare extrafields
                                $altExtrafields = array();
                                if (!empty($altDatanorm->metal_surcharge) && $altDatanorm->metal_surcharge > 0 && !empty($altDatanorm->price)) {
                                    $altExtrafields['options_produktpreis'] = $altDatanorm->price;
                                }
                                if (!empty($altDatanorm->product_group)) {
                                    $altExtrafields['options_warengruppe'] = $altDatanorm->product_group;
                                }

                                // Mindestbestellmenge, Verpackungseinheit, Steuersatz und kaufmenge vom bestehenden Preis übernehmen
                                $altMinQty = 1;
                                $altPackaging = null;
                                $altTvaTx = $lineObj->tax_percent ?: 19;
                                $altKaufmenge = null;
                                $sqlAltExisting = "SELECT pf.rowid, pf.quantity, pf.packaging, pf.tva_tx FROM " . MAIN_DB_PREFIX . "product_fournisseur_price pf";
                                $sqlAltExisting .= " WHERE pf.fk_product = " . (int)$existingProductId;
                                $sqlAltExisting .= " AND pf.quantity > 0 ORDER BY pf.rowid ASC LIMIT 1";
                                $resAltExisting = $db->query($sqlAltExisting);
                                if ($resAltExisting && $db->num_rows($resAltExisting) > 0) {
                                    $objAltExisting = $db->fetch_object($resAltExisting);
                                    if ($objAltExisting->quantity > 0) {
                                        $altMinQty = $objAltExisting->quantity;
                                    }
                                    if (!empty($objAltExisting->packaging)) {
                                        $altPackaging = $objAltExisting->packaging;
                                    }
                                    if ($objAltExisting->tva_tx > 0) {
                                        $altTvaTx = $objAltExisting->tva_tx;
                                    }
                                    // kaufmenge aus Extrafields übernehmen (nur wenn numerisch und > 0)
                                    $sqlKaufmenge = "SELECT kaufmenge FROM " . MAIN_DB_PREFIX . "product_fournisseur_price_extrafields";
                                    $sqlKaufmenge .= " WHERE fk_object = " . (int)$objAltExisting->rowid;
                                    $resKaufmenge = $db->query($sqlKaufmenge);
                                    if ($resKaufmenge && $db->num_rows($resKaufmenge) > 0) {
                                        $objKaufmenge = $db->fetch_object($resKaufmenge);
                                        $kmValue = trim($objKaufmenge->kaufmenge);
                                        if ($kmValue !== '' && is_numeric($kmValue) && (int)$kmValue > 0) {
                                            $altKaufmenge = (int)$kmValue;
                                        }
                                    }
                                }

                                // Preis berechnen - Datanorm-Preis ist für die price_unit Menge!
                                $altCableText = $altDatanorm->short_text1 . ' ' . $altDatanorm->short_text2;
                                $altRingSize = extractCableRingSize($altCableText);
                                $altPriceUnit = 1;

                                if ($altRingSize > 0) {
                                    // Kabel mit Ringgröße
                                    $altPriceUnit = $altRingSize;
                                    $altExtrafields['options_preiseinheit'] = $altRingSize;
                                } elseif (!empty($altDatanorm->price_unit) && $altDatanorm->price_unit > 1) {
                                    // Nicht-Kabel mit price_unit > 1
                                    $altPriceUnit = $altDatanorm->price_unit;
                                    $altExtrafields['options_preiseinheit'] = $altDatanorm->price_unit;
                                }

                                // WICHTIG: Datanorm price ist bereits für die altPriceUnit Menge!
                                // Nur umrechnen wenn altMinQty != altPriceUnit
                                if ($altMinQty == $altPriceUnit) {
                                    // Gleiche Menge: Preis direkt übernehmen
                                    $altTotalPrice = $altDatanorm->price;
                                } else {
                                    // Unterschiedliche Menge: Umrechnen über Stückpreis
                                    $altUnitPrice = $altDatanorm->price / $altPriceUnit;
                                    $altTotalPrice = $altUnitPrice * $altMinQty;
                                }

                                // Add supplier price (use tva_tx from existing price)
                                $altProdfourn = new ProductFournisseur($db);
                                $altProdfourn->id = $existingProductId;
                                $altResult = $altProdfourn->update_buyprice(
                                    $altMinQty, $altTotalPrice, $user, 'HT', $altSupplier, 0,
                                    $altDatanorm->article_number, $altTvaTx,
                                    0, 0, 0, 0, 0, 0, array(), '',
                                    0, 'HT', 1, '',
                                    trim($altDatanorm->short_text1 . ($altDatanorm->short_text2 ? ' ' . $altDatanorm->short_text2 : '')),
                                    !empty($altDatanorm->ean) ? $altDatanorm->ean : '',
                                    !empty($altDatanorm->ean) ? 2 : 0,
                                    $altExtrafields
                                );

                                // Verpackungseinheit und kaufmenge nachträglich setzen
                                if ($altResult > 0) {
                                    // Packaging = Mindestmenge (als Standard)
                                    $sqlAltPkg = "UPDATE " . MAIN_DB_PREFIX . "product_fournisseur_price";
                                    $sqlAltPkg .= " SET packaging = " . (float)($altPackaging ?: $altMinQty);
                                    $sqlAltPkg .= " WHERE rowid = " . (int)$altResult;
                                    $db->query($sqlAltPkg);

                                    // kaufmenge in Extrafields übernehmen wenn vorhanden
                                    if (!empty($altKaufmenge)) {
                                        $sqlCheckExtra = "SELECT rowid FROM " . MAIN_DB_PREFIX . "product_fournisseur_price_extrafields WHERE fk_object = " . (int)$altResult;
                                        $resCheckExtra = $db->query($sqlCheckExtra);
                                        if ($resCheckExtra && $db->num_rows($resCheckExtra) > 0) {
                                            $sqlUpdateKm = "UPDATE " . MAIN_DB_PREFIX . "product_fournisseur_price_extrafields";
                                            $sqlUpdateKm .= " SET kaufmenge = " . (int)$altKaufmenge;
                                            $sqlUpdateKm .= " WHERE fk_object = " . (int)$altResult;
                                            $db->query($sqlUpdateKm);
                                        } else {
                                            $sqlInsertKm = "INSERT INTO " . MAIN_DB_PREFIX . "product_fournisseur_price_extrafields";
                                            $sqlInsertKm .= " (fk_object, kaufmenge) VALUES (" . (int)$altResult . ", " . (int)$altKaufmenge . ")";
                                            $db->query($sqlInsertKm);
                                        }
                                    }
                                }

                                // Create product mapping
                                $altMapping = new ProductMapping($db);
                                $altMapping->fk_soc = $altSocId;
                                $altMapping->supplier_ref = $altDatanorm->article_number;
                                $altMapping->fk_product = $existingProductId;
                                $altMapping->ean = $altDatanorm->ean;
                                $altMapping->manufacturer_ref = $altDatanorm->manufacturer_ref;
                                $altMapping->description = $altDatanorm->short_text1;
                                $altMapping->create($user);
                            }
                        }
                    }

                    $assignedCount++;
                } else {
                    // Create new product
                    $newproduct = new Product($db);
                    $newproduct->type = 0;
                    $newproduct->status = 1;
                    $newproduct->status_buy = 1;
                    $newproduct->ref = 'NEW-'.$supplierPrefix.'-'.$datanorm->article_number;
                    $newproduct->label = $datanorm->short_text1;
                    if (!empty($datanorm->short_text2) && strlen($newproduct->label) < 100) {
                        $newproduct->label .= ' '.$datanorm->short_text2;
                    }
                    $newproduct->description = $datanorm->getFullDescription();

                    // Set default accounting codes from module settings
                    $newproduct->accountancy_code_sell = getDolGlobalString('IMPORTZUGFERD_ACCOUNTING_CODE_SELL', '');
                    $newproduct->accountancy_code_sell_intra = getDolGlobalString('IMPORTZUGFERD_ACCOUNTING_CODE_SELL_INTRA', '');
                    $newproduct->accountancy_code_sell_export = getDolGlobalString('IMPORTZUGFERD_ACCOUNTING_CODE_SELL_EXPORT', '');
                    $newproduct->accountancy_code_buy = getDolGlobalString('IMPORTZUGFERD_ACCOUNTING_CODE_BUY', '');
                    $newproduct->accountancy_code_buy_intra = getDolGlobalString('IMPORTZUGFERD_ACCOUNTING_CODE_BUY_INTRA', '');
                    $newproduct->accountancy_code_buy_export = getDolGlobalString('IMPORTZUGFERD_ACCOUNTING_CODE_BUY_EXPORT', '');

                    // Selling price: (purchase price + copper surcharge) × (1 + markup%)
                    $sellingPrice = ($purchasePrice + $copperSurchargeForPrice) * (1 + $markup / 100);
                    $newproduct->price = $sellingPrice;
                    $newproduct->price_base_type = 'HT';
                    $newproduct->tva_tx = $lineObj->tax_percent ?: 19;

                    if (!empty($datanorm->weight)) {
                        $newproduct->weight = $datanorm->weight;
                        $newproduct->weight_units = 0;
                    }

                    if (isModEnabled('barcode') && getDolGlobalString('BARCODE_PRODUCT_ADDON_NUM')) {
                        $newproduct->barcode = '-1';
                    }

                    $result = $newproduct->create($user);

                    if ($result > 0) {
                        // Add supplier price
                        $prodfourn = new ProductFournisseur($db);
                        $prodfourn->id = $newproduct->id;
                        $prodfourn->fourn_ref = $datanorm->article_number;

                        $supplierEan = '';
                        $supplierEanType = 0;
                        if (!empty($datanorm->ean)) {
                            $supplierEan = $datanorm->ean;
                            $supplierEanType = 2;
                        } elseif (!empty($lineObj->ean)) {
                            $supplierEan = $lineObj->ean;
                            $supplierEanType = 2;
                        }

                        // Prepare extrafields for supplier price
                        $supplierPriceExtrafields = array();
                        // Produktpreis (reiner Materialpreis) - nur bei Kabeln mit Metallzuschlag
                        if (!empty($datanorm->metal_surcharge) && $datanorm->metal_surcharge > 0 && !empty($datanorm->price)) {
                            $supplierPriceExtrafields['options_produktpreis'] = $datanorm->price;
                        }
                        // Preiseinheit - Priorität: 1. ZUGFeRD basis_quantity, 2. Datanorm price_unit
                        if (!empty($lineObj->basis_quantity) && $lineObj->basis_quantity > 1) {
                            $supplierPriceExtrafields['options_preiseinheit'] = $lineObj->basis_quantity;
                        } elseif (!empty($datanorm->price_unit) && $datanorm->price_unit > 1) {
                            $supplierPriceExtrafields['options_preiseinheit'] = $datanorm->price_unit;
                        }
                        // Warengruppe aus Datanorm
                        if (!empty($datanorm->product_group)) {
                            $supplierPriceExtrafields['options_warengruppe'] = $datanorm->product_group;
                        }

                        // Mindestbestellmenge und Preis mit zentraler Funktion berechnen
                        $pricing = calculateCablePricing($datanorm, 1);
                        $newMinQty = $pricing['priceUnit'];
                        $newPackaging = $pricing['priceUnit'];
                        $newTotalPrice = $datanorm->price; // Originalpreis aus Datanorm

                        // Fallback auf ZUGFeRD basis_quantity wenn keine Ringgröße erkannt
                        if ($newMinQty == 1 && !empty($lineObj->basis_quantity) && $lineObj->basis_quantity > 1) {
                            $newMinQty = $lineObj->basis_quantity;
                            $newPackaging = $lineObj->basis_quantity;
                            $newTotalPrice = $purchasePrice * $newMinQty;
                        }

                        $newPriceResult = $prodfourn->update_buyprice(
                            $newMinQty, // Quantity (Mindestbestellmenge)
                            $newTotalPrice, // Price (Gesamtpreis für die Mindestmenge)
                            $user,
                            'HT', // Price base
                            $supplier, // Supplier
                            0, // Availability
                            $datanorm->article_number, // Supplier ref
                            $lineObj->tax_percent ?: 19, // VAT
                            0, // Charges
                            0, // Remise
                            0, // Remise percentage
                            0, // No price minimum
                            0, // Delivery delay
                            0, // Reputation
                            array(), // Localtaxes array
                            '', // Default VAT code
                            0, // Multicurrency price
                            'HT', // Multicurrency price base type
                            1, // Multicurrency tx
                            '', // Multicurrency code
                            trim($datanorm->short_text1 . ($datanorm->short_text2 ? ' ' . $datanorm->short_text2 : '')), // Description from Datanorm
                            $supplierEan, // Barcode/EAN
                            $supplierEanType, // Barcode type
                            $supplierPriceExtrafields // Extra fields
                        );

                        // Manually ensure extrafields record exists for supplier price
                        // (Dolibarr update_buyprice doesn't always create it properly)
                        $sqlGetPrice = "SELECT rowid FROM ".MAIN_DB_PREFIX."product_fournisseur_price";
                        $sqlGetPrice .= " WHERE fk_product = ".(int)$newproduct->id;
                        $sqlGetPrice .= " AND fk_soc = ".(int)$supplier->id;
                        $sqlGetPrice .= " ORDER BY rowid DESC LIMIT 1";
                        $resGetPrice = $db->query($sqlGetPrice);
                        if ($resGetPrice && $db->num_rows($resGetPrice) > 0) {
                            $objPrice = $db->fetch_object($resGetPrice);
                            $priceId = $objPrice->rowid;

                            // Check if extrafields record exists
                            $sqlCheckExtra = "SELECT rowid FROM ".MAIN_DB_PREFIX."product_fournisseur_price_extrafields";
                            $sqlCheckExtra .= " WHERE fk_object = ".(int)$priceId;
                            $resCheckExtra = $db->query($sqlCheckExtra);

                            $produktpreis = !empty($supplierPriceExtrafields['options_produktpreis']) ? (float)$supplierPriceExtrafields['options_produktpreis'] : 'NULL';
                            $preiseinheit = !empty($supplierPriceExtrafields['options_preiseinheit']) ? (int)$supplierPriceExtrafields['options_preiseinheit'] : 1;
                            $warengruppe = !empty($supplierPriceExtrafields['options_warengruppe']) ? "'".$db->escape($supplierPriceExtrafields['options_warengruppe'])."'" : 'NULL';

                            if ($resCheckExtra && $db->num_rows($resCheckExtra) == 0) {
                                // Insert extrafields record
                                $sqlInsertExtra = "INSERT INTO ".MAIN_DB_PREFIX."product_fournisseur_price_extrafields";
                                $sqlInsertExtra .= " (fk_object, produktpreis, preiseinheit, warengruppe) VALUES (";
                                $sqlInsertExtra .= (int)$priceId.", ";
                                $sqlInsertExtra .= ($produktpreis === 'NULL' ? "NULL" : $produktpreis).", ";
                                $sqlInsertExtra .= $preiseinheit.", ";
                                $sqlInsertExtra .= $warengruppe.")";
                                if (!$db->query($sqlInsertExtra)) {
                                    dol_syslog('ImportZugferd: Fehler beim Einfuegen der Extrafields: '.$db->lasterror(), LOG_ERR);
                                }
                            } else {
                                // Update extrafields record
                                $sqlUpdateExtra = "UPDATE ".MAIN_DB_PREFIX."product_fournisseur_price_extrafields SET ";
                                $sqlUpdateExtra .= "produktpreis = ".($produktpreis === 'NULL' ? "NULL" : $produktpreis).", ";
                                $sqlUpdateExtra .= "preiseinheit = ".$preiseinheit.", ";
                                $sqlUpdateExtra .= "warengruppe = ".$warengruppe." ";
                                $sqlUpdateExtra .= "WHERE fk_object = ".(int)$priceId;
                                if (!$db->query($sqlUpdateExtra)) {
                                    dol_syslog('ImportZugferd: Fehler beim Update der Extrafields: '.$db->lasterror(), LOG_ERR);
                                }
                            }
                        }

                        // Create product mapping
                        $mapping = new ProductMapping($db);
                        $mapping->fk_soc = $import->fk_soc;
                        $mapping->supplier_ref = $datanorm->article_number;
                        $mapping->fk_product = $newproduct->id;
                        $mapping->ean = $datanorm->ean;
                        $mapping->manufacturer_ref = $datanorm->manufacturer_ref;
                        $mapping->description = $datanorm->short_text1;
                        $mapping->create($user);

                        // Add additional supplier prices from selected alternatives
                        $supplierPricesPost = GETPOST('supplier_prices', 'array');
                        if (!empty($supplierPricesPost[$lineObj->id])) {
                            // Hole Werte vom gerade angelegten Hauptpreis (Mindestmenge, Verpackung, Steuersatz)
                            $mainMinQty = $newMinQty;
                            $mainPackaging = $newPackaging;
                            $mainTvaTx = $lineObj->tax_percent ?: 19;
                            $mainKaufmenge = null;

                            // kaufmenge vom Hauptpreis-Extrafield holen (nur wenn numerisch und > 0)
                            if (!empty($priceId)) {
                                $sqlMainKm = "SELECT kaufmenge FROM " . MAIN_DB_PREFIX . "product_fournisseur_price_extrafields";
                                $sqlMainKm .= " WHERE fk_object = " . (int)$priceId;
                                $resMainKm = $db->query($sqlMainKm);
                                if ($resMainKm && $db->num_rows($resMainKm) > 0) {
                                    $objMainKm = $db->fetch_object($resMainKm);
                                    $kmValue = trim($objMainKm->kaufmenge);
                                    if ($kmValue !== '' && is_numeric($kmValue) && (int)$kmValue > 0) {
                                        $mainKaufmenge = (int)$kmValue;
                                    }
                                }
                            }

                            foreach ($supplierPricesPost[$lineObj->id] as $altSocId => $altDatanormId) {
                                // Skip the main invoice supplier (already added above)
                                if ($altSocId == $import->fk_soc) {
                                    continue;
                                }

                                // Fetch the alternative Datanorm article
                                $altDatanorm = new Datanorm($db);
                                if ($altDatanorm->fetch($altDatanormId) > 0) {
                                    $altSupplier = new Societe($db);
                                    $altSupplier->fetch($altSocId);

                                    // Prepare extrafields for alternative supplier price
                                    $altExtrafields = array();
                                    if (!empty($altDatanorm->metal_surcharge) && $altDatanorm->metal_surcharge > 0 && !empty($altDatanorm->price)) {
                                        $altExtrafields['options_produktpreis'] = $altDatanorm->price;
                                    }
                                    if (!empty($altDatanorm->product_group)) {
                                        $altExtrafields['options_warengruppe'] = $altDatanorm->product_group;
                                    }

                                    // Preis berechnen - Datanorm-Preis ist für die price_unit Menge!
                                    $altCableText = $altDatanorm->short_text1 . ' ' . $altDatanorm->short_text2;
                                    $altRingSize = extractCableRingSize($altCableText);
                                    $altPriceUnit = 1;

                                    if ($altRingSize > 0) {
                                        // Kabel mit Ringgröße
                                        $altPriceUnit = $altRingSize;
                                        $altExtrafields['options_preiseinheit'] = $altRingSize;
                                    } elseif (!empty($altDatanorm->price_unit) && $altDatanorm->price_unit > 1) {
                                        // Nicht-Kabel mit price_unit > 1
                                        $altPriceUnit = $altDatanorm->price_unit;
                                        $altExtrafields['options_preiseinheit'] = $altDatanorm->price_unit;
                                    }

                                    // WICHTIG: Datanorm price ist bereits für die altPriceUnit Menge!
                                    // Umrechnen auf mainMinQty (vom Hauptpreis übernommen)
                                    if ($mainMinQty == $altPriceUnit) {
                                        // Gleiche Menge: Preis direkt übernehmen
                                        $altTotalPrice = $altDatanorm->price;
                                    } else {
                                        // Unterschiedliche Menge: Umrechnen über Stückpreis
                                        $altUnitPrice = $altDatanorm->price / $altPriceUnit;
                                        $altTotalPrice = $altUnitPrice * $mainMinQty;
                                    }

                                    // Add supplier price for alternative supplier
                                    $altProdfourn = new ProductFournisseur($db);
                                    $altProdfourn->id = $newproduct->id;
                                    $altResult = $altProdfourn->update_buyprice(
                                        $mainMinQty, // Quantity (vom Hauptpreis übernommen)
                                        $altTotalPrice, // Price (für mainMinQty berechnet)
                                        $user,
                                        'HT', // Price base
                                        $altSupplier, // Alternative supplier
                                        0, // Availability
                                        $altDatanorm->article_number, // Supplier ref
                                        $mainTvaTx, // VAT (vom Hauptpreis übernommen)
                                        0, 0, 0, 0, 0, 0, array(), '',
                                        0, 'HT', 1, '',
                                        trim($altDatanorm->short_text1 . ($altDatanorm->short_text2 ? ' ' . $altDatanorm->short_text2 : '')),
                                        !empty($altDatanorm->ean) ? $altDatanorm->ean : '',
                                        !empty($altDatanorm->ean) ? 2 : 0,
                                        $altExtrafields
                                    );

                                    // Verpackungseinheit und kaufmenge nachträglich setzen (vom Hauptpreis übernommen)
                                    if ($altResult > 0) {
                                        $sqlAltPkg = "UPDATE " . MAIN_DB_PREFIX . "product_fournisseur_price";
                                        $sqlAltPkg .= " SET packaging = " . (float)$mainPackaging;
                                        $sqlAltPkg .= " WHERE rowid = " . (int)$altResult;
                                        $db->query($sqlAltPkg);

                                        // kaufmenge in Extrafields übernehmen wenn vorhanden
                                        if (!empty($mainKaufmenge)) {
                                            $sqlCheckExtra = "SELECT rowid FROM " . MAIN_DB_PREFIX . "product_fournisseur_price_extrafields WHERE fk_object = " . (int)$altResult;
                                            $resCheckExtra = $db->query($sqlCheckExtra);
                                            if ($resCheckExtra && $db->num_rows($resCheckExtra) > 0) {
                                                $sqlUpdateKm = "UPDATE " . MAIN_DB_PREFIX . "product_fournisseur_price_extrafields";
                                                $sqlUpdateKm .= " SET kaufmenge = " . (int)$mainKaufmenge;
                                                $sqlUpdateKm .= " WHERE fk_object = " . (int)$altResult;
                                                $db->query($sqlUpdateKm);
                                            } else {
                                                $sqlInsertKm = "INSERT INTO " . MAIN_DB_PREFIX . "product_fournisseur_price_extrafields";
                                                $sqlInsertKm .= " (fk_object, kaufmenge) VALUES (" . (int)$altResult . ", " . (int)$mainKaufmenge . ")";
                                                $db->query($sqlInsertKm);
                                            }
                                        }
                                    }

                                    // Create product mapping for alternative supplier
                                    $altMapping = new ProductMapping($db);
                                    $altMapping->fk_soc = $altSocId;
                                    $altMapping->supplier_ref = $altDatanorm->article_number;
                                    $altMapping->fk_product = $newproduct->id;
                                    $altMapping->ean = $altDatanorm->ean;
                                    $altMapping->manufacturer_ref = $altDatanorm->manufacturer_ref;
                                    $altMapping->description = $altDatanorm->short_text1;
                                    $altMapping->create($user);
                                }
                            }
                        }

                        // Assign to import line
                        $lineObj->setProduct($newproduct->id, 'datanorm', $user);
                        $createdCount++;
                    } else {
                        $errorCount++;
                    }
                }
            }
        }

        if ($createdCount > 0) {
            setEventMessages($langs->trans('DatanormBatchCreated', $createdCount), null, 'mesgs');
        }
        if ($assignedCount > 0) {
            setEventMessages($langs->trans('DatanormBatchAssigned', $assignedCount), null, 'mesgs');
        }
        if ($errorCount > 0) {
            setEventMessages($langs->trans('DatanormBatchErrors', $errorCount), null, 'warnings');
        }
        if ($createdCount == 0 && $assignedCount == 0 && $errorCount == 0) {
            setEventMessages($langs->trans('DatanormBatchNoMatches'), null, 'warnings');
        }

        // Check if all lines now have products
        $allHaveProducts = $importLine->allLinesHaveProducts($id);
        if ($allHaveProducts) {
            $import->status = ZugferdImport::STATUS_IMPORTED;
            $import->update($user);
        }
    }
    $action = 'edit';
    $import->fetch($id);
}

// Preview Datanorm matches (step 1 - show what will be created)
$datanormPreviewMatches = array();
if ($action == 'previewdatanorm' && $id > 0) {
    $import->fetch($id);

    if ($import->fk_soc > 0) {
        // Get Datanorm settings
        $markup = getDolGlobalString('IMPORTZUGFERD_DATANORM_MARKUP', 30);
        $searchAll = getDolGlobalString('IMPORTZUGFERD_DATANORM_SEARCH_ALL', 0);

        // Load supplier
        $supplier = new Societe($db);
        $supplier->fetch($import->fk_soc);
        $supplierPrefix = strtoupper(substr(preg_replace('/[^a-zA-Z]/', '', $supplier->name), 0, 3));

        // Get all lines without product
        $lines = $importLine->fetchAllByImport($import->id);
        $datanorm = new Datanorm($db);

        require_once DOL_DOCUMENT_ROOT.'/fourn/class/fournisseur.product.class.php';

        foreach ($lines as $lineObj) {
            // Skip lines that already have a product
            if ($lineObj->fk_product > 0) {
                continue;
            }

            // Skip lines without supplier_ref
            if (empty($lineObj->supplier_ref)) {
                continue;
            }

            // Search in Datanorm database - get ALL supplier alternatives
            $results = $datanorm->searchByArticleNumber($lineObj->supplier_ref, $import->fk_soc, $searchAll, 10);

            if (empty($results) && !empty($lineObj->ean)) {
                $results = $datanorm->searchByArticleNumber($lineObj->ean, $import->fk_soc, $searchAll, 10);
            }

            if (!empty($results)) {
                // Process the primary result (first = current supplier or cheapest)
                $datanormArticle = $results[0];
                $datanorm->fetch($datanormArticle['id']);

                $purchasePrice = $datanorm->price;
                if ($datanorm->price_unit > 1) {
                    $purchasePrice = $datanorm->price / $datanorm->price_unit;
                }

                // Get copper surcharge for selling price calculation
                $copperSurchargeForPrice = 0;
                if (!empty($datanorm->metal_surcharge) && $datanorm->metal_surcharge > 0) {
                    $copperSurchargeForPrice = $datanorm->metal_surcharge;
                    if ($datanorm->price_unit > 1) {
                        $copperSurchargeForPrice = $datanorm->metal_surcharge / $datanorm->price_unit;
                    }
                } elseif (!empty($lineObj->copper_surcharge) && $lineObj->copper_surcharge > 0) {
                    $copperSurchargeForPrice = $lineObj->copper_surcharge;
                    if (!empty($lineObj->copper_surcharge_basis_qty) && $lineObj->copper_surcharge_basis_qty > 1) {
                        $copperSurchargeForPrice = $lineObj->copper_surcharge / $lineObj->copper_surcharge_basis_qty;
                    }
                }

                // Calculate selling price
                $sellingPrice = ($purchasePrice + $copperSurchargeForPrice) * (1 + $markup / 100);

                // Check if product already exists in Dolibarr
                $existingProductId = 0;
                $productAction = 'create'; // 'create' or 'assign'

                // 1. Check by supplier reference (ProductFournisseur)
                $sqlCheck = "SELECT DISTINCT pf.fk_product FROM ".MAIN_DB_PREFIX."product_fournisseur_price as pf";
                $sqlCheck .= " WHERE pf.fk_soc = ".(int)$import->fk_soc;
                $sqlCheck .= " AND pf.ref_fourn = '".$db->escape($datanorm->article_number)."'";
                $sqlCheck .= " AND pf.entity IN (".getEntity('product').")";
                $resqlCheck = $db->query($sqlCheck);
                if ($resqlCheck && $db->num_rows($resqlCheck) > 0) {
                    $objCheck = $db->fetch_object($resqlCheck);
                    $existingProductId = $objCheck->fk_product;
                    $productAction = 'assign';
                }

                // 2. Check by product reference pattern
                if ($existingProductId <= 0) {
                    $expectedRef = 'NEW-'.$supplierPrefix.'-'.$datanorm->article_number;
                    $existingProduct = new Product($db);
                    $fetchResult = $existingProduct->fetch(0, $expectedRef);
                    if ($fetchResult > 0) {
                        $existingProductId = $existingProduct->id;
                        $productAction = 'assign';
                    }
                }

                // 3. Check by EAN if available
                if ($existingProductId <= 0 && !empty($datanorm->ean)) {
                    $sqlEan = "SELECT rowid FROM ".MAIN_DB_PREFIX."product";
                    $sqlEan .= " WHERE barcode = '".$db->escape($datanorm->ean)."'";
                    $sqlEan .= " AND entity IN (".getEntity('product').")";
                    $resqlEan = $db->query($sqlEan);
                    if ($resqlEan && $db->num_rows($resqlEan) > 0) {
                        $objEan = $db->fetch_object($resqlEan);
                        $existingProductId = $objEan->rowid;
                        $productAction = 'assign';
                    }
                }

                // Build supplier alternatives array
                // Only show suppliers that don't already have a price for this product
                $supplierAlternatives = array();
                $existingPriceSuppliers = array();

                // If product exists, load existing supplier prices
                if ($existingProductId > 0) {
                    $sqlExisting = "SELECT fk_soc FROM ".MAIN_DB_PREFIX."product_fournisseur_price";
                    $sqlExisting .= " WHERE fk_product = ".(int)$existingProductId;
                    $resExisting = $db->query($sqlExisting);
                    if ($resExisting) {
                        while ($objEx = $db->fetch_object($resExisting)) {
                            $existingPriceSuppliers[$objEx->fk_soc] = true;
                        }
                    }
                }

                foreach ($results as $altResult) {
                    // Skip if supplier already has a price for this product
                    if ($existingProductId > 0 && isset($existingPriceSuppliers[$altResult['fk_soc']])) {
                        continue;
                    }

                    $altSupplier = new Societe($db);
                    $altSupplier->fetch($altResult['fk_soc']);

                    $altPurchasePrice = $altResult['price'];
                    if ($altResult['price_unit'] > 1) {
                        $altPurchasePrice = $altResult['price'] / $altResult['price_unit'];
                    }

                    $supplierAlternatives[] = array(
                        'datanorm_id' => $altResult['id'],
                        'fk_soc' => $altResult['fk_soc'],
                        'supplier_name' => $altSupplier->name,
                        'article_number' => $altResult['article_number'],
                        'short_text1' => $altResult['short_text1'],
                        'price' => $altResult['price'],
                        'price_unit' => $altResult['price_unit'],
                        'purchase_price' => $altPurchasePrice,
                        'ean' => $altResult['ean'],
                        'manufacturer_ref' => $altResult['manufacturer_ref'],
                        'is_invoice_supplier' => ($altResult['fk_soc'] == $import->fk_soc),
                    );
                }

                // Store match info for preview
                $datanormPreviewMatches[] = array(
                    'line_id' => $lineObj->id,
                    'line_supplier_ref' => $lineObj->supplier_ref,
                    'line_product_name' => $lineObj->product_name,
                    'line_quantity' => $lineObj->quantity,
                    'line_unit_price' => $lineObj->unit_price,
                    'datanorm_id' => $datanorm->id,
                    'datanorm_article_number' => $datanorm->article_number,
                    'datanorm_short_text1' => $datanorm->short_text1,
                    'datanorm_short_text2' => $datanorm->short_text2,
                    'datanorm_price' => $datanorm->price,
                    'datanorm_price_unit' => $datanorm->price_unit,
                    'datanorm_ean' => $datanorm->ean,
                    'purchase_price' => $purchasePrice,
                    'selling_price' => $sellingPrice,
                    'copper_surcharge' => $copperSurchargeForPrice,
                    'existing_product_id' => $existingProductId,
                    'action' => $productAction,
                    'new_ref' => 'NEW-'.$supplierPrefix.'-'.$datanorm->article_number,
                    'supplier_alternatives' => $supplierAlternatives
                );
            }
        }
    }
    $action = 'edit';
}

// Create supplier invoice
if ($action == 'createinvoice' && $id > 0) {
    $import->fetch($id);

    // Check prerequisites
    if ($import->fk_soc <= 0) {
        $error++;
        setEventMessages($langs->trans('ErrorSupplierRequired'), null, 'errors');
    } else {
        // Check all lines have products
        $lines = $importLine->fetchAllByImport($id);
        $allHaveProducts = true;
        foreach ($lines as $line) {
            if ($line->fk_product <= 0) {
                $allHaveProducts = false;
                break;
            }
        }

        if (!$allHaveProducts) {
            $error++;
            setEventMessages($langs->trans('ErrorNotAllProductsAssigned'), null, 'errors');
        } else {
            // Load supplier to get default values
            $supplier = new Societe($db);
            $supplier->fetch($import->fk_soc);

            // Create invoice
            $invoice = new FactureFournisseur($db);
            $invoice->socid = $import->fk_soc;
            $invoice->ref_supplier = $import->invoice_number;
            $invoice->date = $import->invoice_date;
            $invoice->note_private = $langs->trans('ImportedFromZugferd').' ('.$import->ref.')';

            // Set label to most expensive item (for list display)
            $maxTotal = 0;
            $mostExpensiveLabel = '';
            foreach ($lines as $line) {
                $lineTotal = $line->quantity * $line->unit_price;
                if ($lineTotal > $maxTotal) {
                    $maxTotal = $lineTotal;
                    $mostExpensiveLabel = $line->product_name;
                }
            }
            if (!empty($mostExpensiveLabel)) {
                // Truncate to 255 chars (database field limit)
                $invoice->label = dol_trunc($mostExpensiveLabel, 255);
            }

            // Use supplier default values for payment
            $invoice->cond_reglement_id = $supplier->cond_reglement_supplier_id ?: 1;
            $invoice->mode_reglement_id = $supplier->mode_reglement_supplier_id ?: 0;
            $invoice->fk_account = $supplier->fk_account ?: 0;

            $db->begin();
            $result = $invoice->create($user);

            if ($result > 0) {
                // Add lines
                foreach ($lines as $line) {
                    $res = $invoice->addline(
                        $line->product_name,
                        $line->unit_price,
                        $line->tax_percent,
                        0, 0,
                        $line->quantity,
                        $line->fk_product,
                        0, '', '',
                        0, 0,
                        'HT',  // price_base_type - Netto-Preise aus ZUGFeRD
                        0      // type (0=product)
                    );
                    if ($res < 0) {
                        $error++;
                        setEventMessages($invoice->error, $invoice->errors, 'errors');
                        break;
                    }

                    // Update EAN on product if not set
                    if (!empty($line->ean) && $line->fk_product > 0) {
                        $product = new Product($db);
                        $product->fetch($line->fk_product);
                        if (empty($product->barcode)) {
                            $product->barcode = $line->ean;
                            $product->barcode_type = 2; // EAN13
                            $product->update($product->id, $user);
                        }
                    }
                }

                if (!$error) {
                    // Invoice stays as draft - user can validate manually

                    // Copy PDF to invoice and register in ECM
                    // Neuer Pfad: /imports/{id}/{filename}
                    $source_pdf = $conf->importzugferd->dir_output.'/imports/'.$import->id.'/'.$import->pdf_filename;
                    // Fallback: Alter Pfad /imports/{ref}_{filename}
                    if (!file_exists($source_pdf)) {
                        $source_pdf = $conf->importzugferd->dir_output.'/imports/'.$import->ref.'_'.$import->pdf_filename;
                    }
                    if (file_exists($source_pdf)) {
                        // Relativer Pfad für ECM (ohne DOL_DATA_ROOT Prefix)
                        $rel_dir = 'fournisseur/facture/'.get_exdir($invoice->id, 2, 0, 0, $invoice, 'invoice_supplier').$invoice->ref;
                        $dest_dir = $conf->fournisseur->facture->dir_output.'/'.get_exdir($invoice->id, 2, 0, 0, $invoice, 'invoice_supplier').$invoice->ref;

                        if (!is_dir($dest_dir)) {
                            dol_mkdir($dest_dir);
                        }

                        $dest_file = $dest_dir.'/'.$import->pdf_filename;
                        if (@copy($source_pdf, $dest_file)) {
                            // In ECM-Datenbank registrieren für korrekte Verknüpfung
                            require_once DOL_DOCUMENT_ROOT.'/ecm/class/ecmfiles.class.php';
                            $ecmfile = new EcmFiles($db);
                            $ecmfile->filepath = $rel_dir;
                            $ecmfile->filename = $import->pdf_filename;
                            $ecmfile->label = md5_file(dol_osencode($dest_file));
                            $ecmfile->fullpath_orig = $dest_file;
                            $ecmfile->gen_or_uploaded = 'uploaded';
                            $ecmfile->description = 'ZUGFeRD Import - '.$import->invoice_number;
                            $ecmfile->src_object_type = 'supplier_invoice';
                            $ecmfile->src_object_id = $invoice->id;
                            $ecmfile->entity = $conf->entity;
                            $result = $ecmfile->create($user);
                            if ($result < 0) {
                                dol_syslog('ImportZugferd: Fehler beim ECM-Eintrag: '.implode(',', $ecmfile->errors), LOG_ERR);
                            }
                        } else {
                            dol_syslog('ImportZugferd: Fehler beim Kopieren der PDF nach '.$dest_dir, LOG_ERR);
                        }
                    }

                    // Update import record
                    $import->fk_facture_fourn = $invoice->id;
                    $import->status = ZugferdImport::STATUS_PROCESSED;
                    $import->date_import = dol_now();
                    $import->update($user);

                    $db->commit();
                    setEventMessages($langs->trans('InvoiceCreatedSuccessfully'), null, 'mesgs');

                    // Redirect to invoice
                    header('Location: '.DOL_URL_ROOT.'/fourn/facture/card.php?facid='.$invoice->id);
                    exit;
                } else {
                    $db->rollback();
                }
            } else {
                $error++;
                setEventMessages($invoice->error, $invoice->errors, 'errors');
                $db->rollback();
            }
        }
    }
    $action = 'edit';
}

// Finish import - check for existing invoice and update status
if ($action == 'finishimport' && $id > 0) {
    $import->fetch($id);

    // Check all lines have products
    $lines = $importLine->fetchAllByImport($id);
    $allHaveProducts = true;
    foreach ($lines as $line) {
        if ($line->fk_product <= 0) {
            $allHaveProducts = false;
            break;
        }
    }

    if (!$allHaveProducts) {
        $error++;
        setEventMessages($langs->trans('ErrorNotAllProductsAssigned'), null, 'errors');
    } elseif ($import->fk_soc <= 0) {
        $error++;
        setEventMessages($langs->trans('ErrorSupplierRequired'), null, 'errors');
    } else {
        // Search for existing supplier invoice with this ref_supplier
        $sql = "SELECT rowid FROM ".MAIN_DB_PREFIX."facture_fourn";
        $sql .= " WHERE fk_soc = ".((int) $import->fk_soc);
        $sql .= " AND ref_supplier = '".$db->escape($import->invoice_number)."'";
        $sql .= " LIMIT 1";

        $resql = $db->query($sql);
        if ($resql && $db->num_rows($resql) > 0) {
            $obj = $db->fetch_object($resql);
            // Found existing invoice - link it
            $import->fk_facture_fourn = $obj->rowid;
            $import->status = ZugferdImport::STATUS_PROCESSED;
            $import->date_import = dol_now();
            $result = $import->update($user);

            if ($result > 0) {
                $invoiceLink = '<a href="'.DOL_URL_ROOT.'/fourn/facture/card.php?facid='.$obj->rowid.'">'.$import->invoice_number.'</a>';
                setEventMessages($langs->trans('ImportLinkedToExistingInvoice', $invoiceLink), null, 'mesgs');
            } else {
                setEventMessages($import->error, null, 'errors');
            }
        } else {
            // No existing invoice - mark as imported (ready for invoice creation)
            $import->status = ZugferdImport::STATUS_IMPORTED;
            $result = $import->update($user);

            if ($result > 0) {
                setEventMessages($langs->trans('ImportFinished'), null, 'mesgs');
            } else {
                setEventMessages($import->error, null, 'errors');
            }
        }
    }
    $action = 'edit';
}

// Delete import record
if ($action == 'confirm_delete' && $confirm == 'yes' && $id > 0 && $user->hasRight('importzugferd', 'import', 'delete')) {
    $import->fetch($id);

    // Delete lines first
    $importLine->deleteAllByImport($id);

    // Delete files
    $import_dir = $conf->importzugferd->dir_output.'/imports/'.$import->id;
    if (is_dir($import_dir)) {
        dol_delete_dir_recursive($import_dir);
    }

    // Delete import record
    $import->delete($user);
    setEventMessages($langs->trans('RecordDeleted'), null, 'mesgs');

    header('Location: '.$_SERVER['PHP_SELF']);
    exit;
}

/*
 * View
 */

$title = $langs->trans('ZugferdImport');
llxHeader('', $title, '', '', 0, 0, '', '', '', 'mod-importzugferd page-import');

print load_fiche_titre($title, '', 'fa-file-import');

// Error message
if ($error && !empty($message)) {
    setEventMessages($message, null, 'errors');
}

/*
 * Upload form (shown when no import is being edited)
 */
if (empty($action) || ($action == 'upload' && $error)) {
    print '<form method="POST" action="'.$_SERVER['PHP_SELF'].'" enctype="multipart/form-data">';
    print '<input type="hidden" name="token" value="'.newToken().'">';
    print '<input type="hidden" name="action" value="upload">';

    print '<div class="fichecenter">';
    print '<div class="fichethirdleft">';

    print '<div class="div-table-responsive-no-min">';
    print '<table class="noborder centpercent">';
    print '<tr class="liste_titre">';
    print '<td colspan="2">'.$langs->trans('UploadZugferdInvoice').'</td>';
    print '</tr>';

    print '<tr class="oddeven">';
    print '<td class="titlefield">'.$langs->trans('File').' (PDF)</td>';
    print '<td>';
    print '<input type="file" name="zugferd_file" accept=".pdf" class="flat minwidth300" required>';
    print '</td>';
    print '</tr>';

    print '<tr class="oddeven">';
    print '<td>'.$langs->trans('ForceReimport').'</td>';
    print '<td>';
    print '<input type="checkbox" name="force_reimport" value="1"> ';
    print '<span class="opacitymedium">'.$langs->trans('ForceReimportHelp').'</span>';
    print '</td>';
    print '</tr>';

    print '</table>';
    print '</div>';

    print '<div class="center" style="margin-top: 20px;">';
    print '<input type="submit" class="button button-primary" value="'.$langs->trans('Upload').'">';
    print '</div>';

    print '</div>';

    // Show pending imports
    print '<div class="fichetwothirdright">';
    print '<div class="div-table-responsive-no-min">';
    print '<table class="noborder centpercent">';
    print '<tr class="liste_titre">';
    print '<td colspan="5">'.$langs->trans('PendingImports').'</td>';
    print '</tr>';

    $sql = "SELECT i.rowid, i.ref, i.invoice_number, i.seller_name, i.total_ttc, i.status, i.date_creation";
    $sql .= " FROM ".MAIN_DB_PREFIX."importzugferd_import as i";
    $sql .= " WHERE i.entity = ".$conf->entity;
    $sql .= " AND i.status IN (".ZugferdImport::STATUS_IMPORTED.", ".ZugferdImport::STATUS_PENDING.")";
    $sql .= " ORDER BY i.date_creation DESC LIMIT 10";

    $resql = $db->query($sql);
    if ($resql) {
        $num = $db->num_rows($resql);
        if ($num > 0) {
            print '<tr class="liste_titre">';
            print '<td>'.$langs->trans('Ref').'</td>';
            print '<td>'.$langs->trans('InvoiceNumber').'</td>';
            print '<td>'.$langs->trans('Supplier').'</td>';
            print '<td class="right">'.$langs->trans('TotalTTC').'</td>';
            print '<td>'.$langs->trans('Status').'</td>';
            print '</tr>';

            while ($obj = $db->fetch_object($resql)) {
                print '<tr class="oddeven">';
                print '<td><a href="'.$_SERVER['PHP_SELF'].'?id='.$obj->rowid.'">'.$obj->ref.'</a></td>';
                print '<td>'.$obj->invoice_number.'</td>';
                print '<td>'.$obj->seller_name.'</td>';
                print '<td class="right">'.price($obj->total_ttc).'</td>';
                print '<td>';
                $tmpimport = new ZugferdImport($db);
                print $tmpimport->LibStatut($obj->status, 1);
                print '</td>';
                print '</tr>';
            }
        } else {
            print '<tr class="oddeven"><td colspan="5" class="opacitymedium">'.$langs->trans('NoPendingImports').'</td></tr>';
        }
    }

    print '</table>';
    print '</div>';
    print '</div>';

    print '</div>';
    print '</form>';
}

/*
 * Delete confirmation dialog
 */
if ($action == 'delete' && $id > 0) {
    $import->fetch($id);
    $formconfirm = $form->formconfirm(
        $_SERVER['PHP_SELF'].'?id='.$import->id,
        $langs->trans('DeleteImportRecord'),
        $langs->trans('ConfirmDeleteImportRecord', $import->ref),
        'confirm_delete',
        '',
        0,
        1
    );
    print $formconfirm;
    $action = 'edit'; // Continue showing the edit form
}

/*
 * Edit/Review import
 */
if ($action == 'edit' && $import->id > 0) {
    // Fetch lines
    $lines = $importLine->fetchAllByImport($import->id);
    $missingProducts = $importLine->countLinesWithoutProduct($import->id);
    $allComplete = ($missingProducts == 0 && $import->fk_soc > 0);

    // Header info
    print '<div class="fichecenter">';

    // Status banner
    if ($import->status == ZugferdImport::STATUS_PENDING) {
        print '<div class="warning">';
        print '<i class="fas fa-exclamation-triangle paddingright"></i>';
        print $langs->trans('ManualInterventionRequired');
        if ($missingProducts > 0) {
            print ' - '.$missingProducts.' '.$langs->trans('ProductsNotAssigned');
        }
        if ($import->fk_soc <= 0) {
            print ' - '.$langs->trans('SupplierNotAssigned');
        }
        print '</div><br>';
    } elseif ($allComplete) {
        print '<div class="ok" style="padding: 10px; margin-bottom: 10px;">';
        print '<i class="fas fa-check-circle paddingright"></i>';
        print $langs->trans('ReadyToCreateInvoice');
        print '</div>';
    }

    // Invoice data
    print '<div class="div-table-responsive-no-min">';
    print '<table class="noborder centpercent">';
    print '<tr class="liste_titre">';
    print '<td colspan="4">'.$langs->trans('InvoiceData').' - '.$import->ref.'</td>';
    print '</tr>';

    print '<tr class="oddeven">';
    print '<td class="titlefield">'.$langs->trans('InvoiceNumber').'</td>';
    print '<td><strong>'.dol_escape_htmltag($import->invoice_number).'</strong></td>';
    print '<td>'.$langs->trans('InvoiceDate').'</td>';
    print '<td>'.dol_print_date($import->invoice_date, 'day').'</td>';
    print '</tr>';

    print '<tr class="oddeven">';
    print '<td>'.$langs->trans('Supplier').'</td>';
    print '<td>'.dol_escape_htmltag($import->seller_name).'</td>';
    print '<td>'.$langs->trans('VATIntra').'</td>';
    print '<td>'.dol_escape_htmltag($import->seller_vat).'</td>';
    print '</tr>';

    print '<tr class="oddeven">';
    print '<td>'.$langs->trans('BuyerReference').'</td>';
    print '<td>'.dol_escape_htmltag($import->buyer_reference).'</td>';
    print '<td>'.$langs->trans('TotalHT').'</td>';
    print '<td>'.price($import->total_ht).' '.$import->currency.'</td>';
    print '</tr>';

    print '<tr class="oddeven">';
    print '<td>'.$langs->trans('Status').'</td>';
    print '<td>'.$import->getLibStatut(1).'</td>';
    print '<td>'.$langs->trans('TotalTTC').'</td>';
    print '<td><strong>'.price($import->total_ttc).' '.$import->currency.'</strong></td>';
    print '</tr>';

    print '</table>';
    print '</div>';

    // Supplier selection
    print '<br>';
    print '<form method="POST" action="'.$_SERVER['PHP_SELF'].'">';
    print '<input type="hidden" name="token" value="'.newToken().'">';
    print '<input type="hidden" name="action" value="setsupplier">';
    print '<input type="hidden" name="id" value="'.$import->id.'">';

    print '<div class="div-table-responsive-no-min">';
    print '<table class="noborder centpercent">';
    print '<tr class="liste_titre">';
    print '<td colspan="2">'.$langs->trans('SupplierAssignment').'</td>';
    print '</tr>';

    print '<tr class="oddeven">';
    print '<td class="titlefield">'.$langs->trans('SelectSupplier').' <span class="fieldrequired">*</span></td>';
    print '<td>';
    print $form->select_company($import->fk_soc, 'supplier_id', 's.fournisseur = 1', 'SelectThirdParty', 0, 0, null, 0, 'minwidth300');
    print ' <input type="submit" class="button smallpaddingimp" value="'.$langs->trans('Save').'">';
    print '</td>';
    print '</tr>';

    print '</table>';
    print '</div>';
    print '</form>';

    // Line items
    print '<br>';
    // Form fuer fehlende Lieferantenpreise (ausserhalb der Tabelle, um verschachtelte Forms zu vermeiden)
    print '<form method="POST" action="'.$_SERVER['PHP_SELF'].'" id="missing_prices_form" style="display:none;">';
    print '<input type="hidden" name="token" value="'.newToken().'">';
    print '<input type="hidden" name="action" value="addmissingprices">';
    print '<input type="hidden" name="id" value="'.$import->id.'">';
    print '</form>';
    print '<div class="div-table-responsive">';
    print '<table class="noborder centpercent">';
    print '<tr class="liste_titre">';
    print '<td>'.$langs->trans('Position').'</td>';
    print '<td>'.$langs->trans('SupplierRef').'</td>';
    print '<td>'.$langs->trans('ProductDescription').'</td>';
    print '<td class="right">'.$langs->trans('Qty').'</td>';
    print '<td class="right">'.$langs->trans('UnitPrice').'</td>';
    print '<td class="right">'.$langs->trans('DolibarrPrice').'</td>';
    print '<td class="right">'.$langs->trans('TotalHT').'</td>';
    print '<td>'.$langs->trans('MatchedProduct').'</td>';
    print '<td>'.$langs->trans('Action').'</td>';
    print '</tr>';

    // Initialize totals for summary row
    $totalDolibarrHT = 0;
    $totalZugferdHT = 0;
    $hasDolibarrPrices = false;
    $allProductsMatched = true;
    $matchedLinesCount = 0;
    $totalLinesCount = count($lines);
    $allMissingPrices = array(); // Fehlende Lieferantenpreise sammeln
    $hasMissingPrices = false; // Flag für globale Buttons

    foreach ($lines as $line) {
        $hasProduct = ($line->fk_product > 0);
        $rowStyle = $hasProduct ? 'background-color: #dff0d8;' : ''; // Green for matched products

        print '<tr class="oddeven" style="'.$rowStyle.'">';
        print '<td>'.$line->line_id.'</td>';
        print '<td>'.dol_escape_htmltag($line->supplier_ref).'</td>';
        print '<td>';
        print dol_escape_htmltag($line->product_name);
        if (!empty($line->ean) && !$hasProduct) {
            print '<br><span style="color: #666;">EAN: '.dol_escape_htmltag($line->ean).'</span>';
        }
        print '</td>';
        print '<td class="right">'.price2num($line->quantity, 'MS').' '.zugferdGetUnitLabel($line->unit_code).'</td>';
        print '<td class="right">';
        print price($line->unit_price);
        if (!empty($line->basis_quantity) && $line->basis_quantity != 1) {
            print '<br><span style="color: #888; font-size: 0.9em;">('.price($line->unit_price_raw).'/'.price2num($line->basis_quantity, 'MS').zugferdGetUnitLabel($line->basis_quantity_unit).')</span>';
        }
        print '</td>';

        // Dolibarr price column - show supplier price and difference
        print '<td class="right nowraponall">';
        $lineDolibarrTotal = 0;
        if ($hasProduct && $import->fk_soc > 0) {
            require_once DOL_DOCUMENT_ROOT.'/fourn/class/fournisseur.product.class.php';
            $productFourn = new ProductFournisseur($db);
            // Use line quantity to find price for matching quantity tier (e.g. 100m cables)
            $searchQty = max(1, $line->quantity);
            $result = $productFourn->find_min_price_product_fournisseur($line->fk_product, $searchQty, $import->fk_soc);

            if ($result > 0 && $productFourn->fourn_unitprice > 0) {
                // Use unit price for comparison (per-unit, not per-quantity-tier)
                // Note: fourn_unitprice already INCLUDES copper surcharge - it's the total price from invoice
                // The extrafield 'kupferzuschlag' is only informational (shows copper portion of price)
                // The extrafield 'produktpreis' is only informational (shows material price without copper)
                $dolibarrUnitPrice = $productFourn->fourn_unitprice;
                $zugferdPrice = $line->unit_price;
                $priceDiff = $zugferdPrice - $dolibarrUnitPrice;
                $priceDiffPercent = ($dolibarrUnitPrice > 0) ? (($priceDiff / $dolibarrUnitPrice) * 100) : 0;

                // Accumulate for summary
                $lineDolibarrTotal = $dolibarrUnitPrice * $line->quantity;
                $totalDolibarrHT += $lineDolibarrTotal;
                $hasDolibarrPrices = true;
                $matchedLinesCount++;

                print price($dolibarrUnitPrice);

                if (abs($priceDiffPercent) >= 0.01) {
                    $threshold = getDolGlobalInt('IMPORTZUGFERD_PRICE_DIFF_THRESHOLD', 10);
                    $isSignificant = (abs($priceDiffPercent) >= $threshold);

                    print '<br>';
                    if ($priceDiff > 0) {
                        // ZUGFeRD price is higher
                        $iconColor = $isSignificant ? 'color: #d9534f;' : 'color: #f0ad4e;';
                        print '<span style="'.$iconColor.'" title="'.$langs->trans('PriceIncrease').'">';
                        print '<i class="fas fa-arrow-up"></i> +'.number_format($priceDiffPercent, 1).'%';
                        print '</span>';
                    } else {
                        // ZUGFeRD price is lower
                        $iconColor = $isSignificant ? 'color: #5cb85c;' : 'color: #5bc0de;';
                        print '<span style="'.$iconColor.'" title="'.$langs->trans('PriceDecrease').'">';
                        print '<i class="fas fa-arrow-down"></i> '.number_format($priceDiffPercent, 1).'%';
                        print '</span>';
                    }
                } else {
                    print '<br><span class="opacitymedium"><i class="fas fa-equals"></i></span>';
                }
            } else {
                print '<span class="opacitymedium">'.$langs->trans('NoPriceFound').'</span>';
                $allProductsMatched = false; // No price found for matched product
            }
        } else {
            print '<span class="opacitymedium">-</span>';
            $allProductsMatched = false; // Product not matched
        }
        print '</td>';

        print '<td class="right">'.price($line->line_total).'</td>';
        print '<td>';

        if ($hasProduct) {
            $product = new Product($db);
            $product->fetch($line->fk_product);
            print $product->getNomUrl(1);
            if (!empty($line->match_method)) {
                print '<br><span class="opacitymedium">'.$langs->trans('MatchMethod').': '.$line->match_method.'</span>';
            }
            if (!empty($line->ean)) {
                print '<br><span class="opacitymedium"><i class="fas fa-barcode"></i> '.dol_escape_htmltag($line->ean).'</span>';
            }
            print ' <i class="fas fa-check-circle" style="color: green;"></i>';

            // Alle Einkaufspreise des Produktes anzeigen
            $sqlPrices = "SELECT pfp.fk_soc, pfp.price, pfp.unitprice, pfp.ref_fourn, pfp.quantity, s.nom as supplier_name";
            $sqlPrices .= " FROM ".MAIN_DB_PREFIX."product_fournisseur_price pfp";
            $sqlPrices .= " LEFT JOIN ".MAIN_DB_PREFIX."societe s ON s.rowid = pfp.fk_soc";
            $sqlPrices .= " WHERE pfp.fk_product = ".(int)$line->fk_product;
            $sqlPrices .= " ORDER BY pfp.unitprice ASC";
            $resPrices = $db->query($sqlPrices);
            if ($resPrices && $db->num_rows($resPrices) > 0) {
                print '<div style="margin-top: 4px; font-size: 0.85em; line-height: 1.4;">';
                while ($objP = $db->fetch_object($resPrices)) {
                    $isInvoiceSupplier = ($objP->fk_soc == $import->fk_soc);
                    $style = $isInvoiceSupplier ? 'font-weight: bold;' : 'color: #666;';
                    print '<div style="'.$style.'">';
                    print dol_escape_htmltag($objP->supplier_name);
                    print ': <strong>'.price($objP->unitprice).'</strong>';
                    if ($objP->quantity > 1) {
                        print ' <span class="opacitymedium">('.price($objP->price).'/'.(int)$objP->quantity.'Stk.)</span>';
                    }
                    if (!empty($objP->ref_fourn)) {
                        print ' <span class="opacitymedium">('.dol_escape_htmltag($objP->ref_fourn).')</span>';
                    }
                    if ($isInvoiceSupplier) {
                        print ' <i class="fas fa-file-invoice" style="color: #337ab7;" title="'.$langs->trans('SupplierAssignment').'"></i>';
                    }
                    print '</div>';
                }
                print '</div>';
            }
        } else {
            print '<span class="warning">'.$langs->trans('NoProductMatch').'</span>';
        }
        print '</td>';

        print '<td class="nowraponall">';
        if ($hasProduct) {
            // Remove assignment button
            print '<a href="'.$_SERVER['PHP_SELF'].'?action=removeproduct&line_id='.$line->id.'&id='.$import->id.'&token='.newToken().'" class="button buttongen">';
            print '<i class="fas fa-times"></i>';
            print '</a>';

            // Fehlende Lieferantenpreise aus anderen Katalogen sammeln (Anzeige weiter unten)
            if ($import->fk_soc > 0 && getDolGlobalString('IMPORTZUGFERD_DATANORM_SEARCH_ALL')) {
                // Alle vorhandenen Lieferantenpreise fuer dieses Produkt laden
                $sqlExistingPrices = "SELECT fk_soc, price, unitprice, barcode FROM ".MAIN_DB_PREFIX."product_fournisseur_price";
                $sqlExistingPrices .= " WHERE fk_product = ".(int)$line->fk_product;
                $resExistingPrices = $db->query($sqlExistingPrices);
                $existingSupplierIds = array();
                $currentSupplierPrice = 0;
                $supplierEan = '';
                if ($resExistingPrices) {
                    while ($objPrice = $db->fetch_object($resExistingPrices)) {
                        $existingSupplierIds[$objPrice->fk_soc] = true;
                        // Stueckpreis und EAN vom Rechnungslieferanten merken
                        if ($objPrice->fk_soc == $import->fk_soc) {
                            $currentSupplierPrice = $objPrice->unitprice;
                            if (!empty($objPrice->barcode)) {
                                $supplierEan = $objPrice->barcode;
                            }
                        }
                    }
                }

                // Suche mit Lieferanten-Artikelnummer (die EAN wird intern für Cross-Catalog verwendet)
                $datanormSearch = new Datanorm($db);
                $allCatalogResults = array();

                // Suche mit Artikelnummer - die Funktion nutzt dann die EAN für Cross-Catalog
                if (!empty($line->supplier_ref)) {
                    $allCatalogResults = $datanormSearch->searchByArticleNumber($line->supplier_ref, $import->fk_soc, true, 10);
                }

                if (!empty($allCatalogResults)) {

                    $missingSuppliers = array();
                    foreach ($allCatalogResults as $catalogResult) {
                        if (!isset($existingSupplierIds[$catalogResult['fk_soc']])) {
                            $altSupplier = new Societe($db);
                            $altSupplier->fetch($catalogResult['fk_soc']);

                            $altPurchasePrice = $catalogResult['price'];
                            if ($catalogResult['price_unit'] > 1) {
                                $altPurchasePrice = $catalogResult['price'] / $catalogResult['price_unit'];
                            }

                            $missingSuppliers[] = array(
                                'datanorm_id' => $catalogResult['id'],
                                'fk_soc' => $catalogResult['fk_soc'],
                                'supplier_name' => $altSupplier->name,
                                'article_number' => $catalogResult['article_number'],
                                'price' => $catalogResult['price'],
                                'price_unit' => $catalogResult['price_unit'],
                                'purchase_price' => $altPurchasePrice,
                                'ean' => $catalogResult['ean'],
                            );
                        }
                    }

                    if (!empty($missingSuppliers)) {
                        // Inline-Anzeige der fehlenden Lieferantenpreise direkt bei der Produktzeile
                        $toggleId = 'missing_inline_'.$line->id;
                        $missingCount = count($missingSuppliers);

                        print '<div class="missing-suppliers-inline" style="margin-top: 8px; padding: 8px; background-color: #fcf8e3; border: 1px solid #faebcc; border-radius: 4px;">';
                        print '<div style="font-weight: bold; cursor: pointer; color: #8a6d3b;" onclick="$(\'#'.$toggleId.'\').toggle(); $(this).find(\'.toggle-icon\').toggleClass(\'fa-chevron-down fa-chevron-up\');">';
                        print '<i class="fas fa-plus-circle paddingright"></i>';
                        print $langs->trans('MissingSupplierPrices');
                        print ' <span class="badge badge-warning">'.$missingCount.'</span>';
                        print ' <i class="fas fa-chevron-up toggle-icon" style="float: right; color: #999;"></i>';
                        print '</div>';

                        // Aufklappbarer Bereich (Standard: sichtbar/aufgeklappt)
                        print '<div id="'.$toggleId.'" class="missing-suppliers-content" style="margin-top: 5px;">';

                        foreach ($missingSuppliers as $missing) {
                            $priceDiffHtml = '';
                            if ($currentSupplierPrice > 0) {
                                $pDiff = $missing['purchase_price'] - $currentSupplierPrice;
                                $pDiffPercent = ($pDiff / $currentSupplierPrice) * 100;
                                if ($pDiff < 0) {
                                    $priceDiffHtml = ' <span style="color: #5cb85c;"><i class="fas fa-arrow-down"></i> '.number_format(abs($pDiffPercent), 1).'%</span>';
                                } elseif ($pDiff > 0) {
                                    $priceDiffHtml = ' <span style="color: #d9534f;"><i class="fas fa-arrow-up"></i> +'.number_format($pDiffPercent, 1).'%</span>';
                                } else {
                                    $priceDiffHtml = ' <span class="opacitymedium">=</span>';
                                }
                            }

                            // Wert: productId,socId,datanormId
                            $cbValue = $line->fk_product.','.$missing['fk_soc'].','.$missing['datanorm_id'];
                            print '<div style="padding: 3px 0 3px 10px;">';
                            print '<label style="cursor: pointer; display: block;">';
                            print '<input type="checkbox" name="add_prices[]" value="'.dol_escape_htmltag($cbValue).'" checked class="cb-missing-price" form="missing_prices_form" style="margin-right: 5px;">';
                            print '<strong>'.dol_escape_htmltag($missing['supplier_name']).'</strong>';
                            print ' <code style="font-size: 0.9em;">'.dol_escape_htmltag($missing['article_number']).'</code>';
                            print ' @ <strong>'.price($missing['purchase_price']).'</strong>';
                            print $priceDiffHtml;
                            print '</label>';
                            print '</div>';
                        }
                        print '</div>'; // End toggleable div
                        print '</div>'; // End inline box

                        // Track for global actions
                        $hasMissingPrices = true;
                    }
                }
            }
        } else {
            // Product selection form
            print '<form method="POST" action="'.$_SERVER['PHP_SELF'].'" class="inline-block">';
            print '<input type="hidden" name="token" value="'.newToken().'">';
            print '<input type="hidden" name="action" value="assignproduct">';
            print '<input type="hidden" name="line_id" value="'.$line->id.'">';
            print '<input type="hidden" name="id" value="'.$import->id.'">';
            print $form->select_produits('', 'product_id_'.$line->id, '', 0, 0, -1, 2, '', 0, array(), 0, '1', 0, 'minwidth150 maxwidth200', 1, '', 0);
            print ' <button type="submit" class="button buttongen" title="'.$langs->trans('AssignProduct').'">';
            print '<i class="fas fa-link"></i>';
            print '</button>';
            print '</form>';

            // Create new product link
            $create_url = DOL_URL_ROOT.'/product/card.php?action=create';
            $create_url .= '&label='.urlencode($line->product_name);
            $create_url .= '&price='.urlencode($line->unit_price);
            $create_desc = '';
            if (!empty($line->supplier_ref)) {
                $create_desc .= $langs->trans('SupplierRef').': '.$line->supplier_ref."\n";
            }
            if (!empty($line->unit_code)) {
                $create_desc .= $langs->trans('Unit').': '.zugferdGetUnitLabel($line->unit_code)."\n";
            }
            if (!empty($line->ean)) {
                $create_desc .= 'EAN: '.$line->ean."\n";
            }
            $create_url .= '&description='.urlencode(trim($create_desc));

            print '<br><a href="'.$create_url.'" target="_blank" class="button buttongen margintoponlyshort">';
            print '<i class="fas fa-plus-circle"></i> '.$langs->trans('CreateProduct');
            print '</a>';

            // Refresh-Button nach Produktanlage
            print ' <a href="'.$_SERVER['PHP_SELF'].'?id='.$import->id.'" class="button buttongen margintoponlyshort" title="'.$langs->trans('RefreshProductListHelp').'">';
            print '<i class="fas fa-sync-alt"></i>';
            print '</a>';

            // Product template
            print '<br>';
            print '<form method="POST" action="'.$_SERVER['PHP_SELF'].'" class="inline-block margintoponlyshort">';
            print '<input type="hidden" name="token" value="'.newToken().'">';
            print '<input type="hidden" name="action" value="duplicateproduct">';
            print '<input type="hidden" name="line_id" value="'.$line->id.'">';
            print '<input type="hidden" name="id" value="'.$import->id.'">';
            print $form->select_produits('', 'template_product_id_'.$line->id, '', 0, 0, -1, 2, '', 0, array(), 0, '1', 0, 'minwidth100 maxwidth150', 1, '', 0);
            print ' <button type="submit" class="button buttongen" title="'.$langs->trans('ProductTemplateHelp').'">';
            print '<i class="fas fa-copy"></i>';
            print '</button>';
            print '</form>';

            // Datanorm button (only if supplier is set and supplier_ref exists)
            if ($import->fk_soc > 0 && !empty($line->supplier_ref)) {
                // Check if Datanorm article exists
                $datanormCheck = new Datanorm($db);
                $searchAll = getDolGlobalString('IMPORTZUGFERD_DATANORM_SEARCH_ALL', 0);
                $datanormResults = $datanormCheck->searchByArticleNumber($line->supplier_ref, $import->fk_soc, $searchAll, 1);

                if (!empty($datanormResults)) {
                    $datanormArticle = $datanormResults[0];
                    print '<br>';
                    print '<a href="'.$_SERVER['PHP_SELF'].'?action=createfromdatanorm&line_id='.$line->id.'&id='.$import->id.'&token='.newToken().'" class="button buttongen margintoponlyshort" title="'.$langs->trans('CreateFromDatanormHelp').'">';
                    print '<i class="fas fa-database paddingright"></i>'.$langs->trans('CreateFromDatanorm');
                    print '</a>';
                    // Button to show raw Datanorm data
                    print ' <a href="#" class="button buttongen margintoponlyshort" onclick="showRawDatanorm(\''.dol_escape_js($line->supplier_ref).'\', '.$import->fk_soc.'); return false;" title="'.$langs->trans('ShowRawDatanorm').'">';
                    print '<i class="fas fa-file-code"></i>';
                    print '</a>';
                    // Show comparison: Invoice name vs Datanorm name
                    print '<div class="small" style="margin-top: 5px; padding: 5px; background-color: #e8f4fd; border-radius: 3px;">';
                    print '<table class="noborder" style="width: 100%; font-size: 0.85em;">';
                    print '<tr><td style="color: #666; width: 70px;"><i class="fas fa-file-invoice"></i> Rechnung:</td>';
                    print '<td><strong>'.dol_trunc($line->product_name, 50).'</strong></td></tr>';
                    print '<tr><td style="color: #666;"><i class="fas fa-database"></i> Datanorm:</td>';
                    print '<td style="color: #2980b9;"><strong>'.dol_trunc($datanormArticle['short_text1'], 50).'</strong>';
                    print ' <span style="color: #27ae60;">('.price($datanormArticle['price']).')</span></td></tr>';
                    print '</table>';
                    print '</div>';
                }
            }
        }
        print '</td>';
        print '</tr>';

        // Accumulate ZUGFeRD total
        $totalZugferdHT += $line->line_total;
    }

    // Summary row with total comparison
    // Only show full comparison if ALL products are matched with Dolibarr prices
    print '<tr style="background-color: #f5f5f5; font-weight: bold;">';
    print '<td colspan="5" class="right"><strong>'.$langs->trans('Total').' '.$langs->trans('TotalHT').'</strong></td>';

    if ($allProductsMatched && $hasDolibarrPrices) {
        // Full comparison possible - all products matched with prices
        $totalDiff = $totalZugferdHT - $totalDolibarrHT;
        $totalDiffPercent = ($totalDolibarrHT > 0) ? (($totalDiff / $totalDolibarrHT) * 100) : 0;

        // Determine colors: green if close match, red if significant difference
        $threshold = getDolGlobalInt('IMPORTZUGFERD_PRICE_DIFF_THRESHOLD', 10);
        $isMatch = (abs($totalDiffPercent) < 0.5); // Less than 0.5% difference = match
        $isSignificant = (abs($totalDiffPercent) >= $threshold);

        if ($isMatch) {
            $cellStyle = 'background-color: #dff0d8;'; // Green
        } elseif ($isSignificant) {
            $cellStyle = 'background-color: #f2dede;'; // Red
        } else {
            $cellStyle = 'background-color: #fcf8e3;'; // Yellow/warning
        }

        print '<td class="right nowraponall" style="'.$cellStyle.'">';
        print '<strong>'.price($totalDolibarrHT).'</strong>';
        if (abs($totalDiffPercent) >= 0.01) {
            print '<br>';
            if ($totalDiff > 0) {
                print '<span style="color: #d9534f;"><i class="fas fa-arrow-up"></i> +'.number_format($totalDiffPercent, 1).'%</span>';
            } elseif ($totalDiff < 0) {
                print '<span style="color: #5cb85c;"><i class="fas fa-arrow-down"></i> '.number_format($totalDiffPercent, 1).'%</span>';
            }
        }
        print '</td>';
        print '<td class="right" style="'.$cellStyle.'"><strong>'.price($totalZugferdHT).'</strong></td>';
        print '<td colspan="2" class="nowraponall" style="'.$cellStyle.'">';
        if ($isMatch) {
            print '<span style="color: #3c763d;"><i class="fas fa-check-circle"></i> '.$langs->trans('SumValidationOk').'</span>';
        } else {
            print '<span style="color: #a94442;"><i class="fas fa-exclamation-triangle"></i> '.$langs->trans('Difference').': '.price($totalDiff).' '.$import->currency.'</span>';
        }
        print '</td>';
    } else {
        // Not all products matched - show totals but no comparison
        print '<td class="right nowraponall">';
        if ($hasDolibarrPrices) {
            print '<span class="opacitymedium">'.price($totalDolibarrHT).'</span>';
            print '<br><span class="opacitymedium small">('.$matchedLinesCount.'/'.$totalLinesCount.')</span>';
        } else {
            print '<span class="opacitymedium">-</span>';
        }
        print '</td>';
        print '<td class="right"><strong>'.price($totalZugferdHT).'</strong></td>';
        print '<td colspan="2" class="nowraponall">';
        print '<span class="opacitymedium"><i class="fas fa-info-circle"></i> '.$langs->trans('ProductsNotAssigned').'</span>';
        print '</td>';
    }
    print '</tr>';

    print '</table>';
    print '</div>';

    // Aktionsbereich für fehlende Lieferantenpreise (wenn vorhanden)
    if ($hasMissingPrices) {
        print '<div style="margin-top: 10px; padding: 10px; background-color: #fcf8e3; border: 1px solid #faebcc; border-radius: 4px;">';
        print '<div style="display: flex; align-items: center; flex-wrap: wrap; gap: 10px;">';

        // Toggle Buttons
        print '<span style="color: #8a6d3b; font-weight: bold;"><i class="fas fa-plus-circle paddingright"></i>'.$langs->trans('MissingSupplierPrices').'</span>';
        print '<a href="#" onclick="$(\'.missing-suppliers-content\').show(); $(\'.missing-suppliers-inline .toggle-icon\').removeClass(\'fa-chevron-down\').addClass(\'fa-chevron-up\'); return false;" class="button buttongen small">';
        print '<i class="fas fa-expand-alt paddingright"></i>'.$langs->trans('ExpandAll');
        print '</a>';
        print '<a href="#" onclick="$(\'.missing-suppliers-content\').hide(); $(\'.missing-suppliers-inline .toggle-icon\').removeClass(\'fa-chevron-up\').addClass(\'fa-chevron-down\'); return false;" class="button buttongen small">';
        print '<i class="fas fa-compress-alt paddingright"></i>'.$langs->trans('CollapseAll');
        print '</a>';

        // Checkbox Buttons
        print '<span style="border-left: 1px solid #ccc; padding-left: 10px;">';
        print '<a href="#" onclick="$(\'.cb-missing-price\').prop(\'checked\', true); return false;" class="button buttongen small">';
        print '<i class="fas fa-check-square paddingright"></i>'.$langs->trans('SelectAll');
        print '</a>';
        print '</span>';
        print '<a href="#" onclick="$(\'.cb-missing-price\').prop(\'checked\', false); return false;" class="button buttongen small">';
        print '<i class="fas fa-square paddingright"></i>'.$langs->trans('DeselectAll');
        print '</a>';

        // Submit Button
        print '<span style="border-left: 1px solid #ccc; padding-left: 10px;">';
        print '<button type="submit" form="missing_prices_form" class="button buttongen">';
        print '<i class="fas fa-plus paddingright"></i>'.$langs->trans('AddSelectedPrices');
        print '</button>';
        print '</span>';

        print '</div>';
        print '</div>';
    }

    // missing_prices_form ist bereits oben geschlossen (ausgelagert wegen verschachtelter Forms)

    // Datanorm Preview Section (shown when preview action was triggered)
    if (!empty($datanormPreviewMatches)) {
        print '<div class="div-table-responsive-no-min" style="margin-top: 20px;">';
        print '<div class="titre" style="margin-bottom: 10px;">';
        print '<i class="fas fa-database paddingright"></i>'.$langs->trans('DatanormPreview');
        print ' <span class="badge badge-info">'.count($datanormPreviewMatches).' '.$langs->trans('Matches').'</span>';
        print '</div>';

        print '<form method="POST" action="'.$_SERVER['PHP_SELF'].'" id="datanorm_confirm_form">';
        print '<input type="hidden" name="token" value="'.newToken().'">';
        print '<input type="hidden" name="action" value="createallfromdatanorm">';
        print '<input type="hidden" name="id" value="'.$import->id.'">';

        print '<table class="noborder centpercent">';
        print '<tr class="liste_titre">';
        print '<th class="center" style="width: 30px;"><input type="checkbox" id="checkall_datanorm" checked></th>';
        print '<th>'.$langs->trans('SupplierRef').'</th>';
        print '<th>'.$langs->trans('InvoiceProductName').'</th>';
        print '<th>'.$langs->trans('DatanormProductName').'</th>';
        print '<th class="right">'.$langs->trans('InvoicePrice').'</th>';
        print '<th class="right">'.$langs->trans('DatanormPrice').'</th>';
        print '<th class="right">'.$langs->trans('SellingPrice').'</th>';
        print '<th class="center">'.$langs->trans('Action').'</th>';
        print '</tr>';

        $countCreate = 0;
        $countAssign = 0;
        foreach ($datanormPreviewMatches as $match) {
            $rowClass = ($match['action'] == 'assign') ? 'background-color: #d9edf7;' : 'background-color: #dff0d8;';

            print '<tr class="oddeven" style="'.$rowClass.'">';
            print '<td class="center"><input type="checkbox" name="selected_lines[]" value="'.$match['line_id'].'" checked></td>';
            print '<td><strong>'.$match['datanorm_article_number'].'</strong>';
            if (!empty($match['datanorm_ean'])) {
                print '<br><span class="small" style="color: #666;">EAN: '.$match['datanorm_ean'].'</span>';
            }
            print '</td>';

            // Invoice product name
            print '<td>';
            print '<span style="color: #666;">'.dol_trunc($match['line_product_name'], 40).'</span>';
            print '</td>';

            // Datanorm product name
            print '<td>';
            print '<strong style="color: #2980b9;">'.dol_trunc($match['datanorm_short_text1'], 40).'</strong>';
            if (!empty($match['datanorm_short_text2'])) {
                print '<br><span class="small" style="color: #666;">'.dol_trunc($match['datanorm_short_text2'], 40).'</span>';
            }
            print '</td>';

            // Invoice price (from ZUGFeRD)
            print '<td class="right nowraponall">';
            print '<strong>'.price($match['line_unit_price']).'</strong>';
            print '</td>';

            // Datanorm price - show original price and calculated unit price
            print '<td class="right nowraponall">';
            if ($match['datanorm_price_unit'] > 1) {
                // Show original price and price unit
                print '<span class="small" style="color: #666;">'.price($match['datanorm_price']).'/'.$match['datanorm_price_unit'].'</span>';
                print '<br><strong>= '.price($match['purchase_price']).'</strong>';
            } else {
                print '<strong>'.price($match['purchase_price']).'</strong>';
            }
            if ($match['copper_surcharge'] > 0) {
                print '<br><span class="small" style="color: #d9534f;">+ '.price($match['copper_surcharge']).' Cu</span>';
            }
            print '</td>';

            // Selling price
            print '<td class="right nowraponall"><strong style="color: #27ae60;">'.price($match['selling_price']).'</strong></td>';

            // Action
            print '<td class="center nowraponall">';
            if ($match['action'] == 'assign') {
                print '<span class="badge badge-info" title="'.$langs->trans('ProductAlreadyExists').'"><i class="fas fa-link"></i> '.$langs->trans('Assign').'</span>';
                $countAssign++;
            } else {
                print '<span class="badge badge-success"><i class="fas fa-plus"></i> '.$langs->trans('Create').'</span>';
                print '<br><span class="small" style="color: #666;">'.$match['new_ref'].'</span>';
                $countCreate++;
            }
            print '</td>';
            print '</tr>';

            // Show supplier alternatives if available (more than 1 supplier found)
            if (!empty($match['supplier_alternatives']) && count($match['supplier_alternatives']) > 1) {
                $altCount = count($match['supplier_alternatives']);
                $toggleId = 'alt_'.$match['line_id'];
                print '<tr class="oddeven" style="background-color: #f9f9f9;">';
                print '<td></td>'; // Empty checkbox column
                print '<td colspan="7" style="padding: 10px;">';
                print '<div style="background-color: #fff; border: 1px solid #ddd; border-radius: 5px; padding: 10px;">';
                // Header mit Anzahl und Toggle-Button
                print '<div style="font-weight: bold; margin-bottom: 8px; color: #555; cursor: pointer;" onclick="$(\'#'.$toggleId.'\').toggle(); $(this).find(\'.toggle-icon\').toggleClass(\'fa-chevron-down fa-chevron-up\');">';
                print '<i class="fas fa-store-alt paddingright"></i>'.$langs->trans('SupplierAlternatives');
                print ' <span class="badge" style="background-color: #5bc0de;">'.$altCount.' '.$langs->trans('Suppliers').'</span>';
                print ' <i class="fas fa-chevron-up toggle-icon" style="float: right; color: #999;"></i>';
                print '</div>';
                // Aufklappbarer Bereich (Standard: sichtbar)
                print '<div id="'.$toggleId.'">';

                print '<table class="noborder" style="width: 100%; font-size: 0.9em;">';
                print '<tr style="background-color: #f5f5f5;">';
                print '<th class="center" style="width: 40px;">'.$langs->trans('Select').'</th>';
                print '<th>'.$langs->trans('Supplier').'</th>';
                print '<th>'.$langs->trans('SupplierRef').'</th>';
                print '<th>'.$langs->trans('EAN').'</th>';
                print '<th>'.$langs->trans('ManufacturerRef').'</th>';
                print '<th class="right">'.$langs->trans('UnitPrice').'</th>';
                print '<th class="right">'.$langs->trans('Difference').'</th>';
                print '</tr>';

                $lowestPrice = PHP_FLOAT_MAX;
                foreach ($match['supplier_alternatives'] as $alt) {
                    if ($alt['purchase_price'] < $lowestPrice) {
                        $lowestPrice = $alt['purchase_price'];
                    }
                }

                foreach ($match['supplier_alternatives'] as $altIdx => $alt) {
                    $isInvoiceSupplier = $alt['is_invoice_supplier'];
                    $isCheapest = ($alt['purchase_price'] == $lowestPrice);
                    $rowStyle = '';
                    if ($isInvoiceSupplier) {
                        $rowStyle = 'background-color: #d9edf7;'; // Blue for invoice supplier
                    } elseif ($isCheapest) {
                        $rowStyle = 'background-color: #dff0d8;'; // Green for cheapest
                    }

                    print '<tr style="'.$rowStyle.'">';

                    // Checkbox for selecting this supplier as purchase source
                    print '<td class="center">';
                    $checkboxName = 'supplier_prices['.$match['line_id'].']['.$alt['fk_soc'].']';
                    $checked = $isInvoiceSupplier ? ' checked' : '';
                    print '<input type="checkbox" name="'.$checkboxName.'" value="'.$alt['datanorm_id'].'"'.$checked.' title="'.$langs->trans('AddAsPurchasePrice').'">';
                    print '</td>';

                    // Supplier name
                    print '<td>';
                    print '<strong>'.dol_escape_htmltag($alt['supplier_name']).'</strong>';
                    if ($isInvoiceSupplier) {
                        print ' <span class="badge" style="background-color: #337ab7; font-size: 0.75em;"><i class="fas fa-file-invoice"></i></span>';
                    }
                    if ($isCheapest) {
                        print ' <span class="badge" style="background-color: #5cb85c; font-size: 0.75em;"><i class="fas fa-tag"></i></span>';
                    }
                    print '</td>';

                    // Supplier article number
                    print '<td><code>'.dol_escape_htmltag($alt['article_number']).'</code></td>';

                    // EAN
                    print '<td>';
                    if (!empty($alt['ean'])) {
                        print '<span class="small">'.dol_escape_htmltag($alt['ean']).'</span>';
                    } else {
                        print '<span class="opacitymedium">-</span>';
                    }
                    print '</td>';

                    // Manufacturer ref
                    print '<td>';
                    if (!empty($alt['manufacturer_ref'])) {
                        print '<span class="small">'.dol_escape_htmltag($alt['manufacturer_ref']).'</span>';
                    } else {
                        print '<span class="opacitymedium">-</span>';
                    }
                    print '</td>';

                    // Price
                    print '<td class="right nowraponall">';
                    if ($alt['price_unit'] > 1) {
                        print '<span class="small" style="color: #666;">'.price($alt['price']).'/'.$alt['price_unit'].'</span><br>';
                    }
                    print '<strong>'.price($alt['purchase_price']).'</strong>';
                    print '</td>';

                    // Difference from invoice supplier price
                    print '<td class="right nowraponall">';
                    if (!$isInvoiceSupplier && isset($match['purchase_price'])) {
                        $diff = $alt['purchase_price'] - $match['purchase_price'];
                        $diffPercent = ($match['purchase_price'] > 0) ? ($diff / $match['purchase_price'] * 100) : 0;
                        if ($diff < 0) {
                            print '<span style="color: #5cb85c;"><i class="fas fa-arrow-down"></i> '.price(abs($diff)).' ('.number_format(abs($diffPercent), 1).'%)</span>';
                        } elseif ($diff > 0) {
                            print '<span style="color: #d9534f;"><i class="fas fa-arrow-up"></i> +'.price($diff).' (+'.number_format($diffPercent, 1).'%)</span>';
                        } else {
                            print '<span class="opacitymedium">=</span>';
                        }
                    } else {
                        print '<span class="opacitymedium">-</span>';
                    }
                    print '</td>';

                    print '</tr>';
                }

                print '</table>';
                print '<div class="small opacitymedium" style="margin-top: 5px;">';
                print '<i class="fas fa-info-circle"></i> '.$langs->trans('SelectSuppliersForPurchasePrices');
                print '</div>';
                print '</div>'; // End toggleable div
                print '</div>'; // End white box
                print '</td>';
                print '</tr>';
            }
        }

        print '</table>';

        // Summary and confirm button
        print '<div class="center" style="margin-top: 15px; padding: 15px; background-color: #f5f5f5; border-radius: 5px;">';
        print '<div style="margin-bottom: 10px;">';
        if ($countCreate > 0) {
            print '<span class="badge badge-success" style="margin-right: 10px;"><i class="fas fa-plus"></i> '.$countCreate.' '.$langs->trans('ToCreate').'</span>';
        }
        if ($countAssign > 0) {
            print '<span class="badge badge-info"><i class="fas fa-link"></i> '.$countAssign.' '.$langs->trans('ToAssign').'</span>';
        }
        print '</div>';
        print '<button type="submit" class="button button-primary">';
        print '<i class="fas fa-check paddingright"></i>'.$langs->trans('ConfirmAndCreateProducts');
        print '</button>';
        print ' &nbsp; ';
        print '<a href="'.$_SERVER['PHP_SELF'].'?action=edit&id='.$import->id.'" class="button">';
        print '<i class="fas fa-times paddingright"></i>'.$langs->trans('Cancel');
        print '</a>';
        print '</div>';

        print '</form>';
        print '</div>';

        // JavaScript for select all checkbox
        print '<script>
        $(document).ready(function() {
            $("#checkall_datanorm").change(function() {
                $("input[name=\'selected_lines[]\']").prop("checked", this.checked);
            });
        });
        </script>';
    }

    // Action buttons
    print '<div class="center" style="margin-top: 20px;">';

    if ($allComplete) {
        print '<a href="'.$_SERVER['PHP_SELF'].'?action=createinvoice&id='.$import->id.'&token='.newToken().'" class="button button-primary">';
        print '<i class="fas fa-file-invoice paddingright"></i>'.$langs->trans('CreateSupplierInvoice');
        print '</a>';
        print ' &nbsp; ';
    }

    // Finish import button - shown when pending status and all products assigned
    if ($import->status == ZugferdImport::STATUS_PENDING && $allComplete) {
        print '<a href="'.$_SERVER['PHP_SELF'].'?action=finishimport&id='.$import->id.'&token='.newToken().'" class="button">';
        print '<i class="fas fa-check paddingright"></i>'.$langs->trans('FinishImport');
        print '</a>';
        print ' &nbsp; ';
    }

    // Datanorm buttons - show when products are missing and supplier is set
    if ($missingProducts > 0 && $import->fk_soc > 0 && empty($datanormPreviewMatches)) {
        // "Alle zuordnen" - creates all products from Datanorm
        print '<a href="'.$_SERVER['PHP_SELF'].'?action=createallfromdatanorm&id='.$import->id.'&token='.newToken().'" class="button">';
        print '<i class="fas fa-database paddingright"></i>'.$langs->trans('AssignAllFromDatanorm');
        print '</a>';
        print ' &nbsp; ';

        // "Datanorm Vorschau" - preview what will be created
        print '<a href="'.$_SERVER['PHP_SELF'].'?action=previewdatanorm&id='.$import->id.'&token='.newToken().'" class="button">';
        print '<i class="fas fa-search paddingright"></i>'.$langs->trans('PreviewDatanormMatches');
        print '</a>';
        print ' &nbsp; ';
    }

    print '<a href="'.dol_buildpath('/importzugferd/list.php', 1).'" class="button">'.$langs->trans('BackToList').'</a>';

    // Delete button - show for pending imports or imports without linked invoice
    $canDelete = ($import->status == ZugferdImport::STATUS_PENDING) ||
                 ($import->status == ZugferdImport::STATUS_IMPORTED && $import->fk_facture_fourn <= 0);
    if ($canDelete) {
        print ' &nbsp; ';
        print '<a href="'.$_SERVER['PHP_SELF'].'?action=delete&id='.$import->id.'&token='.newToken().'" class="button button-cancel">';
        print '<i class="fas fa-trash paddingright"></i>'.$langs->trans('Delete');
        print '</a>';
    }

    print '</div>';

    print '</div>';

    // Modal CSS and HTML for raw Datanorm data
    print '<style>
.datanorm-modal-overlay {
    display: none;
    position: fixed;
    top: 0;
    left: 0;
    width: 100%;
    height: 100%;
    background-color: rgba(0,0,0,0.5);
    z-index: 9999;
}
.datanorm-modal {
    position: relative;
    background: white;
    width: 90%;
    max-width: 700px;
    max-height: 85vh;
    margin: 50px auto;
    padding: 20px;
    border-radius: 5px;
    overflow-y: auto;
}
.datanorm-modal h3 {
    margin-top: 0;
    color: #333;
}
.datanorm-modal h4 {
    margin-bottom: 5px;
    color: #555;
    border-bottom: 1px solid #ddd;
    padding-bottom: 5px;
}
.datanorm-modal pre {
    background: #f5f5f5;
    padding: 10px;
    font-size: 11px;
    overflow-x: auto;
    white-space: pre-wrap;
    word-break: break-all;
}
.datanorm-modal .close-btn {
    float: right;
    cursor: pointer;
    font-size: 20px;
    color: #999;
}
.datanorm-modal .close-btn:hover {
    color: #333;
}
</style>';

    // Modal for raw data
    print '<div id="datanormRawModal" class="datanorm-modal-overlay" onclick="closeRawDatanormModal(event)">';
    print '<div class="datanorm-modal" onclick="event.stopPropagation()">';
    print '<span class="close-btn" onclick="closeRawDatanormModal()">&times;</span>';
    print '<h3><i class="fas fa-file-code"></i> Rohdaten: <span id="modalArticleNumber"></span></h3>';
    print '<div id="modalContent">';
    print '<p><em>Laden...</em></p>';
    print '</div>';
    print '</div>';
    print '</div>';

    print '<script>
function showRawDatanorm(articleNumber, fkSoc) {
    document.getElementById("datanormRawModal").style.display = "block";
    document.getElementById("modalArticleNumber").textContent = articleNumber;
    document.getElementById("modalContent").innerHTML = "<p><em>Laden...</em></p>";

    // AJAX request
    var xhr = new XMLHttpRequest();
    xhr.open("GET", "'.dol_escape_js($_SERVER['PHP_SELF']).'?action=get_raw_lines&article_number=" + encodeURIComponent(articleNumber) + "&fk_soc=" + fkSoc + "&token='.newToken().'", true);
    xhr.onreadystatechange = function() {
        if (xhr.readyState === 4) {
            if (xhr.status === 200) {
                try {
                    var data = JSON.parse(xhr.responseText);
                    var html = "";

                    html += "<h4>DATANORM (A-Satz)</h4>";
                    if (data.datanorm_line) {
                        html += "<pre>" + escapeHtml(data.datanorm_line) + "</pre>";
                        // Parse and show fields
                        var parts = data.datanorm_line.split(";");
                        html += "<table class=\"noborder\" style=\"margin-top:10px;font-size:12px;\">";
                        html += "<tr><td><b>0: Satzart</b></td><td>" + escapeHtml(parts[0] || "") + "</td></tr>";
                        html += "<tr><td><b>1: Aktionscode</b></td><td>" + escapeHtml(parts[1] || "") + "</td></tr>";
                        html += "<tr><td><b>2: Artikelnummer</b></td><td>" + escapeHtml(parts[2] || "") + "</td></tr>";
                        html += "<tr><td><b>3: Textkennzeichen</b></td><td>" + escapeHtml(parts[3] || "") + "</td></tr>";
                        html += "<tr><td><b>4: Kurztext 1</b></td><td>" + escapeHtml(parts[4] || "") + "</td></tr>";
                        html += "<tr><td><b>5: Kurztext 2</b></td><td>" + escapeHtml(parts[5] || "") + "</td></tr>";
                        html += "<tr><td><b>6: Preiskennzeichen</b></td><td>" + escapeHtml(parts[6] || "") + " (1=Brutto, 2=Netto)</td></tr>";
                        html += "<tr><td><b>7: PE-Code</b></td><td>" + escapeHtml(parts[7] || "") + " (0=1, 1=10, 2=100, 3=1000)</td></tr>";
                        html += "<tr><td><b>8: Mengeneinheit</b></td><td>" + escapeHtml(parts[8] || "") + "</td></tr>";
                        html += "<tr><td><b>9: Preis (Cent)</b></td><td>" + escapeHtml(parts[9] || "") + "</td></tr>";
                        html += "<tr><td><b>10: Rabattgruppe</b></td><td>" + escapeHtml(parts[10] || "") + "</td></tr>";
                        html += "<tr><td><b>11: Warengruppe</b></td><td>" + escapeHtml(parts[11] || "") + "</td></tr>";
                        html += "</table>";
                    } else {
                        html += "<p class=\"opacitymedium\">Keine DATANORM-Zeile gefunden</p>";
                    }

                    html += "<br><h4>DATPREIS (P-Satz)</h4>";
                    if (data.datpreis_line) {
                        html += "<pre>" + escapeHtml(data.datpreis_line) + "</pre>";
                        // Parse P-Satz
                        var pparts = data.datpreis_line.split(";");
                        html += "<table class=\"noborder\" style=\"margin-top:10px;font-size:12px;\">";
                        html += "<tr><td><b>0: Satzart</b></td><td>" + escapeHtml(pparts[0] || "") + "</td></tr>";
                        html += "<tr><td><b>1: Aktionscode</b></td><td>" + escapeHtml(pparts[1] || "") + "</td></tr>";
                        // Find the article in the P-Satz (multiple articles per line)
                        for (var i = 2; i < pparts.length; i += 9) {
                            if (pparts[i] && pparts[i].trim() === articleNumber) {
                                html += "<tr><td colspan=\"2\"><b>--- Artikel " + escapeHtml(pparts[i]) + " ---</b></td></tr>";
                                html += "<tr><td><b>" + i + ": Artikelnummer</b></td><td>" + escapeHtml(pparts[i] || "") + "</td></tr>";
                                html += "<tr><td><b>" + (i+1) + ": Preiskennzeichen</b></td><td>" + escapeHtml(pparts[i+1] || "") + " (2=Netto)</td></tr>";
                                html += "<tr><td><b>" + (i+2) + ": Preis (Cent)</b></td><td>" + escapeHtml(pparts[i+2] || "") + " = " + (parseFloat(pparts[i+2] || 0) / 100).toFixed(2) + " EUR</td></tr>";
                                html += "<tr><td><b>" + (i+3) + ": Unbekannt</b></td><td>" + escapeHtml(pparts[i+3] || "") + "</td></tr>";
                                html += "<tr><td><b>" + (i+4) + ": Metallzuschlag (Cent)</b></td><td>" + escapeHtml(pparts[i+4] || "") + " = " + (parseFloat(pparts[i+4] || 0) / 100).toFixed(2) + " EUR</td></tr>";
                                break;
                            }
                        }
                        html += "</table>";
                    } else {
                        html += "<p class=\"opacitymedium\">Keine DATPREIS-Zeile gefunden</p>";
                    }

                    if (data.error) {
                        html += "<br><p class=\"error\">" + escapeHtml(data.error) + "</p>";
                    }

                    document.getElementById("modalContent").innerHTML = html;
                } catch(e) {
                    document.getElementById("modalContent").innerHTML = "<p class=\"error\">Fehler beim Parsen: " + e.message + "</p><pre>" + escapeHtml(xhr.responseText) + "</pre>";
                }
            } else {
                document.getElementById("modalContent").innerHTML = "<p class=\"error\">HTTP Fehler: " + xhr.status + "</p>";
            }
        }
    };
    xhr.send();
}

function closeRawDatanormModal(event) {
    if (!event || event.target.id === "datanormRawModal") {
        document.getElementById("datanormRawModal").style.display = "none";
    }
}

function escapeHtml(text) {
    var div = document.createElement("div");
    div.appendChild(document.createTextNode(text || ""));
    return div.innerHTML;
}

// Close modal with ESC key
document.addEventListener("keydown", function(e) {
    if (e.key === "Escape") {
        closeRawDatanormModal();
    }
});
</script>';
}

llxFooter();
$db->close();
