<?php
/* GET /api/orders.php
 *   Liefert Aufträge des aktuellen Users.
 * GET /api/orders.php?id=<id>
 *   Liefert Detail eines einzelnen Auftrags.
 * GET /api/orders.php?id=<id>&action=photos
 *   Liefert die Anhang-Bilder/PDFs eines Auftrags.
 * POST /api/orders.php?id=<id>&action=upload_photo
 *   multipart: file=<binary> — fügt ein Foto zum Bericht des Auftrags hinzu
 *   (legt automatisch einen Bericht an wenn keiner existiert)
 * POST /api/orders.php?action=create
 *   JSON-Body: { socid, ref_client, title?, note_private?, date?, date_livraison?, validate? }
 *   - ref_client  ("Ihr Zeichen") ist PFLICHT (Geschäftsregel; Dolibarr selbst verlangt es nicht).
 *   - title       (Auftragsbeschreibung) optional -> Extrafield options_auftragsbeschreibung.
 *   - date_livraison (Unix-TS) optional -> geplanter Liefertermin (Spalte date_livraison).
 *   - validate    (bool) optional -> Auftrag direkt freigeben. Vorher wird automatisch eine
 *                 Std-Lohn-Zeile ergänzt (Kundenkarten-Default options_stundenzettel_default_service,
 *                 sonst Fallback-Produkt BERICHT_ORDER_DEFAULT_SERVICE_REF, Default 'ELEK-STD-M').
 *                 Preis = kundenspezifischer Preis (PRODUIT_CUSTOMER_PRICES) falls vorhanden,
 *                 sonst Produkt-Standardpreis.
 *   Legt einen Draft-Auftrag an und übernimmt Kunden-Defaults (Zahlungsbedingungen,
 *   Zahlart, Bankkonto, Incoterms, Lieferadresse, Default-Ansprechpartner).
 */
require_once __DIR__.'/_inc.php';

api_authenticate();
global $db, $user, $conf;

require_once DOL_DOCUMENT_ROOT.'/commande/class/commande.class.php';
require_once DOL_DOCUMENT_ROOT.'/societe/class/societe.class.php';
require_once DOL_DOCUMENT_ROOT.'/core/lib/files.lib.php';

$id = (int) ($_GET['id'] ?? 0);
$action = $_GET['action'] ?? '';

