<?php

namespace Lucent\File;

use Exception;
use Illuminate\Contracts\Filesystem\Filesystem;
use Illuminate\Http\UploadedFile;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Storage;
use Illuminate\Support\Str;
use Intervention\Image\ImageManagerStatic;
use Lucent\LucentException;
use Lucent\Record\File as RecordFile;
use Lucent\Schema\Schema;
use Spatie\ImageOptimizer\OptimizerChainFactory;

/**
 * @throws LucentException
 */
function uploadFile(Schema $schema, UploadedFile $file): FileUploadResult
{
    $originalName = pathinfo($file->getClientOriginalName(), PATHINFO_FILENAME);
    $extension = pathinfo($file->getClientOriginalName(), PATHINFO_EXTENSION);
    $originalFilename = $file->getClientOriginalName();
    $filename = createFileName($originalName, $extension);
    $mimetype = $file->getMimeType();

    $optimizerChain = OptimizerChainFactory::create();
    $optimizerChain->setTimeout(10)->optimize($file->getPathName());

    $checksum = sha1_file($file);
    $recordId = checkDuplicate($schema->name, $checksum, $file->getSize());
    if (!empty($recordId)) {
        return new FileUploadResult(
            recordFile: null,
            duplicateId: $recordId,
            isDuplicate: true
        );
    }

    $disk = loadDisk();
    $path = $schema->path . "/" . $filename;
    $res = $disk->put(
        $path,
        file_get_contents($file),
//        'public' // now managed by aws policy
    );

    if ($res === false) {
        throw new LucentException("File $filename not uploaded");
    }

    createThumbnail($disk, $schema->path, $filename, $file);

    list($width, $height) = isImage($mimetype) ? getimagesize($file) : [0, 0];
    $recordFile = new RecordFile(
        originalName: $originalFilename,
        mime: $mimetype,
        path: $path,
        size: $file->getSize(),
        width: $width,
        height: $height,
        checksum: $checksum
    );

    return new FileUploadResult(
        recordFile: $recordFile,
        duplicateId: "",
        isDuplicate: false
    );
}

function createFileName(string $originalName, string $extension): string
{
    return Str::slug($originalName, '-') . '-' . uniqid() . '.' . $extension;
}

function isImage(string $mimetype): bool
{
    $imageMimes = ['image/webp', 'image/gif', 'image/jpeg', 'image/png', 'image/tiff'];
    return in_array($mimetype, $imageMimes);
}

function loadDisk(): Filesystem
{
    return Storage::build([
        'driver' => 'local',
//        'key' => config("filesystems.disks.s3.key"),
//        'secret' => config("filesystems.disks.s3.secret"),
//        'region' => config("filesystems.disks.s3.region"),
//        'bucket' => config("filesystems.disks.s3.bucket"),
//        // 'url' => $schema->objectStorageUrl,
//        'endpoint' => $schema->objectStorageEndpoint,
        'use_path_style_endpoint' => false,
        'visibility' => 'public', // now managed by aws policy
        'root' => storage_path('app/public'),
        'throw' => true,
    ]);
}

function checkDuplicate(string $schemaName, string $checksum, int $filesize): string
{

    $record = DB::table("records")
        ->where("schema", $schemaName)
        ->where("_file->checksum", $checksum)
        ->where("_file->size", $filesize)
        ->first();

    return $record->id ?? "";
}

function createThumbnail(Filesystem $disk, string $schemaPath, string $filename, UploadedFile $file): void
{


    $thumbDir = storage_path("app/public/thumbs/" . $schemaPath . "/");
    if (!file_exists($thumbDir)) {
        make_dir_r($thumbDir);
    }

    try {
        ImageManagerStatic::configure(['driver' => 'imagick']);
        $image = ImageManagerStatic::make($file);
    } catch (Exception $e) {
        logger($e->getMessage());
        return;
    }

    $image->fit(300, 300);
    try {
        $image->encode('webp', 75)->save($thumbDir .$filename);
    } catch (Exception $e) {
        logger($e->getMessage());
    }
}
