<?php

namespace Inside\BCLH\Jobs;

use Illuminate\Bus\Queueable;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Queue\InteractsWithQueue;
use Illuminate\Queue\SerializesModels;
use Illuminate\Support\Facades\Queue;
use Illuminate\Support\Facades\Storage;
use Inside\BCLH\Events\BulkCSVImportedEvent;
use Inside\BCLH\Events\BulkCSVImportFailedEvent;
use League\Csv\Reader;

class ImportBulkCSV implements ShouldQueue
{
    use InteractsWithQueue;
    use Queueable;
    use SerializesModels;

    public const CSV_UPLOAD_FOLDER = 'csv/upload';

    /**
     * @var string
     */
    private $userUuid;

    /**
     * @var string
     */
    private $filePath;

    public function __construct(string $userUuid, string $filePath)
    {
        $this->userUuid = $userUuid;
        $this->filePath = $filePath;
    }

    public function handle(): void
    {
        $csv = Reader::createFromPath(Storage::disk('local')->path($this->filePath))
            ->setDelimiter(';')
            ->setHeaderOffset(0);
        $header = $csv->getHeader();

        if (array_diff($header, GenerateBulkCSV::CSV_HEADER) !== []) {
            event(new BulkCSVImportFailedEvent($this->userUuid));

            return;
        }

        $jobs = [];
        $now = time();

        foreach ($csv as $line) {
            if (empty($line['uuid'])) {
                continue;
            }

            $content_type = $line['content_type'];
            $content = call_user_func(type_to_class($content_type).'::find', $line['uuid']);

            if ($content === null) {
                continue;
            }

            $data = [
                'type' => 'node',
                'bundle' => $line['content_type'],
                'uuid' => $line['uuid'],
                'last_update' => $now,
            ];

            $referenceFields = ['brands', 'countries', 'management_modes', 'profiles'];
            foreach ($referenceFields as $referenceField) {
                $data[$referenceField] = $this->getUuidsByCode($referenceField, $line[$referenceField], $content->langcode);
            }

            $jobs[] = new BulkUpdate($line['content_type'], $data);
        }
        $jobs[] = new DispatchEvent(BulkCSVImportedEvent::class, $this->userUuid, count($jobs));
        $this->chain($jobs);
    }

    public function getUuidsByCode(string $content_type, ?string $codesString, string $langcode): array
    {
        if ($codesString === '' || $codesString === null) {
            return [];
        }

        if ($codesString === 'all') {
            return call_user_func(type_to_class($content_type).'::query')
                ->where('langcode', '=', $langcode)
                ->pluck('uuid')
                ->toArray();
        }

        $codes = explode(',', $codesString);

        return call_user_func(type_to_class($content_type).'::query')
            ->where('langcode', '=', $langcode)
            ->whereIn('code', $codes)
            ->pluck('uuid')
            ->toArray();
    }
}
