<?php
error_reporting(E_ALL);
require('../config.php');
require('../EpiApi.php');

use chillerlan\QRCode\{
    QRCode,
    QROptions
};

require('../vendor/autoload.php');

$options = new QROptions([
    'imageBase64' => false,
    'qrCodeHeight' => 75,
    'qrCodeWidth' => 75,
    'version' => -1,
    'quietzoneSize' => 1
]);

$Epi = new Epirent();

$result = $Epi->requestEpiApi('/v1/packingnote/open?isco=False&cl=' . Epirent_Mandant);
$data_output = json_decode($result)->payload;

/** ---------- Helpers & Marking (analog Checkout) ---------- */
const APP_TZ = 'Europe/Berlin';

function dt(?string $s): ?DateTimeImmutable {
    if (!$s) return null;
    try {
        return new DateTimeImmutable($s, new DateTimeZone(APP_TZ));
    } catch (Throwable $e) {
        return null;
    }
}

function dayStart(DateTimeImmutable $d): DateTimeImmutable {
    return $d->setTime(0, 0, 0);
}

function rowClassForDate(?DateTimeImmutable $markDate, ?DateTimeImmutable $today): string {
    if (!$markDate || !$today) return '';
    if ($markDate == $today)   return 'text-dark bg-warning';
    if ($markDate <  $today)   return 'bg-danger';
    return '';
}

/**
 * Row-Marking Quelle (Check-In):
 * 1 = $packingjob->date_end
 * 2 = $NachbereitungsTimeDetail->date_start
 * 3 = $RePackagingTimeDetail->date_start
 * 4 = $PackingNoteDetail->date_redelivery
 * Fallback: $packingjob->date_end
 */
function resolveRowMarkDateCheckIn(
    $packingjob,
    $NachbereitungsTimeDetail,
    $RePackagingTimeDetail,
    $PackingNoteDetail,
    $DispoTimeDetail,
    int $source
): ?DateTimeImmutable {
    $candidate = null;
    switch ($source) {
        case 1: $candidate = dt($packingjob->date_end ?? null); break;
        case 2: $candidate = dt($NachbereitungsTimeDetail->date_start ?? null); break;
        case 3: $candidate = dt($RePackagingTimeDetail->date_start ?? null); break;
        case 4: $candidate = dt($PackingNoteDetail->date_redelivery ?? null); break;
        case 5: $candidate = dt($DispoTimeDetail->date_end ?? null); break;

        default: $candidate = null; break;
    }
    if (!$candidate) {
        $candidate = dt($packingjob->date_end ?? null);
    }
    return $candidate ? dayStart($candidate) : null;
}

function echoMarkedTimeLine(?string $dateStr, ?int $timeSeconds, DateTimeImmutable $today, $ReturnTime): void {
    if (!$dateStr) return;
    $d = dt($dateStr);
    if (!$d) return;

    $mark = dayStart($d);
    $cls  = rowClassForDate($mark, $today);

    echo $cls ? "<span class=\"{$cls}\">" : "";
    echo date_format(new \DateTime($dateStr), 'd.m.Y');
    if ($ReturnTime) {
        echo " " . getTimeFromSeconds((string)$timeSeconds);
    }
    echo $cls ? "</span>" : "";
}

/** ---------- Sortierung nach Ende ---------- */
if (SortCheckIn == 2) {
    if (is_array($data_output)) {
        usort($data_output, function ($a, $b) {
            $timeEndA = $a->time_end / 1000;
            $timeEndB = $b->time_end / 1000;
            $datetimeA = strtotime($a->date_end) + $timeEndA;
            $datetimeB = strtotime($b->date_end) + $timeEndB;
            return $datetimeA <=> $datetimeB;
        });
    } else {
        echo "Daten konnten nicht verarbeitet werden.";
    }
}

