<?php

namespace App\Console\Commands;

use App\Jobs\ImageOptimizePipeline\ImageOptimize;
use App\Jobs\MediaPipeline\MediaFixLocalFilesystemCleanupPipeline;
use App\Media;
use Illuminate\Console\Command;
use Illuminate\Support\Facades\Storage;
use League\Flysystem\MountManager;

class FixMediaDriver extends Command
{
    /**
     * The name and signature of the console command.
     *
     * @var string
     */
    protected $signature = 'media:fix-nonlocal-driver';

    /**
     * The console command description.
     *
     * @var string
     */
    protected $description = 'Fix filesystem when FILESYSTEM_DRIVER not set to local';

    /**
     * Execute the console command.
     *
     * @return int
     */
    public function handle()
    {
        if (config('filesystems.default') !== 'local') {
            $this->error('Invalid default filesystem, set FILESYSTEM_DRIVER=local to proceed');

            return Command::SUCCESS;
        }

        if ((bool) config_cache('pixelfed.cloud_storage') == false) {
            $this->error('Cloud storage not enabled, exiting...');

            return Command::SUCCESS;
        }

        $this->info('       ____  _           ______         __  ');
        $this->info('      / __ \(_)  _____  / / __/__  ____/ /  ');
        $this->info('     / /_/ / / |/_/ _ \/ / /_/ _ \/ __  /   ');
        $this->info('    / ____/ />  </  __/ / __/  __/ /_/ /    ');
        $this->info('   /_/   /_/_/|_|\___/_/_/  \___/\__,_/     ');
        $this->info(' ');
        $this->info('   Media Filesystem Fix');
        $this->info('   =====================');
        $this->info('   Fix media that was created when FILESYSTEM_DRIVER=local');
        $this->info('   was not properly set. This command will fix media urls');
        $this->info('   and optionally optimize/generate thumbnails when applicable,');
        $this->info('   clean up temporary local media files and clear the app cache');
        $this->info('   to fix media paths/urls.');
        $this->info(' ');
        $this->error('   Remember, FILESYSTEM_DRIVER=local must remain set or you will break things!');

        if (! $this->confirm('Are you sure you want to perform this command?')) {
            $this->info('Exiting...');

            return Command::SUCCESS;
        }

        $optimize = $this->choice(
            'Do you want to optimize media and generate thumbnails? This will store s3 locally and re-upload optimized versions.',
            ['no', 'yes'],
            1
        );

        $cloud = Storage::disk(config('filesystems.cloud'));
        $mountManager = new MountManager([
            's3' => $cloud->getDriver(),
            'local' => Storage::disk('local')->getDriver(),
        ]);

        $this->info('Fixing media, this may take a while...');
        $this->line(' ');
        $bar = $this->output->createProgressBar(Media::whereNotNull('status_id')->whereNull('cdn_url')->count());
        $bar->start();

        foreach (Media::whereNotNull('status_id')->whereNull('cdn_url')->lazyById(20) as $media) {
            if ($cloud->exists($media->media_path)) {
                if ($optimize === 'yes') {
                    $mountManager->copy(
                        's3://'.$media->media_path,
                        'local://'.$media->media_path
                    );
                    sleep(1);
                    if (empty($media->original_sha256)) {
                        $hash = \hash_file('sha256', Storage::disk('local')->path($media->media_path));
                        $media->original_sha256 = $hash;
                        $media->save();
                        sleep(1);
                    }
                    if (
                        $media->mime &&
                        in_array($media->mime, [
                            'image/jpg',
                            'image/jpeg',
                            'image/png',
                            'image/webp',
                        ])
                    ) {
                        ImageOptimize::dispatch($media);
                        sleep(3);
                    }
                } else {
                    $media->cdn_url = $cloud->url($media->media_path);
                    $media->save();
                }
            }
            $bar->advance();
        }

        $bar->finish();
        $this->line(' ');
        $this->line(' ');

        $this->callSilently('cache:clear');

        $this->info('Successfully fixed media paths and cleared cached!');

        if ($optimize === 'yes') {
            MediaFixLocalFilesystemCleanupPipeline::dispatch()->delay(now()->addMinutes(15))->onQueue('default');
            $this->line(' ');
            $this->info('A cleanup job has been dispatched to delete media stored locally, it may take a few minutes to process!');
        }

        $this->line(' ');

        return Command::SUCCESS;
    }
}
