<?php
/* Copyright (C) 2026 Eduard Wisch <data@data-it-solution.de>
 * GPL v3+
 *
 * Editor-Seite des Bericht-Moduls.
 * Eingang über Tab "Bericht" auf Rechnung/Auftrag/Angebot.
 *
 * Aufruf:
 *   /bericht/bericht_card.php?id=<parent_id>&element=invoice|order|propal
 *   /bericht/bericht_card.php?berichtid=<bericht_id>      (direkter Aufruf eines bestehenden Berichts)
 */

// Standard-Dolibarr-Include-Kaskade (symlink-sicher)
$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) die("Include of main fails");

require_once DOL_DOCUMENT_ROOT.'/core/lib/functions2.lib.php';
require_once __DIR__.'/class/bericht.class.php';
require_once __DIR__.'/lib/bericht.lib.php';

if (!$user->hasRight('bericht', 'read')) accessforbidden();

$langs->loadLangs(array("bericht@bericht", "main", "other"));

$id        = GETPOSTINT('id');
$berichtid = GETPOSTINT('berichtid');
$element   = GETPOST('element', 'alpha');
$action    = GETPOST('action', 'alpha');

// Bericht laden bzw. Parent ermitteln
$bericht = null;
$parent = null;

if ($berichtid > 0) {
    $bericht = new Bericht($db);
    if ($bericht->fetch($berichtid) <= 0) {
        accessforbidden('Bericht nicht gefunden');
    }
    $element = $bericht->element_type;
    $id      = $bericht->fk_element;
}

$parent = bericht_fetch_parent($db, $element, $id);
if (!$parent) {
    setEventMessages($langs->trans("BerichtErrorNoParent"), null, 'errors');
    llxHeader('', $langs->trans("Bericht"));
    print '<div class="error">'.$langs->trans("BerichtErrorNoParent").'</div>';
    llxFooter();
    exit;
}

$auftragsnummer = bericht_get_auftragsnummer($parent);

// Aktion: Bericht zur aktuellen Karte verknüpfen
if ($action === 'link' && $berichtid > 0 && $user->hasRight('bericht', 'write')) {
    $b = new Bericht($db);
    if ($b->fetch($berichtid) > 0) {
        $b->linkToElement($element, $parent->id);
        setEventMessages('Bericht der Rechnung zugeordnet', null, 'mesgs');
    }
    header("Location: ".$_SERVER['PHP_SELF'].'?id='.$parent->id.'&element='.$element);
    exit;
}

if ($action === 'unlink' && $berichtid > 0 && $user->hasRight('bericht', 'write')) {
    $b = new Bericht($db);
    if ($b->fetch($berichtid) > 0) {
        $b->unlinkFromElement($element, $parent->id);
        setEventMessages('Verknüpfung entfernt', null, 'mesgs');
    }
    header("Location: ".$_SERVER['PHP_SELF'].'?id='.$parent->id.'&element='.$element);
    exit;
}

// Aktion: neuen Bericht anlegen (ggf. aus Vorlage)
if ($action === 'create' && $user->hasRight('bericht', 'write')) {
    $tpl_id = GETPOSTINT('template_id');
    if ($tpl_id > 0) {
        $new_id = Bericht::createFromTemplate($db, $user, $tpl_id, $element, $parent->id, $auftragsnummer);
        if ($new_id) {
            header("Location: ".$_SERVER['PHP_SELF'].'?berichtid='.$new_id);
            exit;
        }
        setEventMessages('Vorlage konnte nicht angewendet werden', null, 'errors');
    }
    $b = new Bericht($db);
    $b->element_type   = $element;
    $b->fk_element     = $parent->id;
    $b->titel          = GETPOST('titel', 'alphanohtml') ?: ('Bericht '.$auftragsnummer);
    $b->auftragsnummer = $auftragsnummer;
    $b->template_odt   = getDolGlobalString('BERICHT_DEFAULT_TEMPLATE', '');
    if ($b->create($user) > 0) {
        header("Location: ".$_SERVER['PHP_SELF'].'?berichtid='.$b->id);
        exit;
    }
    setEventMessages($b->error, $b->errors, 'errors');
}

// Aktion: neue Version erstellen
if ($action === 'new_version' && $berichtid > 0 && $user->hasRight('bericht', 'write')) {
    $new_id = $bericht->duplicateAsNewVersion($user);
    if ($new_id) {
        setEventMessages('Neue Version erstellt', null, 'mesgs');
        header("Location: ".$_SERVER['PHP_SELF'].'?berichtid='.$new_id);
        exit;
    }
    setEventMessages('Versionierung fehlgeschlagen', null, 'errors');
}

