<?php

namespace Ignite\Core\Files\Processors;

use Ignite\Core\Contracts\Files\FileProcessor;
use Ignite\Core\Contracts\Repositories\ImportRepository;
use Ignite\Core\Contracts\Repositories\UserRepository;
use Ignite\Core\Entities\Import;
use Ignite\Core\Files\File;
use Ignite\Core\Models\Import\File as ImportFile;
use Illuminate\Support\Facades\Artisan;

class ToImport implements FileProcessor
{
    /**
     * The type of import we're creating this file for.
     *
     * @var string
     */
    protected $type;

    /**
     * Run the import as well?
     *
     * @var bool
     */
    protected $andQueue = false;

    /**
     * Keep the original file after processing?
     *
     * @var bool
     */
    protected $keepOriginal = false;

    /**
     * @var ImportRepository
     */
    protected $importRepository;

    /**
     * @var UserRepository
     */
    protected $userRepository;

    public function __construct(string $type, ImportRepository $importRepository, UserRepository $userRepository)
    {
        $this->type = $type;
        $this->importRepository = $importRepository;
        $this->userRepository = $userRepository;
    }

    /**
     * Instantiate this class for the given type (outside of testing, I'm not sure where else we'd want to swap the
     * import or user repos).
     *
     * @param string $type
     * @return static
     */
    public static function forType(string $type): self
    {
        return app(static::class, compact('type'));
    }

    /**
     * Queue up running the import?
     *
     * @param bool $value
     * @return static
     */
    public function andQueue(bool $value = true): self
    {
        $this->andQueue = $value;
        return $this;
    }

    /**
     * Keep the original file after processing?
     *
     * @param bool $value
     * @return static
     */
    public function keepOriginal(bool $value = true): self
    {
        $this->keepOriginal = $value;
        return $this;
    }

    /**
     * {@inheritdoc}
     * @throws \Illuminate\Contracts\Filesystem\FileExistsException
     * @throws \Illuminate\Contracts\Filesystem\FileNotFoundException
     */
    public function run(File $file): File
    {
        $file = ToImportFile::forType($this->type)
            ->keepOriginal($this->keepOriginal)
            ->run($file);
        $importFile = ImportFile::fromFile($file, $this->type);
        $import = $this->importRepository->createFromFile($importFile);

        if ($this->andQueue) {
            $this->queueImport($import);
        }

        return new File($importFile->getFile(), $importFile->getDisk());
    }

    /**
     * Queue up the import for running, if we were asked to not only create it, but also run it.
     *
     * @param Import $import
     * @return void
     */
    protected function queueImport(Import $import): void
    {
        Artisan::queue('ignite:import', [
            '--id' => $import->getKey(),
            '--user' => $this->userRepository->findAdminUser()->getKey(),
            '--no-interaction' => true,
        ])->onQueue(config('core.import.queue_connection'));
    }
}
