<?php

declare(strict_types=1);

namespace App\Services\NovaCards;

use App\Models\NovaCardBackground;
use App\Models\User;
use Illuminate\Http\UploadedFile;
use Illuminate\Support\Str;
use Illuminate\Support\Facades\Storage;
use Intervention\Image\Encoders\WebpEncoder;
use Intervention\Image\ImageManager;
use RuntimeException;

class NovaCardBackgroundService
{
    private ?ImageManager $manager = null;

    public function __construct()
    {
        try {
            $this->manager = extension_loaded('gd') ? ImageManager::gd() : ImageManager::imagick();
        } catch (\Throwable) {
            $this->manager = null;
        }
    }

    public function storeUploadedBackground(User $user, UploadedFile $file): NovaCardBackground
    {
        if ($this->manager === null) {
            throw new RuntimeException('Nova card background processing requires Intervention Image.');
        }

        $sourcePath = $this->resolveUploadPath($file);
        $binary = $this->readUploadedBinary($sourcePath);

        $uuid = (string) Str::uuid();
        $extension = strtolower($file->getClientOriginalExtension() ?: 'jpg');
        $originalDisk = Storage::disk((string) config('nova_cards.storage.private_disk', 'local'));
        $processedDisk = Storage::disk((string) config('nova_cards.storage.public_disk', 'public'));

        $originalPath = trim((string) config('nova_cards.storage.background_original_prefix', 'cards/backgrounds/original'), '/')
            . '/' . $user->id . '/' . $uuid . '.' . $extension;

        $processedPath = trim((string) config('nova_cards.storage.background_processed_prefix', 'cards/backgrounds/processed'), '/')
            . '/' . $user->id . '/' . $uuid . '.webp';

        $originalDisk->put($originalPath, $binary);

        $image = $this->manager->read($binary)->scaleDown(width: 2200, height: 2200);
        $encoded = (string) $image->encode(new WebpEncoder(88));
        $processedDisk->put($processedPath, $encoded);

        return NovaCardBackground::query()->create([
            'user_id' => $user->id,
            'original_path' => $originalPath,
            'processed_path' => $processedPath,
            'width' => $image->width(),
            'height' => $image->height(),
            'mime_type' => (string) ($file->getMimeType() ?: 'image/jpeg'),
            'file_size' => (int) $file->getSize(),
            'sha256' => hash('sha256', $binary),
            'visibility' => 'card-only',
        ]);
    }

    private function resolveUploadPath(UploadedFile $file): string
    {
        $path = $file->getRealPath() ?: $file->getPathname();

        if (! is_string($path) || trim($path) === '' || ! is_readable($path)) {
            throw new RuntimeException('Unable to resolve uploaded background path.');
        }

        return $path;
    }

    private function readUploadedBinary(string $path): string
    {
        $binary = @file_get_contents($path);

        if ($binary === false || $binary === '') {
            throw new RuntimeException('Unable to read uploaded background image.');
        }

        return $binary;
    }
}