// Aktion: Bericht löschen
if ($action === 'delete' && $berichtid > 0 && $user->hasRight('bericht', 'delete')) {
    if ($bericht->delete($user) > 0) {
        setEventMessages($langs->trans("BerichtDeleteSuccess"), null, 'mesgs');
        // Zurück auf die Tab-Übersicht (gleiche URL ohne berichtid)
        header("Location: ".$_SERVER['PHP_SELF'].'?id='.$parent->id.'&element='.$element);
        exit;
    }
    setEventMessages($bericht->error, $bericht->errors, 'errors');
}

/*
 * Anzeige
 */
$title = $langs->trans("Bericht").' — '.$parent->ref;
llxHeader('', $title, '', '', 0, 0, array(), array(dol_buildpath('/bericht/css/imageviewer.css', 1)), '', 'mod-bericht page-bericht-card');

// Header des Parent-Objekts (Standard-Dolibarr-Tabs für Rechnung/Auftrag/Angebot)
if ($element === 'invoice') {
    require_once DOL_DOCUMENT_ROOT.'/core/lib/invoice.lib.php';
    $head = facture_prepare_head($parent);
    print dol_get_fiche_head($head, 'bericht', $langs->trans("Bill"), -1, 'bill');
} elseif ($element === 'order') {
    require_once DOL_DOCUMENT_ROOT.'/core/lib/order.lib.php';
    $head = commande_prepare_head($parent);
    print dol_get_fiche_head($head, 'bericht', $langs->trans("CustomerOrder"), -1, 'order');
} elseif ($element === 'propal') {
    require_once DOL_DOCUMENT_ROOT.'/core/lib/propal.lib.php';
    $head = propal_prepare_head($parent);
    print dol_get_fiche_head($head, 'bericht', $langs->trans("Proposal"), -1, 'propal');
}

// Banner mit Parent-Infos
$linkback = '<a href="javascript:history.back()">'.$langs->trans("BackToList").'</a>';
dol_banner_tab($parent, 'ref', $linkback, 1, 'ref');
print dol_get_fiche_end();

print '<br>';

