<?php

namespace App\Jobs;

use Illuminate\Contracts\Queue\ShouldBeUnique;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Foundation\Queue\Queueable;
use Illuminate\Queue\Middleware\WithoutOverlapping;
use Illuminate\Queue\SerializesModels;
use Illuminate\Queue\InteractsWithQueue;
use Illuminate\Support\Facades\Log;

use App\Models\Abstracted\Catalog;

class CatalogScan implements ShouldQueue, ShouldBeUnique
{
	use InteractsWithQueue,Queueable,SerializesModels;

	// Our object
	private Catalog $o;
	private bool $show_dirty;

	/**
	 * Create a new job instance.
	 *
	 * @return void
	 */
	public function __construct(Catalog $o,bool $show_dirty=FALSE) {
		$this->o = $o->withoutRelations();
		$this->show_dirty = $show_dirty;
	}

	public function middleware(): array
	{
		return [new WithoutOverlapping($this->o->id)];
	}

	/**
	 * Get the unique ID for the job.
	 */
	public function uniqueId(): string
	{
		return $this->o->id;
	}

	/**
	 * Execute the job.
	 *
	 * @return void
	 * @throws \Exception
	 */
	public function handle()
	{
		Log::info(sprintf('%s: Scanning [%s|%s]',__METHOD__,$this->o->objecttype(),$this->o->id));

		if (! $this->o->isReadable()) {
			Log::alert(sprintf('Ignoring [%s], it is not readable',$this->o->file_name(FALSE)));

			return;
		}

		$this->o->init();

		// If this is a duplicate
		$x = $this->o->myduplicates()->get();
		if (count($x)) {
			foreach ($x as $this->oo) {
				// And that catalog item is not marked as a duplicate
				if (! $this->oo->duplicate) {
					$this->o->duplicate = TRUE;
					Log::alert(sprintf('Image [%s] marked as a duplicate',$this->o->filename));

					// If the file signature also matches, we'll mark it for deletion
					if ($this->oo->file_signature && ($this->o->file_signature == $this->oo->file_signature)) {
						Log::alert(sprintf('Image [%s] marked for deletion',$this->o->filename));
						$this->o->remove = TRUE;
					}

					break;
				}
			}
		}

		$this->o->scanned = TRUE;

		if ($this->o->getDirty()) {
			Log::alert(sprintf('Image [%s] metadata changed',$this->o->filename));

			if ($this->show_dirty)
				dump(['id'=>$this->o->id,'data'=>$this->o->getDirty()]);
		}

		// If the file signature changed, abort the update.
		if ($this->o->getOriginal('file_signature') && $this->o->wasChanged('file_signature'))
			throw new \Exception(sprintf('File Signature Changed for [%s] DB: [%s], File: [%s]?',
				$this->o->file_name(),
				$this->o->file_signature,
				$this->o->getOriginal('file_signature'),
			));

		$this->o->save();
	}
}