<?php

declare(strict_types=1);

namespace App\Http\Requests\NovaCards;

use Closure;
use Illuminate\Foundation\Http\FormRequest;
use Illuminate\Http\UploadedFile;

class UploadNovaCardBackgroundRequest extends FormRequest
{
    public function authorize(): bool
    {
        return $this->user() !== null;
    }

    public function rules(): array
    {
        $bytes = (int) config('nova_cards.validation.max_background_upload_bytes', 8 * 1024 * 1024);
        $maxKilobytes = (int) ceil($bytes / 1024);

        return [
            'background' => [
                'bail',
                'required',
                'file',
                function (string $attribute, mixed $value, Closure $fail): void {
                    $this->validateUpload($attribute, $value, $fail);
                },
                'image',
                'mimes:jpeg,jpg,png,webp',
                'max:' . $maxKilobytes,
                function (string $attribute, mixed $value, Closure $fail): void {
                    $this->validateMinimumDimensions($attribute, $value, $fail, 480, 480);
                },
            ],
        ];
    }

    private function validateUpload(string $attribute, mixed $value, Closure $fail): void
    {
        if (! $value instanceof UploadedFile) {
            return;
        }

        $path = $value->getRealPath() ?: $value->getPathname();

        if (! $value->isValid() || ! is_string($path) || trim($path) === '' || ! is_readable($path)) {
            $fail('The ' . $attribute . ' upload is invalid.');
        }
    }

    private function validateMinimumDimensions(string $attribute, mixed $value, Closure $fail, int $minWidth, int $minHeight): void
    {
        if (! $value instanceof UploadedFile) {
            return;
        }

        $path = $value->getRealPath() ?: $value->getPathname();

        if (! is_string($path) || trim($path) === '' || ! is_readable($path)) {
            $fail('The ' . $attribute . ' upload is invalid.');

            return;
        }

        $binary = @file_get_contents($path);
        if ($binary === false || $binary === '') {
            $fail('The ' . $attribute . ' upload is invalid.');

            return;
        }

        $dimensions = @getimagesizefromstring($binary);
        if (! is_array($dimensions) || ($dimensions[0] ?? 0) < $minWidth || ($dimensions[1] ?? 0) < $minHeight) {
            $fail(sprintf('The %s must be at least %dx%d pixels.', $attribute, $minWidth, $minHeight));
        }
    }
}