/* ----- NEUEN AUFTRAG ANLEGEN ----- */
if ($action === 'create' && $_SERVER['REQUEST_METHOD'] === 'POST') {
    if (!$user->hasRight('commande', 'creer')) api_fail('Keine Berechtigung zum Anlegen von Aufträgen', 403);

    $in = api_input();
    $socid = (int) ($in['socid'] ?? 0);
    $title = trim((string) ($in['title'] ?? ''));            // Auftragsbeschreibung (optional)
    $ref_client = trim((string) ($in['ref_client'] ?? ''));  // "Ihr Zeichen" (Pflicht)
    $note_private = trim((string) ($in['note_private'] ?? ''));
    $date = (int) ($in['date'] ?? 0);
    if ($date <= 0) $date = dol_now();
    $date_livraison = (int) ($in['date_livraison'] ?? 0);    // geplanter Liefertermin (optional)
    $do_validate = !empty($in['validate']);                  // direkt freigeben?

    if ($socid <= 0) api_fail('socid fehlt');
    // Geschäftsregel: "Ihr Zeichen" (ref_client) ist Pflicht. Dolibarr-Core verlangt nur den Kunden.
    if ($ref_client === '') api_fail('Ihr Zeichen (Kunden-Referenz) ist Pflicht');

    // Kundenstamm holen, um Defaults zu ziehen (wie Dolibarr-Web beim Auftrag-Anlegen)
    $soc = new Societe($db);
    if ($soc->fetch($socid) <= 0) api_fail('Kunde nicht gefunden', 404);

    $cmd = new Commande($db);
    $cmd->socid = $socid;
    $cmd->date_commande = $date;
    $cmd->date = $date;
    $cmd->ref_client = $ref_client;
    $cmd->note_private = $note_private;
    if ($date_livraison > 0) $cmd->delivery_date = $date_livraison; // -> Spalte date_livraison

    // Kunden-Defaults übernehmen
    if (!empty($soc->cond_reglement_id)) $cmd->cond_reglement_id = (int) $soc->cond_reglement_id;
    if (!empty($soc->mode_reglement_id)) $cmd->mode_reglement_id = (int) $soc->mode_reglement_id;
    if (!empty($soc->fk_account))        $cmd->fk_account        = (int) $soc->fk_account;
    if (!empty($soc->fk_incoterms))      $cmd->fk_incoterms      = (int) $soc->fk_incoterms;
    if (!empty($soc->location_incoterms)) $cmd->location_incoterms = $soc->location_incoterms;
    if (!empty($soc->fk_delivery_address)) $cmd->fk_delivery_address = (int) $soc->fk_delivery_address;

    // Titel des Auftrags in Extrafield "auftragsbeschreibung" ablegen (das Bericht-Modul nutzt dieses)
    if ($title !== '') {
        if (!is_array($cmd->array_options)) $cmd->array_options = array();
        $cmd->array_options['options_auftragsbeschreibung'] = $title;
    }

    $newid = $cmd->create($user);
    if ($newid <= 0) api_fail('Anlegen fehlgeschlagen: '.$cmd->error, 500);

    // Hauptansprechpartner aus llx_socpeople als externen Kontakt hinzufügen (falls vorhanden)
    $sql_c = "SELECT rowid FROM ".$db->prefix()."socpeople"
        ." WHERE fk_soc = ".((int) $socid)." AND statut = 1"
        ." ORDER BY rowid ASC LIMIT 1";
    $rc = $db->query($sql_c);
    if ($rc && ($oc = $db->fetch_object($rc))) {
        $cmd->add_contact((int) $oc->rowid, 'CUSTOMER', 'external');
    }

    /* ----- Optional: Std-Lohn-Zeile ergänzen und Auftrag direkt freigeben ----- */
    $validated = false;
    $validate_warning = '';
    $added_line = null;
    if ($do_validate) {
        require_once DOL_DOCUMENT_ROOT.'/product/class/product.class.php';

        // 1) Leistungs-Produkt bestimmen: Kundenkarten-Default, sonst Fallback über Ref
        //    (Ref statt rowid, da rowids zwischen Test-/Prod-DB verschieden sind)
        if (method_exists($soc, 'fetch_optionals')) $soc->fetch_optionals();
        $svc_id = (int) ($soc->array_options['options_stundenzettel_default_service'] ?? 0);
        if ($svc_id <= 0) {
            $fallback_ref = getDolGlobalString('BERICHT_ORDER_DEFAULT_SERVICE_REF', 'ELEK-STD-M');
            $rp = $db->query("SELECT rowid FROM ".$db->prefix()."product"
                ." WHERE ref = '".$db->escape($fallback_ref)."'"
                ." AND entity IN (".getEntity('product').") LIMIT 1");
            if ($rp && ($op = $db->fetch_object($rp))) $svc_id = (int) $op->rowid;
        }

        if ($svc_id > 0) {
            $prod = new Product($db);
            if ($prod->fetch($svc_id) > 0) {
                $pu_ht = (float) $prod->price;
                $tva   = (float) $prod->tva_tx;

                // 2) Kundenspezifischer Preis (PRODUIT_CUSTOMER_PRICES) hat Vorrang
                if (getDolGlobalString('PRODUIT_CUSTOMER_PRICES')) {
                    $rcp = $db->query("SELECT price, tva_tx FROM ".$db->prefix()."product_customer_price"
                        ." WHERE fk_product = ".((int) $svc_id)." AND fk_soc = ".((int) $socid)
                        ." ORDER BY rowid DESC LIMIT 1");
                    if ($rcp && ($cp = $db->fetch_object($rcp))) {
                        $pu_ht = (float) $cp->price;
                        if ($cp->tva_tx !== null && $cp->tva_tx !== '') $tva = (float) $cp->tva_tx;
                    }
                }

                // Menge 1 als Start; Monteur trägt die echten Stunden später ein
                $rl = $cmd->addline($prod->label, $pu_ht, 1, $tva, 0, 0, $svc_id, 0, 0, 0, 'HT', 0, '', '', (int) $prod->type);
                if ($rl > 0) {
                    $added_line = array(
                        'product' => $prod->ref,
                        'label'   => $prod->label,
                        'pu_ht'   => $pu_ht,
                        'tva_tx'  => $tva,
                    );
                }
            }
        }

        // Zeilen neu laden, dann freigeben
        $cmd->fetch($newid);
        $cmd->fetch_lines();
        $vr = $cmd->valid($user);
        if ($vr > 0) $validated = true;
        else $validate_warning = 'Freigabe fehlgeschlagen: '.$cmd->error;
    }

    // Für identische Response-Shape wie GET ?id= neu laden
    $cmd->fetch($newid);
    $cmd->fetch_thirdparty();
    if (method_exists($cmd, 'fetch_optionals')) $cmd->fetch_optionals();

    api_ok(array(
        'order' => array(
            'id'     => (int) $cmd->id,
            'ref'    => $cmd->ref,
            'ref_client' => $cmd->ref_client,
            'date'   => $cmd->date_commande,
            'date_livraison' => !empty($cmd->delivery_date) ? (int) $cmd->delivery_date : null,
            'status' => (int) $cmd->statut,
            'validated' => $validated,
            'total'  => (float) $cmd->total_ttc,
            'note_private' => $cmd->note_private,
            'auftragsbeschreibung' => $cmd->array_options['options_auftragsbeschreibung'] ?? '',
        ),
        'customer' => array(
            'id'      => (int) ($cmd->thirdparty->id ?? 0),
            'name'    => $cmd->thirdparty->name ?? '',
            'address' => $cmd->thirdparty->address ?? '',
            'zip'     => $cmd->thirdparty->zip ?? '',
            'town'    => $cmd->thirdparty->town ?? '',
            'phone'   => $cmd->thirdparty->phone ?? '',
            'email'   => $cmd->thirdparty->email ?? '',
        ),
        'added_line'       => $added_line,
        'validate_warning' => $validate_warning,
    ));
}