if (!$bericht) {
    /*
     * MODUS A: Übersicht
     * - Berichte direkt zugeordnet (element_type+fk_element)
     * - Berichte zusätzlich verknüpft (llx_element_element)
     * - NUR auf Rechnung: Berichte aus den verknüpften Aufträgen (read-only Sicht)
     */
    $list_direct = Bericht::fetchAllForElement($db, $element, $parent->id);
    $list_linked = Bericht::fetchLinkedForElement($db, $element, $parent->id);

    // Aus verknüpften Aufträgen: nur wenn aktuelle Karte eine Rechnung ist
    $list_from_orders = array();
    if ($element === 'invoice') {
        $parent->fetchObjectLinked();
        if (!empty($parent->linkedObjects['commande'])) {
            foreach ($parent->linkedObjects['commande'] as $linked_order) {
                $more = Bericht::fetchAllForElement($db, 'order', $linked_order->id);
                foreach ($more as $b) {
                    // Nicht doppelt zeigen wenn schon manuell verknüpft
                    $b->_source_order_ref = $linked_order->ref;
                    $b->_source_order_id  = $linked_order->id;
                    $list_from_orders[] = $b;
                }
            }
        }
    }

    // Set der bereits verknüpften IDs für Vergleich
    $linked_ids = array_map(function ($b) { return (int) $b->id; }, $list_linked);

    print '<div class="bericht-overview">';

    print '<div class="bericht-overview-header">';
    print '<h3>'.$langs->trans("Berichte").'</h3>';
    if ($user->hasRight('bericht', 'write')) {
        $templates = Bericht::fetchAllTemplates($db);
        print '<form method="post" class="inline-block" style="display:flex;gap:6px;align-items:center;">';
        print '<input type="hidden" name="token" value="'.newToken().'">';
        print '<input type="hidden" name="action" value="create">';
        print '<input type="hidden" name="id" value="'.$parent->id.'">';
        print '<input type="hidden" name="element" value="'.$element.'">';
        if (!empty($templates)) {
            print '<select name="template_id" title="Vorlage verwenden (optional)">';
            print '<option value="0">— Leerer Bericht —</option>';
            foreach ($templates as $t) {
                print '<option value="'.$t->id.'">📋 '.dol_escape_htmltag($t->template_label ?: $t->titel ?: $t->ref).'</option>';
            }
            print '</select>';
        }
        print '<button type="submit" class="butAction">+ '.$langs->trans("BerichtNew").'</button>';
        print '</form>';
    }
    print '</div>';

    /* ----- Helper: Bericht-Tabelle rendern ----- */
    $renderBerichtTable = function ($title, $items, $mode = 'direct') use ($langs, $user, $element, $parent) {
        if (empty($items)) return;
        print '<h4 style="margin-top:16px;margin-bottom:6px;opacity:0.8;">'.$title.' ('.count($items).')</h4>';
        print '<table class="noborder centpercent">';
        print '<tr class="liste_titre">';
        print '<th>'.$langs->trans("Ref").'</th>';
        print '<th>'.$langs->trans("BerichtTitle").'</th>';
        if ($mode === 'from_order') print '<th>Aus Auftrag</th>';
        print '<th>'.$langs->trans("BerichtCreatedAt").'</th>';
        print '<th>'.$langs->trans("BerichtStatus").'</th>';
        print '<th class="right">'.$langs->trans("Action").'</th>';
        print '</tr>';
        foreach ($items as $b) {
            $url = $_SERVER['PHP_SELF'].'?berichtid='.$b->id;
            print '<tr class="oddeven">';
            print '<td><a href="'.$url.'">'.dol_escape_htmltag($b->ref).'</a></td>';
            print '<td>'.dol_escape_htmltag($b->titel).'</td>';
            if ($mode === 'from_order') {
                print '<td>'.dol_escape_htmltag($b->_source_order_ref ?? '').'</td>';
            }
            print '<td>'.dol_print_date($b->datec, 'dayhour').'</td>';
            print '<td>'.$b->getLibStatut().'</td>';
            print '<td class="right">';
            print '<a href="'.$url.'" class="button-small">'.$langs->trans("Open").'</a> ';

            if ($mode === 'from_order' && $user->hasRight('bericht', 'write')) {
                print '<a href="'.$_SERVER['PHP_SELF'].'?action=link&berichtid='.$b->id.'&id='.$parent->id.'&element='.$element.'&token='.newToken().'" '
                    .'class="button-small" title="Diesen Bericht zusätzlich der aktuellen Karte zuordnen">→ Übernehmen</a> ';
            }
            if ($mode === 'linked' && $user->hasRight('bericht', 'write')) {
                print '<a href="'.$_SERVER['PHP_SELF'].'?action=unlink&berichtid='.$b->id.'&id='.$parent->id.'&element='.$element.'&token='.newToken().'" '
                    .'class="button-small" title="Verknüpfung lösen">⊗ Lösen</a> ';
            }
            if ($mode !== 'from_order' && $user->hasRight('bericht', 'delete')) {
                print '<a href="'.$_SERVER['PHP_SELF'].'?action=delete&berichtid='.$b->id.'&token='.newToken().'" '
                    .'data-dolconfirm="'.dol_escape_htmltag($langs->trans("BerichtConfirmDelete")).'" '
                    .'class="button-small button-delete">'.$langs->trans("Delete").'</a>';
            }
            print '</td>';
            print '</tr>';
        }
        print '</table>';
    };

    if (empty($list_direct) && empty($list_linked) && empty($list_from_orders)) {
        print '<div class="opacitymedium" style="padding:20px;">'.$langs->trans("BerichtNoReports").'</div>';
    } else {
        $renderBerichtTable('Berichte direkt zu dieser Karte', $list_direct, 'direct');
        $renderBerichtTable('Zusätzlich verknüpfte Berichte',  $list_linked, 'linked');
        if ($element === 'invoice') {
            // Auftragsberichte filtern: solche die schon verknüpft sind, ausblenden
            $remaining = array_filter($list_from_orders, function ($b) use ($linked_ids) {
                return !in_array((int) $b->id, $linked_ids, true);
            });
            $renderBerichtTable('Berichte aus verknüpften Aufträgen', $remaining, 'from_order');
        }
    }

    print '</div>';

    // Bestätigungsdialog für Lösch-Buttons (eigener Modal statt browser-confirm)
    print '<script>
document.addEventListener("click", function(e) {
    var el = e.target.closest("[data-dolconfirm]");
    if (!el) return;
    if (el.dataset._dolconfirmed === "1") return;
    e.preventDefault();
    e.stopPropagation();

    var msg = el.getAttribute("data-dolconfirm");
    var overlay = document.createElement("div");
    overlay.className = "bericht-dolmodal-overlay";
    overlay.innerHTML = \'<div class="bericht-dolmodal">\'
        + \'<div class="bericht-dolmodal-title">Bestätigen</div>\'
        + \'<div class="bericht-dolmodal-body"></div>\'
        + \'<div class="bericht-dolmodal-foot">\'
        + \'<button class="button" data-action="cancel">Abbrechen</button>\'
        + \'<button class="butActionDelete" data-action="ok">Löschen</button>\'
        + \'</div></div>\';
    overlay.querySelector(".bericht-dolmodal-body").textContent = msg;
    document.body.appendChild(overlay);

    overlay.addEventListener("click", function(ev) {
        var action = ev.target.getAttribute("data-action");
        if (!action && ev.target === overlay) action = "cancel";
        if (!action) return;
        overlay.remove();
        if (action === "ok") {
            el.dataset._dolconfirmed = "1";
            if (el.tagName === "A") window.location.href = el.getAttribute("href");
            else el.click();
        }
    });
}, true);
</script>';

} else {
    /*
     * MODUS B: Editor — bestehender Bericht wird bearbeitet
     */
    $pages = BerichtPage::fetchAllForBericht($db, $bericht->id);
    $attachments = bericht_collect_attachments($db, $parent, $element);
    $templates = bericht_list_templates();

    // Daten für JS bereitstellen
    $editor_config = array(
        'berichtid'    => (int) $bericht->id,
        'element_id'   => (int) $parent->id,
        'element_type' => $element,
        'token'        => newToken(),
        'urls'      => array(
            'save_annotations' => dol_buildpath('/bericht/ajax/save_annotations.php', 1),
            'upload_extra'     => dol_buildpath('/bericht/ajax/upload_extra.php', 1),
            'add_attachment'   => dol_buildpath('/bericht/ajax/add_attachment.php', 1),
            'delete_page'      => dol_buildpath('/bericht/ajax/delete_page.php', 1),
            'reorder_pages'    => dol_buildpath('/bericht/ajax/reorder_pages.php', 1),
            'page_image'       => dol_buildpath('/bericht/ajax/page_image.php', 1),
            'generate_pdf'     => dol_buildpath('/bericht/ajax/generate_pdf.php', 1),
            'preview_pdf'      => dol_buildpath('/bericht/ajax/preview_pdf.php', 1),
            'delete_attachment'=> dol_buildpath('/bericht/ajax/delete_attachment.php', 1),
            'save_meta'        => dol_buildpath('/bericht/ajax/save_meta.php', 1),
            'save_page_options'=> dol_buildpath('/bericht/ajax/save_page_options.php', 1),
            'create_grid_page' => dol_buildpath('/bericht/ajax/create_grid_page.php', 1),
            'set_slot_image'   => dol_buildpath('/bericht/ajax/set_slot_image.php', 1),
            'create_upload_token' => dol_buildpath('/bericht/ajax/create_upload_token.php', 1),
            'list_pages'       => dol_buildpath('/bericht/ajax/list_pages.php', 1),
            'verify_signature' => dol_buildpath('/bericht/ajax/verify_signature.php', 1),
            'save_as_template' => dol_buildpath('/bericht/ajax/save_as_template.php', 1),
        ),
        'lang' => array(
            'undo'        => $langs->trans("BerichtUndo"),
            'redo'        => $langs->trans("BerichtRedo"),
            'select'      => $langs->trans("BerichtToolSelect"),
            'draw'        => $langs->trans("BerichtToolDraw"),
            'rect'        => $langs->trans("BerichtToolRect"),
            'circle'      => $langs->trans("BerichtToolCircle"),
            'arrow'       => $langs->trans("BerichtToolArrow"),
            'text'        => $langs->trans("BerichtToolText"),
            'delete'      => $langs->trans("BerichtToolDelete"),
            'note_hint'   => $langs->trans("BerichtNoteHint"),
            'confirm_del' => $langs->trans("BerichtConfirmDelete"),
        ),
    );

    print '<div class="bericht-editor">';

    // Kopfzeile mit Bericht-Meta
    print '<div class="bericht-meta">';
    print '<form method="post" id="bericht-meta-form">';
    print '<input type="hidden" name="token" value="'.newToken().'">';
    print '<input type="hidden" name="berichtid" value="'.$bericht->id.'">';
    // Versionsliste derselben Kette ermitteln
    $chain_id = $bericht->fk_bericht_parent ?: $bericht->id;
    $version_links = '';
    $vres = $db->query("SELECT rowid, version FROM ".$db->prefix()."bericht"
        ." WHERE rowid = ".((int) $chain_id)." OR fk_bericht_parent = ".((int) $chain_id)
        ." ORDER BY version ASC");
    if ($vres) {
        $vs = array();
        while ($vr = $db->fetch_object($vres)) {
            $active = ((int) $vr->rowid === (int) $bericht->id);
            $vs[] = '<a href="'.$_SERVER['PHP_SELF'].'?berichtid='.$vr->rowid.'" '
                .($active ? 'style="font-weight:bold;text-decoration:underline;"' : '').'>v'.$vr->version.'</a>';
        }
        if (count($vs) > 1) $version_links = ' &nbsp; <span class="opacitymedium small">Versionen: '.implode(' · ', $vs).'</span>';
    }

    print '<table class="border centpercent"><tr>';
    print '<td class="titlefield">'.$langs->trans("Ref").'</td><td>'.dol_escape_htmltag($bericht->ref).' <span class="opacitymedium">v'.((int) $bericht->version).'</span>'.$version_links.'</td>';
    print '<td class="titlefield">'.$langs->trans("BerichtAuftragsnummer").'</td><td>'.dol_escape_htmltag($bericht->auftragsnummer).'</td>';
    print '</tr><tr>';
    print '<td>'.$langs->trans("BerichtTitle").'</td><td><input type="text" name="titel" value="'.dol_escape_htmltag($bericht->titel).'" size="40"></td>';
    print '<td>'.$langs->trans("BerichtTemplate").'</td><td><select name="template_odt">';
    print '<option value="">— '.$langs->trans("BerichtNoTemplate").' —</option>';
    foreach ($templates as $tpl) {
        $sel = ($tpl === $bericht->template_odt) ? ' selected' : '';
        print '<option value="'.dol_escape_htmltag($tpl).'"'.$sel.'>'.dol_escape_htmltag($tpl).'</option>';
    }
    print '</select></td>';
    print '</tr><tr>';
    // Format und Orientation
    print '<td>Format</td><td>';
    print '<select id="meta-format" name="page_format" title="Seitenformat des PDFs">';
    foreach (array('A4', 'A3', 'A5', 'Letter') as $fmt) {
        $sel = ($fmt === $bericht->page_format) ? ' selected' : '';
        print '<option value="'.$fmt.'"'.$sel.'>'.$fmt.'</option>';
    }
    print '</select>';
    print ' &nbsp; ';
    print '<select id="meta-orientation" name="page_orientation" title="Hoch- oder Querformat">';
    foreach (array('P' => 'Hochformat', 'L' => 'Querformat') as $k => $v) {
        $sel = ($k === $bericht->page_orientation) ? ' selected' : '';
        print '<option value="'.$k.'"'.$sel.'>'.$v.'</option>';
    }
    print '</select>';
    print '</td>';
    print '<td colspan="2"><span class="opacitymedium small">Wird beim Finalisieren angewendet</span></td>';
    print '</tr></table>';
    print '</form>';
    print '</div>';

    // Hauptlayout: links Anhänge, Mitte Editor, rechts Seiten
    print '<div class="bericht-layout">';

    // LINKS: Anhänge-Browser
    print '<aside class="bericht-attachments">';
    print '<h4>'.$langs->trans("BerichtAvailableAttachments").'</h4>';
    $by_source = array();
    foreach ($attachments as $a) {
        $key = $a['source'].':'.$a['source_ref'];
        $by_source[$key][] = $a;
    }
    if (empty($by_source)) {
        print '<div class="opacitymedium small">'.$langs->trans("None").'</div>';
    } else {
        foreach ($by_source as $key => $files) {
            list($src, $ref) = explode(':', $key, 2);
            print '<div class="bericht-att-group"><div class="bericht-att-group-title">'.dol_escape_htmltag($ref).'</div>';
            foreach ($files as $f) {
                $is_image = (strpos($f['mime'], 'image') === 0);
                $icon = $is_image ? '🖼' : ((strpos($f['mime'], 'pdf') !== false) ? '📄' : '📎');
                print '<div class="bericht-att-item">';
                print '<input type="checkbox" class="att-check" data-relpath="'.dol_escape_htmltag($f['relpath']).'" data-mime="'.dol_escape_htmltag($f['mime']).'" title="Auswählen">';

                if ($is_image) {
                    // Bild: Klickbar für Viewer
                    // relpath ist z.B. "facture/FA2025-0001/image.jpg" - erstes Segment ist modulepart
                    $relpath_parts = explode('/', $f['relpath'], 2);
                    $modulepart = $relpath_parts[0];
                    $file_in_module = $relpath_parts[1] ?? '';
                    $img_url = DOL_URL_ROOT.'/viewimage.php?modulepart='.urlencode($modulepart).'&file='.urlencode($file_in_module).'&entity='.$conf->entity;
                    print '<span class="att-preview" data-url="'.dol_escape_htmltag($img_url).'" data-filename="'.dol_escape_htmltag($f['filename']).'" data-group="'.dol_escape_htmltag($key).'" title="Klicken zum Vergrössern">';
                    print '<span class="att-icon">'.$icon.'</span>';
                    print '<span class="att-name" title="'.dol_escape_htmltag($f['filename']).'">'.dol_escape_htmltag($f['filename']).'</span>';
                    print '</span>';
                } else {
                    // Andere Dateien: nicht klickbar
                    print '<span class="att-icon">'.$icon.'</span>';
                    print '<span class="att-name" title="'.dol_escape_htmltag($f['filename']).'">'.dol_escape_htmltag($f['filename']).'</span>';
                }

                print '<span class="att-size opacitymedium small">'.dol_print_size($f['size']).'</span>';
                if ($user->hasRight('bericht', 'write')) {
                    print '<button type="button" class="att-delete" data-relpath="'.dol_escape_htmltag($f['relpath']).'" data-source-ref="'.dol_escape_htmltag($f['source_ref']).'" title="Diese Datei aus dem Anhang löschen">🗑️</button>';
                }
                print '</div>';
            }
            print '</div>';
        }
        print '<div class="bericht-add-selected" style="margin-top:6px;">';
        print '<label class="opacitymedium small" style="display:block;margin-bottom:4px;">Layout für die Auswahl:</label>';
        print '<select id="add-selected-layout" style="width:100%;margin-bottom:6px;">';
        print '<option value="single">Einzeln (1 Bild pro Seite)</option>';
        print '<option value="grid_2">2 pro Seite (oben/unten)</option>';
        print '<option value="grid_2v">2 pro Seite (links/rechts)</option>';
        print '<option value="grid_4">4 pro Seite (2x2)</option>';
        print '<option value="grid_6">6 pro Seite (3x2)</option>';
        print '<option value="before_after">Vorher / Nachher (2 pro Seite)</option>';
        print '</select>';
        print '<button type="button" id="btn-add-selected" class="butAction" style="width:100%;" title="Alle ausgewählten Bilder mit dem gewählten Layout in den Bericht übernehmen">'.$langs->trans("BerichtAddSelectedToReport").'</button>';
        print '</div>';
    }
    print '<hr>';
    print '<div class="bericht-upload">';
    print '<label for="bericht-extra-upload" class="butAction" title="Datei vom PC hochladen">📤 '.$langs->trans("BerichtUploadExtra").'</label>';
    print '<input type="file" id="bericht-extra-upload" style="display:none" accept=".pdf,.png,.jpg,.jpeg">';
    print '<button type="button" id="btn-show-qr" class="butAction" title="QR-Code für Mobile-Upload erzeugen" style="margin-top:6px;">📱 Mobil hochladen</button>';
    print '</div>';
    print '</aside>';

    // MITTE: PDF.js + Fabric.js Editor
    print '<main class="bericht-canvas-area">';
    print '<div class="bericht-toolbar">';
    print '<button type="button" class="tool-btn" data-tool="select" title="'.$langs->trans("BerichtToolSelect").'">↖</button>';
    print '<button type="button" class="tool-btn" data-tool="draw" title="'.$langs->trans("BerichtToolDraw").'">✏️</button>';
    print '<button type="button" class="tool-btn" data-tool="rect" title="'.$langs->trans("BerichtToolRect").'">▭</button>';
    print '<button type="button" class="tool-btn" data-tool="circle" title="'.$langs->trans("BerichtToolCircle").'">○</button>';
    print '<button type="button" class="tool-btn" data-tool="arrow" title="'.$langs->trans("BerichtToolArrow").'">↗</button>';
    print '<button type="button" class="tool-btn" data-tool="text" title="'.$langs->trans("BerichtToolText").'">T</button>';
    print '<span class="sep"></span>';
    print '<label title="Linien-/Textfarbe">'.$langs->trans("BerichtColor").': <input type="color" id="tool-color" value="#ff0000" title="Farbe wählen"></label>';
    print '<label title="Linien-/Strichstärke in Pixel">'.$langs->trans("BerichtStrokeWidth").': <input type="range" id="tool-stroke" min="1" max="20" value="3" title="Strichstärke"></label>';
    print '<span class="sep"></span>';
    print '<button type="button" id="btn-undo" title="'.$langs->trans("BerichtUndo").'">↶</button>';
    print '<button type="button" id="btn-redo" title="'.$langs->trans("BerichtRedo").'">↷</button>';
    print '<button type="button" id="btn-delete-selected" title="'.$langs->trans("BerichtToolDelete").'">🗑️</button>';

    // ====== Zweite Zeile ======
    print '<div class="row-break"></div>';

    // Text-Optionen
    print '<label class="text-tool-option" title="Schriftart für Text-Annotationen">Schrift: <select id="tool-fontfamily" title="Schriftart">'
        .'<option value="Helvetica">Helvetica</option>'
        .'<option value="Arial">Arial</option>'
        .'<option value="Times New Roman">Times New Roman</option>'
        .'<option value="Courier New">Courier New</option>'
        .'<option value="Verdana">Verdana</option>'
        .'<option value="Georgia">Georgia</option>'
        .'</select></label>';
    print '<label class="text-tool-option" title="Schriftgröße in Pixel">Größe: <input type="number" id="tool-fontsize" min="8" max="120" value="24" style="width:60px" title="Schriftgröße"></label>';
    print '<label class="text-tool-option" title="Fett"><input type="checkbox" id="tool-bold" title="Fett"> <b>B</b></label>';
    print '<label class="text-tool-option" title="Kursiv"><input type="checkbox" id="tool-italic" title="Kursiv"> <i>I</i></label>';
    print '<label class="text-tool-option" title="Text-Hintergrundfarbe">BG: <input type="color" id="tool-bgcolor" value="#ffffff"></label>';
    print '<button type="button" id="tool-bg-off" class="text-tool-option" title="Kein Hintergrund" style="padding:4px 8px;">Ø</button>';
    print '<span class="sep"></span>';
    // Zoom
    print '<button type="button" id="btn-zoom-out" title="Verkleinern (Zoom -)">🔍−</button>';
    print '<span id="zoom-label" title="Aktueller Zoom" style="min-width:42px;text-align:center;font-size:12px;">100%</span>';
    print '<button type="button" id="btn-zoom-in" title="Vergrößern (Zoom +)">🔍+</button>';
    print '<button type="button" id="btn-zoom-reset" title="Zoom auf 100% zurücksetzen">⟳%</button>';
    print '<span class="sep"></span>';
    print '<button type="button" id="btn-rotate-left" title="'.$langs->trans("BerichtRotateLeft").' (Seite 90° nach links drehen)">⟲</button>';
    print '<button type="button" id="btn-rotate-right" title="'.$langs->trans("BerichtRotateRight").' (Seite 90° nach rechts drehen)">⟳</button>';

    // ====== Dritte Zeile: Layout & Bildgröße der aktuellen Seite ======
    print '<div class="row-break"></div>';
    print '<label title="Seiten-Layout: Single = 1 Bild, Grid = mehrere Bilder">Layout: <select id="page-layout">'
        .'<option value="single">Single (1 Bild)</option>'
        .'<option value="grid_2">2 Bilder (oben/unten)</option>'
        .'<option value="grid_2v">2 Bilder (links/rechts)</option>'
        .'<option value="grid_4">4 Bilder (2x2)</option>'
        .'<option value="grid_6">6 Bilder (3x2)</option>'
        .'<option value="before_after">Vorher / Nachher</option>'
        .'<option value="title_only">Nur Titel</option>'
        .'</select></label>';
    print '<label class="single-only" title="Wie groß das Bild auf der Seite gedruckt wird (nur Single)">Größe: <select id="page-imgscale">'
        .'<option value="1.0">Vollseite (100%)</option>'
        .'<option value="0.7">Groß (70%)</option>'
        .'<option value="0.5">Mittel (50%)</option>'
        .'<option value="0.3">Klein (30%)</option>'
        .'</select></label>';
    print '<label class="single-only" title="Position auf der Seite (nur bei kleineren Bildern)">Position: <select id="page-imgalign">'
        .'<option value="fit">Anpassen</option>'
        .'<option value="center">Zentriert</option>'
        .'<option value="topleft">Oben links</option>'
        .'<option value="topright">Oben rechts</option>'
        .'<option value="bottomleft">Unten links</option>'
        .'<option value="bottomright">Unten rechts</option>'
        .'</select></label>';
    print '</div>';
    print '<div class="bericht-canvas-wrap">';
    print '<canvas id="pdf-canvas"></canvas>';
    print '<canvas id="fabric-canvas" class="fabric-overlay"></canvas>';
    print '</div>';
    print '<div class="bericht-page-note">';
    print '<label>'.$langs->trans("BerichtNoteHint").'</label>';
    // DolEditor (CKEditor) — wird im PDF mit writeHTMLCell gerendert
    require_once DOL_DOCUMENT_ROOT.'/core/class/doleditor.class.php';
    $noteEditor = new DolEditor('page-note', '', '100%', 120, 'dolibarr_notes', 'In', false, true, true, 4, '100%');
    $noteEditor->Create(0);
    print '</div>';
    print '</main>';

    // RECHTS: Seiten-Thumbnails
    print '<aside class="bericht-pages">';
    print '<div class="bericht-pages-header">';
    print '<h4>'.$langs->trans("BerichtPages").' (<span id="page-count">'.count($pages).'</span>)</h4>';
    print '<button type="button" id="btn-toggle-thumb-bg" title="Hell/Dunkel">🌓</button>';
    print '</div>';
    print '<div id="bericht-page-list" class="page-list paper-light">';
    foreach ($pages as $idx => $p) {
        // Ist das eine gehärtete Unterschrift? (hat .meta.json neben der source_path)
        $is_signature = false;
        if ($p->source_path && strpos($p->note ?? '', 'Unterschrift') === 0) {
            $full_check = DOL_DATA_ROOT.'/'.$p->source_path;
            if (file_exists($full_check.'.meta.json')) {
                $is_signature = true;
            }
        }
        print '<div class="page-thumb'.($is_signature ? ' page-signature' : '').'" data-pageid="'.$p->id.'" data-order="'.$p->page_order.'">';
        print '<div class="page-thumb-paper">';
        print '<canvas class="thumb-canvas"></canvas>';
        print '</div>';
        print '<div class="page-thumb-label"><span class="page-num">'.($idx + 1).'</span>'
            .($is_signature ? ' <span class="sig-badge" title="Unterschrift">🔒</span>' : '')
            .'</div>';
        print '<div class="page-thumb-actions">';
        if ($is_signature) {
            print '<button type="button" class="thumb-verify" title="Unterschrift prüfen" data-pageid="'.$p->id.'">🔍</button>';
        }
        print '<button type="button" class="thumb-del" title="'.$langs->trans("BerichtDeletePage").'">🗑️</button>';
        print '</div>';
        print '</div>';
    }
    print '</div>';
    print '</aside>';

    print '</div>'; // .bericht-layout

    // Footer-Aktionen
    print '<div class="bericht-actions">';
    print '<button type="button" id="btn-save-draft" class="butAction" title="Aktuellen Stand als Entwurf speichern">💾 '.$langs->trans("BerichtSaveDraft").'</button>';
    print '<button type="button" id="btn-preview" class="butAction" title="PDF-Vorschau ansehen ohne zu finalisieren">👁️ Vorschau</button>';
    print '<button type="button" id="btn-save-as-template" class="butAction" title="Aktuellen Bericht als wiederverwendbare Vorlage speichern">📋 Als Vorlage</button>';
    print '<a href="'.$_SERVER['PHP_SELF'].'?action=new_version&berichtid='.$bericht->id.'&token='.newToken().'" '
        .'data-dolconfirm="Neue Version (v'.((int)$bericht->version + 1).') erstellen? Der aktuelle Bericht bleibt unverändert." '
        .'class="butAction" title="Neue Version des Berichts anlegen, aktueller bleibt erhalten">🔀 Neue Version</a>';
    print '<button type="button" id="btn-finalize" class="butAction" title="PDF erzeugen und unter Verknüpfte Dokumente ablegen">📑 '.$langs->trans("BerichtFinalize").'</button>';
    if ($user->hasRight('bericht', 'delete')) {
        print '<a href="'.$_SERVER['PHP_SELF'].'?action=delete&berichtid='.$bericht->id.'&token='.newToken().'" '
            .'data-dolconfirm="'.dol_escape_htmltag($langs->trans("BerichtConfirmDelete")).'" '
            .'class="butActionDelete">🗑️ '.$langs->trans("Delete").'</a>';
    }
    print '</div>';

    print '</div>'; // .bericht-editor

    // PDF-Vorschau-Modal
    print '<div id="bericht-preview-modal" class="bericht-modal" style="display:none;">';
    print '  <div class="bericht-modal-backdrop"></div>';
    print '  <div class="bericht-modal-content">';
    print '    <div class="bericht-modal-header">';
    print '      <h3>📑 PDF-Vorschau</h3>';
    print '      <button type="button" id="bericht-modal-close" title="Schließen">✕</button>';
    print '    </div>';
    print '    <div class="bericht-modal-body">';
    print '      <iframe id="bericht-preview-iframe" src="about:blank"></iframe>';
    print '    </div>';
    print '  </div>';
    print '</div>';

    // QR-Code-Modal für Mobile-Upload
    print '<div id="bericht-qr-modal" class="bericht-modal" style="display:none;">';
    print '  <div class="bericht-modal-backdrop"></div>';
    print '  <div class="bericht-modal-content qr-modal">';
    print '    <div class="bericht-modal-header">';
    print '      <h3>📱 Mobile-Upload</h3>';
    print '      <button type="button" id="bericht-qr-close" title="Schließen">✕</button>';
    print '    </div>';
    print '    <div class="bericht-modal-body qr-modal-body">';
    print '      <div id="qr-code-container"></div>';
    print '      <div class="qr-info">';
    print '        <p>Scanne den QR-Code mit deinem Handy, um direkt Fotos in diesen Bericht hochzuladen.</p>';
    print '        <p class="opacitymedium small">Token gültig: <span id="qr-validity">—</span> Min</p>';
    print '        <p class="qr-url-display"><a id="qr-url-link" href="" target="_blank">Link öffnen</a></p>';
    print '        <p class="qr-status opacitymedium small">Warte auf Uploads…</p>';
    print '      </div>';
    print '    </div>';
    print '  </div>';
    print '</div>';

    // PDF.js + Fabric.js (lokal)
    print '<script src="'.dol_buildpath('/bericht/js/lib/pdf.min.js', 1).'"></script>';
    print '<script src="'.dol_buildpath('/bericht/js/lib/fabric.min.js', 1).'"></script>';
    print '<script src="'.dol_buildpath('/bericht/js/lib/Sortable.min.js', 1).'"></script>';
    print '<script src="'.dol_buildpath('/bericht/js/lib/qrcode.min.js', 1).'"></script>';
    print '<script src="'.dol_buildpath('/bericht/js/imageviewer.js', 1).'"></script>';
    print '<script>window.BERICHT_CONFIG = '.json_encode($editor_config).';</script>';
    print '<script src="'.dol_buildpath('/bericht/js/editor.js', 1).'"></script>';
}

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