<?php

namespace App\Domains\Shared\Rules;

use Closure;
use Illuminate\Contracts\Validation\ValidationRule;
use Illuminate\Http\UploadedFile;

class ImageOrBase64Rule implements ValidationRule
{
    public function validate(string $attribute, mixed $value, Closure $fail): void
    {
        if ($value instanceof UploadedFile) {
            $mime = $value->getMimeType();
            if (! str_starts_with((string) $mime, 'image/')) {
                $fail("The :attribute must be a valid image file.");
            }
            return;
        }

        if (is_string($value)) {
            $payload = trim($value);

            if (\Illuminate\Support\Str::isUuid($payload)) {
                return;
            }

            if ($payload === '') {
                $fail("The :attribute must not be empty.");
                return;
            }

            $declaredMimeType = null;
            if (preg_match('/^data:(?<mime>[-\w.+\/]+);base64,(?<data>.+)$/s', $payload, $matches) === 1) {
                $declaredMimeType = strtolower($matches['mime']);
                $payload = $matches['data'];
            }

            $decoded = base64_decode(preg_replace('/\s+/', '', $payload), true);
            if ($decoded === false || $decoded === '') {
                $fail("The :attribute must be a valid base64-encoded image.");
                return;
            }

            $finfo = new \finfo(FILEINFO_MIME_TYPE);
            $detectedMime = $finfo->buffer($decoded);
            $mime = $detectedMime ?: $declaredMimeType;

            if (! $mime || ! str_starts_with((string) $mime, 'image/')) {
                $fail("The :attribute must be a valid image (file or base64).");
            }

            return;
        }

        $fail("The :attribute must be an image file or a base64-encoded image string.");
    }
}