/* ----- LISTE ----- */
if (!$id) {
    // Filter: nur Aufträge des aktuellen Users (oder Admin sieht alle)
    $where = "c.entity IN (".getEntity('commande').")";
    if (empty($user->admin)) {
        $where .= " AND (c.fk_user_author = ".((int) $user->id)
            ." OR c.fk_user_valid = ".((int) $user->id)
            ." OR c.fk_user_modif = ".((int) $user->id).")";
    }

    // Optional: nur offene
    if (!empty($_GET['open'])) {
        $where .= " AND c.fk_statut IN (1, 2)"; // validiert + in Bearbeitung
    }
    // Suchterm
    if (!empty($_GET['q'])) {
        $q = $db->escape($_GET['q']);
        $where .= " AND (c.ref LIKE '%$q%' OR s.nom LIKE '%$q%')";
    }

    $sql = "SELECT c.rowid, c.ref, c.ref_client, c.date_commande, c.fk_statut, c.total_ttc,"
        ." s.rowid AS soc_id, s.nom AS soc_name, s.zip, s.town, s.address,"
        ." (SELECT COUNT(*) FROM ".$db->prefix()."bericht b WHERE b.element_type='order' AND b.fk_element=c.rowid) AS bericht_count"
        ." FROM ".$db->prefix()."commande c"
        ." LEFT JOIN ".$db->prefix()."societe s ON s.rowid = c.fk_soc"
        ." WHERE ".$where
        ." ORDER BY c.date_commande DESC, c.rowid DESC"
        ." LIMIT 200";

    $r = $db->query($sql);
    if (!$r) api_fail('DB-Fehler: '.$db->lasterror(), 500);
    $orders = array();
    while ($o = $db->fetch_object($r)) {
        $orders[] = array(
            'id'    => (int) $o->rowid,
            'ref'   => $o->ref,
            'ref_client' => $o->ref_client,
            'date'  => $db->jdate($o->date_commande),
            'status'=> (int) $o->fk_statut,
            'total' => (float) $o->total_ttc,
            'customer' => array(
                'id'   => (int) $o->soc_id,
                'name' => $o->soc_name,
                'zip'  => $o->zip,
                'town' => $o->town,
                'address' => $o->address,
            ),
            'bericht_count' => (int) $o->bericht_count,
        );
    }
    api_ok(array('orders' => $orders, 'count' => count($orders)));
}

