<?php

declare(strict_types=1);

namespace App\Services;

use App\Models\Artwork;
use App\Services\Uploads\UploadStorageService;
use Illuminate\Support\Facades\Storage;

final class ArtworkOriginalFileLocator
{
    public function __construct(
        private readonly UploadStorageService $storage,
    ) {}

    public function resolveLocalPath(Artwork $artwork): string
    {
        $objectPath = $this->resolveObjectPath($artwork);
        $prefix = $this->originalObjectPrefix();

        if ($objectPath !== '' && str_starts_with($objectPath, $prefix)) {
            $suffix = substr($objectPath, strlen($prefix));
            $root = rtrim($this->storage->localOriginalsRoot(), DIRECTORY_SEPARATOR);

            return $root . DIRECTORY_SEPARATOR . str_replace(['/', '\\'], DIRECTORY_SEPARATOR, (string) $suffix);
        }

        $hash = strtolower((string) $artwork->hash);
        $ext = strtolower(ltrim((string) $artwork->file_ext, '.'));

        if (! $this->isValidHash($hash) || $ext === '') {
            return '';
        }

        $root = rtrim($this->storage->localOriginalsRoot(), DIRECTORY_SEPARATOR);

        return $root
            . DIRECTORY_SEPARATOR . substr($hash, 0, 2)
            . DIRECTORY_SEPARATOR . substr($hash, 2, 2)
            . DIRECTORY_SEPARATOR . $hash . '.' . $ext;
    }

    public function resolveObjectPath(Artwork $artwork): string
    {
        $relative = trim((string) $artwork->file_path, '/');
        $prefix = $this->originalObjectPrefix();

        if ($relative !== '' && str_starts_with($relative, $prefix)) {
            return $relative;
        }

        $hash = strtolower((string) $artwork->hash);
        $ext = strtolower(ltrim((string) $artwork->file_ext, '.'));

        if (! $this->isValidHash($hash) || $ext === '') {
            return '';
        }

        return $this->storage->objectPathForVariant('original', $hash, $hash . '.' . $ext);
    }

    public function resolveObjectUrl(Artwork $artwork): ?string
    {
        $objectPath = $this->resolveObjectPath($artwork);
        if ($objectPath === '') {
            return null;
        }

        return Storage::disk($this->storage->objectDiskName())->url($objectPath);
    }

    private function originalObjectPrefix(): string
    {
        return trim($this->storage->objectBasePrefix(), '/') . '/original/';
    }

    private function isValidHash(string $hash): bool
    {
        return $hash !== '' && preg_match('/^[a-f0-9]+$/', $hash) === 1;
    }
}
