<?php

namespace App\Jobs;

use App\Models\PrintJob;
use Illuminate\Bus\Queueable;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Foundation\Bus\Dispatchable;
use Illuminate\Queue\InteractsWithQueue;
use Illuminate\Queue\SerializesModels;
use App\Services\Stampa\CreaScontrino;
use App\Services\Stampa\CreaComandaCucina;
use Throwable;
use Illuminate\Support\Facades\Log;

class ElaboraJobStampa implements ShouldQueue
{
    use Dispatchable;
    use InteractsWithQueue;
    use Queueable;
    use SerializesModels;

    public int $tries = 3;

    public function __construct(public int $printJobId) {
        $this->onConnection('redis');
        $this->onQueue('default');
    }

    public function handle(): void
    {
        $job = PrintJob::query()->find($this->printJobId);

        if ($job === null) {
            return;
        }

        if (in_array($job->stato, [PrintJob::STATO_COMPLETATO, PrintJob::STATO_ANNULLATO], true)) {
            return;
        }

        $job->loadMissing('ordine');

        $payload = is_array($job->payload) ? $job->payload : [];

        if ($job->tipo === PrintJob::TIPO_SCONTRINO) {
            if ($job->ordine === null) {
                Log::error('Print job senza ordine associato.');
                throw new \RuntimeException('Print job senza ordine associato.');
            }
            $payload = array_merge($payload, app(CreaScontrino::class)->perOrdine($job->ordine));

        }elseif(str_starts_with($job->tipo, PrintJob::TIPO_COMANDA_CUCINA.'_')){
                if ($job->ordine === null) {
                    Log::error('Print job senza ordine associato.');
                    throw new \RuntimeException('Print job senza ordine associato.');
                }
                
                $prefix = PrintJob::TIPO_COMANDA_CUCINA . '_';
                $cucina_id = str_starts_with($job->tipo, $prefix) ? substr($job->tipo, strlen($prefix)) : null;

                if ($cucina_id === null || $cucina_id === '' || ! is_numeric($cucina_id)) {
                    Log::error('Print job senza cucina associata.');
                    throw new \RuntimeException('Print job senza cucina associata.');
                }
                $payload = array_merge($payload, app(CreaComandaCucina::class)->perOrdine($job->ordine, $cucina_id));
        }else{
            Log::error('Tipo di stampa non supportato: '.$job->tipo);
            throw new \RuntimeException('Tipo di stampa non supportato: '.$job->tipo);
        }

        $job->update([
            'stato' => PrintJob::STATO_IN_CODA,
            'queued_at' => now(),
            'payload' => $payload,
            'last_error' => null,
        ]);
    }

    public function failed(?Throwable $exception): void
    {
        PrintJob::query()->whereKey($this->printJobId)->update([
            'stato' => PrintJob::STATO_FALLITO,
            'failed_at' => now(),
            'last_error' => $exception?->getMessage(),
        ]);
    }
}