/* ----- DETAIL eines Auftrags ----- */
$cmd = new Commande($db);
if ($cmd->fetch($id) <= 0) api_fail('Auftrag nicht gefunden', 404);
$cmd->fetch_thirdparty();
if (method_exists($cmd, 'fetch_optionals')) $cmd->fetch_optionals();

if ($action === 'photos') {
    // Anhänge des Auftrags — verwende glob statt dol_dir_list für korrektes filesize
    $upload_dir = $conf->commande->multidir_output[$cmd->entity].'/'.dol_sanitizeFileName($cmd->ref);
    $out = array();

    if (is_dir($upload_dir)) {
        $allFiles = glob($upload_dir.'/*', GLOB_NOSORT);
        foreach ($allFiles as $filepath) {
            if (!is_file($filepath)) continue;
            $name = basename($filepath);
            // Ignoriere Meta-Dateien, Previews und Hidden Files
            if (strpos($name, '.meta') !== false || strpos($name, '_preview') !== false || $name[0] === '.') continue;

            $out[] = array(
                'filename' => $name,
                'size'     => (int) @filesize($filepath),
                'mime'     => dol_mimetype($name),
                'date'     => (int) @filemtime($filepath),
                'relpath'  => str_replace(DOL_DATA_ROOT.'/', '', $filepath),
            );
        }
    }
    // Sortiere nach Datum (neuste zuerst)
    usort($out, function($a, $b) { return $b['date'] <=> $a['date']; });
    api_ok(array('photos' => $out, 'count' => count($out)));
}

if ($action === 'upload_photo' && $_SERVER['REQUEST_METHOD'] === 'POST') {
    if (!$user->hasRight('bericht', 'write')) api_fail('Schreibrechte fehlen', 403);
    if (empty($_FILES['file']['tmp_name'])) api_fail('file fehlt');

    // Datei validieren
    $orig = dol_sanitizeFileName($_FILES['file']['name']);
    $ext = strtolower(pathinfo($orig, PATHINFO_EXTENSION));
    if (!in_array($ext, array('jpg', 'jpeg', 'png'))) api_fail('Dateityp nicht unterstützt');

    // Foto direkt in den Dolibarr-Standard-Auftragsordner speichern (kein Bericht nötig)
    $upload_dir = $conf->commande->multidir_output[$cmd->entity].'/'.dol_sanitizeFileName($cmd->ref);
    if (!is_dir($upload_dir)) dol_mkdir($upload_dir);

    $filename = 'foto_'.dol_print_date(dol_now(), '%Y%m%d_%H%M%S').'_'.uniqid().'.'.$ext;
    $target = $upload_dir.'/'.$filename;
    if (!move_uploaded_file($_FILES['file']['tmp_name'], $target)) api_fail('Upload fehlgeschlagen', 500);

    $relpath = str_replace(DOL_DATA_ROOT.'/', '', $target);

    api_ok(array(
        'filename' => $filename,
        'relpath'  => $relpath,
        'size'     => filesize($target),
    ));
}

// Default: Auftrags-Detail
$berichte = Bericht::fetchAllForElement($db, 'order', $cmd->id);
$berichte_out = array();
foreach ($berichte as $b) {
    $berichte_out[] = array(
        'id'     => (int) $b->id,
        'ref'    => $b->ref,
        'titel'  => $b->titel,
        'status' => (int) $b->status,
        'datec'  => (int) $b->datec,
    );
}

api_ok(array(
    'order' => array(
        'id'    => (int) $cmd->id,
        'ref'   => $cmd->ref,
        'date'  => $cmd->date_commande,
        'status'=> (int) $cmd->statut,
        'total' => (float) $cmd->total_ttc,
        'note_private' => $cmd->note_private,
        'auftragsbeschreibung' => $cmd->array_options['options_auftragsbeschreibung'] ?? '',
    ),
    'customer' => array(
        'id'   => (int) ($cmd->thirdparty->id ?? 0),
        'name' => $cmd->thirdparty->name ?? '',
        'address' => $cmd->thirdparty->address ?? '',
        'zip'  => $cmd->thirdparty->zip ?? '',
        'town' => $cmd->thirdparty->town ?? '',
        'phone' => $cmd->thirdparty->phone ?? '',
        'email' => $cmd->thirdparty->email ?? '',
    ),
    'berichte' => $berichte_out,
));