/** ---------- Tabelle ---------- */
foreach ($data_output as $packingjob) {
    if ($packingjob->is_archived != true) {

        // OrderDetails
        $result = $Epi->requestEpiApi('/v1/order/' . $packingjob->order_pk . '?cl=' . Epirent_Mandant);
        $orderdetail_output = json_decode($result)->payload[0];

        // PackingNote Details
        $PackingNoteDetailResult = $Epi->requestEpiApi('/v1/packingnote/' . $packingjob->primary_key . '?cl=' . Epirent_Mandant);
        $PackingNoteDetail = json_decode($PackingNoteDetailResult)->payload[0];

        // Zeit-Slots aus dem Schedule
        $NachbereitungsTimeDetail = null;
        $RePackagingTimeDetail    = null;
        $DispoTimeDetail = null;
        foreach ($orderdetail_output->order_schedule as $scheduledetail) {
            if ($scheduledetail->name == Nachbereitung_Zeitvariable) {
                $NachbereitungsTimeDetail = $scheduledetail;
            }
            if ($scheduledetail->name == Rückpacken_Zeitvariable) {
                $RePackagingTimeDetail = $scheduledetail;
            }
            if ($scheduledetail->name == "Dispo") {
                $DispoTimeDetail = $scheduledetail;
            }
        }

        // --- Row-Marking bestimmen (konfigurierbar, analog Checkout) ---
        $today = dayStart(new DateTimeImmutable('today', new DateTimeZone(APP_TZ)));
        $limit = null;
        if (CheckIn_FutureDays != -1) {
            $limit = $today->modify('+' . (int)CheckIn_FutureDays . ' day');
        }

        // Override-Flag wie bei Checkout: Dispo-Ende erzwingen
        $source = CheckIn_UseDispoEndForRowMarking ? 1 : (int)CheckInRowMarkSource;

        $markDate = resolveRowMarkDateCheckIn(
            $packingjob,
            $NachbereitungsTimeDetail,
            $RePackagingTimeDetail,
            $PackingNoteDetail,
            $DispoTimeDetail,
            $source
        );

        if (CheckIn_FutureDays == -1 || ($markDate && (!$limit || $markDate <= $limit))) {
            $trClass = rowClassForDate($markDate, $today);
            echo $trClass ? "<tr class='{$trClass}'>" : "<tr>";

            // QR / Kopfspalten
            if (Enable_QR_Code_CheckIn) {
                echo "<td><div style=\"width: 5vb;\">" . (new QRCode($options))->render($packingjob->packingnote_no) . "</div></td>";
            } else {
                echo "<td>" . $packingjob->packingnote_no . "</td>";
            }
            echo "<td>" . $packingjob->contact->name . "</td>";
            echo "<td>" . $packingjob->event . "</td>";

            // Zeitspalte öffnen, wenn mindestens eine Anzeige aktiv ist
            if (ShowCheckInTimeOnCheckin || ShowNachbereitungTimeOnCheckin || ShowRePackagingTimeOnCheckin || ShowReDeliveryTimeOnCheckin || ShowDispoEndOnCheckin) {
                echo "<td>";
            }

            // Dispo-Ende (Check-In Termin) — ENDE korrekt verwendet
            if (ShowCheckInTimeOnCheckin && $packingjob->date_end != null) {
                echoMarkedTimeLine($packingjob->date_end, (int)$packingjob->time_end, $today, ShowTimesOnCheckin);
            }

            // Nachbereitung (START) — wie von dir bereits genutzt
            if (ShowNachbereitungTimeOnCheckin && $NachbereitungsTimeDetail && $NachbereitungsTimeDetail->date_start != null) {
                if (ShowCheckInTimeOnCheckin) echo "<br>";
                echoMarkedTimeLine($NachbereitungsTimeDetail->date_start, (int)$NachbereitungsTimeDetail->time_start, $today, ShowTimesOnCheckin);
            }

            // Rückpacken (START)
            if (ShowRePackagingTimeOnCheckin && $RePackagingTimeDetail && $RePackagingTimeDetail->date_start != null) {
                if (ShowCheckInTimeOnCheckin || ShowNachbereitungTimeOnCheckin) echo "<br>";
                echoMarkedTimeLine($RePackagingTimeDetail->date_start, (int)$RePackagingTimeDetail->time_start, $today, ShowTimesOnCheckin);
            }

            // Rücklieferung (REDELIVERY) — delivery ↔ redelivery gespiegelt
            if (ShowReDeliveryTimeOnCheckin && $PackingNoteDetail && $PackingNoteDetail->date_redelivery != null) {
                if (ShowCheckInTimeOnCheckin || ShowNachbereitungTimeOnCheckin || ShowRePackagingTimeOnCheckin) echo "<br>";
                echoMarkedTimeLine($PackingNoteDetail->date_redelivery, (int)$PackingNoteDetail->time_redelivery, $today, ShowTimesOnCheckin);
            }

              // Dispo Ende
            if (ShowDispoEndOnCheckin && $DispoTimeDetail && $DispoTimeDetail->date_end != null) {
                if (ShowCheckInTimeOnCheckin || ShowNachbereitungTimeOnCheckin || ShowRePackagingTimeOnCheckin || ShowReDeliveryTimeOnCheckin) echo "<br>";
                echoMarkedTimeLine($DispoTimeDetail->date_end, (int)$DispoTimeDetail->time_end, $today, ShowTimesOnCheckin);
            }

            if (ShowCheckInTimeOnCheckin || ShowNachbereitungTimeOnCheckin || ShowRePackagingTimeOnCheckin || ShowReDeliveryTimeOnCheckin || ShowDispoEndOnCheckin) {
                echo "</td>";
            }

            // Fortschritt
            echo "<td>";
            if ($packingjob->is_all_in == 0) {
                echo "<span class='badge badge-success'>";
            } else {
                echo '<div class="progress"><div class="progress-bar progress-bar-striped progress-bar-animated" role="progressbar" style="width: ' .
                    (( $packingjob->pieces_sum_total - abs($packingjob->is_all_out) - abs($packingjob->is_all_in)) / ($packingjob->pieces_sum_total - $packingjob->is_all_out)) * 100 .
                    '%" aria-valuenow="' . ( $packingjob->pieces_sum_total - abs($packingjob->is_all_out) - abs($packingjob->is_all_in)) .
                    '" aria-valuemin="0" aria-valuemax="' . ($packingjob->pieces_sum_total - $packingjob->is_all_out) . '"></div></div>';
                echo "<span class='badge badge-info'>";
            }
            echo ( $packingjob->pieces_sum_total - abs($packingjob->is_all_out) - abs($packingjob->is_all_in)) . "/" . ($packingjob->pieces_sum_total - $packingjob->is_all_out) . " (" . $packingjob->pieces_sum_total . ")";
            echo "</span></td>";

            // Shipping-Icons (inbound)
            if (ShowShippingIcons) {
                if (UseShippingStatus) {
                    if (($PackingNoteDetail->status == ShippingInOrganizedStatus) || ($PackingNoteDetail->status == ShippingOrganizedStatus)) {
                        echo "<td style='color:#66FF00; text-align:center;'>";
                    } else {
                        echo "<td style='text-align:center;'>";
                    }

                    if ($PackingNoteDetail->is_self_redeliver) {
                        echo '<i class="'.SelbstabholerIcon.'"></i>';
                    } else {
                        if (preg_match('/' . KurierContainsText . '/i', $PackingNoteDetail->shipping_in)) {
                            echo '<i class="'.KurierIcon.'"></i>';
                        }
                        if (preg_match('/' . SpeditionContainsText . '/i', $PackingNoteDetail->shipping_in)) {
                            echo '<i class="'.SpeditionIcon.'"></i>';
                        }
                        if (preg_match('/' . DHLContainsText . '/i', $PackingNoteDetail->shipping_in)) {
                            echo '<i class="'.DHLIcon.'"></i>';
                        }
                        if (preg_match('/' . LKWContainsText . '/i', $PackingNoteDetail->shipping_in)) {
                            echo '<i class="fa-solid fa-industry fa-lg"></i><i class="'.LKWIcon.'"></i>';
                        }
                        if (preg_match('/' . TransporterContainsText . '/i', $PackingNoteDetail->shipping_in)) {
                            echo '<i class="fa-solid fa-industry fa-lg"></i><i class="'.TransporterIcon.'"></i>';
                        }
                        if (preg_match('/' . PKWContainsText . '/i', $PackingNoteDetail->shipping_in)) {
                            echo '<i class="fa-solid fa-industry fa-lg"></i><i class="'.PKWIcon.'"></i>';
                        }
                    }
                    echo "</td>";
                }

                echo "</tr>";
            }

            echo "</tr>";
        }
    }
}

function getTimeFromSeconds($seconds): string {
    if ($seconds === null || $seconds === '') {
        return '';
    }

    // robust normalisieren: String/Float -> Float -> gerundet -> Int
    $seconds = (int) round((float) $seconds);

    if ($seconds < 0) {
        $seconds = 0; // oder: return ''; je nach gewünschtem Verhalten
    }

    // reine Integer-Arithmetik, keine impliziten float->int Casts
    $hours = intdiv($seconds, 3600);
    $mins  = intdiv($seconds % 3600, 60);

    return sprintf('%02d:%02d', $hours, $mins);
}
