<?php
/**
 * Controller Class
 *
 * @version     1.0.$Revision:$
 * @version     SVN: $Id:$
 * @package     bplan-base/globals
 * @subpackage  Controllers
 * @author      Wassilios Meletiadis <wassilios.meletiadis@bplan-solutions.de>
 * @copyright   Copyright (C) 2025, 2026 bplan-solutions GmbH & Co. KG <https://www.bplan-solutions.de/>
 * /Δ\
 */

namespace BplanBase\Globals\Http\Controllers;


use BplanBase\Globals\Enums\PrintJobStatus;
use BplanBase\Globals\Enums\PrinterServiceStatus;
use BplanBase\Globals\Events\PrintJobCompleted;
use BplanBase\Globals\Events\PrintJobFailed;
use BplanBase\Globals\Foundation\Http\Controllers\BaseController;
use BplanBase\Globals\Http\Requests\PrintCallbackRequest;
use BplanBase\Globals\Models\PrintJob;
use BplanBase\Globals\Models\Tenant;
use Illuminate\Http\Response;


/**
 * Controller Class
 *
 * Verarbeitet den Callback-Request des PrintService nach einem Druckauftrag.
 * Feuert PrintJobCompleted oder PrintJobFailed, damit Konsumenten-Pakete
 * über eigene Listener reagieren können.
 *
 * @version     1.1.0 / 2026-05-12
 * @author      Wassilios Meletiadis <wassilios.meletiadis@bplan-solutions.de>
 */
class PrintCallbackController extends BaseController
{


/* +++ TRAITS +++ +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ */


/* +++ CLASS CONSTANTS +++ ++++++++++++++++++++++++++++++++++++++++++++++++++ */


/* +++ OBJECT MEMBERS +++ +++++++++++++++++++++++++++++++++++++++++++++++++++ */


/* +++ CLASS MEMBERS +++ ++++++++++++++++++++++++++++++++++++++++++++++++++++ */


/* +++ OBJECT METHODS +++ +++++++++++++++++++++++++++++++++++++++++++++++++++ */


    /**
     * Verarbeitet den Callback nach einem Druckauftrag.
     *
     * @param       PrintCallbackRequest $request
     *
     * @return      Response
     *
     * @version     1.1.0 / 2026-05-12
     * @author      Wassilios Meletiadis <wassilios.meletiadis@bplan-solutions.de>
     */
    public function callback(PrintCallbackRequest $request): Response
    {
        $jobId        = $request->validated('clientJobId');
        $status       = $request->validated('status');
        $errorMessage = $request->validated('lastError');

        \AppLog::debug(
            message: "PrintService Callback für PrintJob ID {$jobId}",
            prefix:  'PrintCallbackController',
        );

        $PrintJob = PrintJob::withoutGlobalScopes()->findOrFail((int) $jobId);

        $this->_initTenant($PrintJob);

        try {
            match (PrinterServiceStatus::tryFrom($status)) {
                PrinterServiceStatus::Completed => $this->_handleCompleted($PrintJob),
                PrinterServiceStatus::Failed    => $this->_handleFailed($PrintJob, $errorMessage),
                PrinterServiceStatus::Printing  => $this->_handlePrinting($PrintJob),
                default                         => $this->_handleUnknown($PrintJob, $status),
            };

        } catch (\Throwable $E) {
            \AppLog::error(
                message: $E,
                prefix:  'PrintCallbackController',
                context: ['printJobId' => $PrintJob->id],
            );

            $PrintJob->update(['status' => PrintJobStatus::Failed]);

            PrintJobFailed::dispatch($PrintJob);

        }

        return response()->noContent();

    } // callback()


    /**
     * Verarbeitet einen erfolgreich abgeschlossenen Druckauftrag.
     *
     * @param       PrintJob $PrintJob
     *
     * @return      void
     *
     * @version     1.0.0 / 2026-04-27
     * @author      Wassilios Meletiadis <wassilios.meletiadis@bplan-solutions.de>
     */
    private function _handleCompleted(PrintJob $PrintJob): void
    {
        \AppLog::info(
            message: "PrintService Callback – Druck erfolgreich für PrintJob ID {$PrintJob->id}",
            prefix:  'PrintCallbackController',
        );

        $PrintJob->update([
            'finished_at' => now(),
            'status'      => PrintJobStatus::Done,
        ]);

        PrintJobCompleted::dispatch($PrintJob);

    } // _handleCompleted()


    /**
     * Verarbeitet einen fehlgeschlagenen Druckauftrag.
     *
     * @param       PrintJob $PrintJob
     *
     * @param       string|null $errorMessage
     *
     * @return      void
     *
     * @version     1.0.0 / 2026-04-27
     * @author      Wassilios Meletiadis <wassilios.meletiadis@bplan-solutions.de>
     */
    private function _handleFailed(PrintJob $PrintJob, ?string $errorMessage): void
    {
        \AppLog::error(
            message: "PrintService Callback – Fehler für PrintJob ID {$PrintJob->id}: {$errorMessage}",
            prefix:  'PrintCallbackController',
        );

        $PrintJob->update([
            'error_message' => $errorMessage,
            'finished_at'   => now(),
            'status'        => PrintJobStatus::Error,
        ]);

        PrintJobFailed::dispatch($PrintJob);

    } // _handleFailed()


    /**
     * Verarbeitet einen Zwischenstatus während des Druckvorgangs.
     *
     * @param       PrintJob $PrintJob
     *
     * @return      void
     *
     * @version     1.0.0 / 2026-04-27
     * @author      Wassilios Meletiadis <wassilios.meletiadis@bplan-solutions.de>
     */
    private function _handlePrinting(PrintJob $PrintJob): void
    {
        \AppLog::debug(
            message: "PrintService Callback – Druckvorgang läuft für PrintJob ID {$PrintJob->id}",
            prefix:  'PrintCallbackController',
        );

    } // _handlePrinting()


    /**
     * Verarbeitet einen unbekannten Callback-Status.
     *
     * @param       PrintJob $PrintJob
     *
     * @param       string $status
     *
     * @return      void
     *
     * @version     1.1.0 / 2026-05-12
     * @author      Wassilios Meletiadis <wassilios.meletiadis@bplan-solutions.de>
     */
    private function _handleUnknown(PrintJob $PrintJob, string $status): void
    {
        \AppLog::warning(
            message: "PrintService Callback – Unbekannter Status '{$status}' für PrintJob ID {$PrintJob->id}",
            prefix:  'PrintCallbackController',
        );

        $PrintJob->update([
            'finished_at' => now(),
            'status'      => PrintJobStatus::Failed,
        ]);

        PrintJobFailed::dispatch($PrintJob);

    } // _handleUnknown()


    /**
     * Setzt den Tenant-Kontext anhand des PrintJobs, sofern ein Tenant hinterlegt ist.
     *
     * @param       PrintJob $PrintJob
     *
     * @return      void
     *
     * @version     1.0.0 / 2026-04-27
     * @author      Wassilios Meletiadis <wassilios.meletiadis@bplan-solutions.de>
     */
    private function _initTenant(PrintJob $PrintJob): void
    {
        if ($PrintJob->tenant_id === null) {
            return;
        }

        $Tenant = Tenant::find($PrintJob->tenant_id);

        if ($Tenant !== null) {
            $Tenant->makeCurrent();
        }

    } // _initTenant()


/* +++ CLASS METHODS +++ ++++++++++++++++++++++++++++++++++++++++++++++++++++ */


} // class PrintCallbackController extends BaseController {}
