<?php

namespace App\Models\Concerns;

use App\Services\Storage\TenantStorage;
use Illuminate\Database\Eloquent\Casts\Attribute;

/**
 * For models whose `image_url` column holds a file on the platform's Cloudflare
 * R2 bucket.
 *
 * The column stores a PATH — "tenants/<id>/products/abc.png" — never a URL,
 * because the URL depends on the public host currently configured (Master
 * Control → Storage) and a stored absolute URL would keep pointing at the old
 * host after that changes. `image_display_url` is what a browser can actually
 * load, resolved per read.
 *
 * Never put the raw `image_url` in an <img src>: the file is on a bucket host,
 * not the app's own origin, so the column value 404s.
 */
trait HasStoredImage
{
    /**
     * The stored image as something a browser can load, or null when there is
     * no image (or storage cannot answer — see TenantStorage::resolveUrl()).
     *
     * @return Attribute<?string, never>
     */
    protected function imageDisplayUrl(): Attribute
    {
        // Reads the raw attribute rather than $this->image_url: a model may
        // still define its own accessor on the column, and this must resolve
        // what is actually stored.
        return Attribute::get(fn (): ?string => static::resolveStoredImage(
            $this->attributes['image_url'] ?? null,
        ));
    }

    /**
     * Also handles the two shapes rows written before storage was switchable
     * can hold, so an old catalogue keeps rendering after the upgrade.
     */
    public static function resolveStoredImage(?string $value): ?string
    {
        $value = trim((string) $value);

        if ($value === '') {
            return null;
        }

        // Legacy: upload code that called Storage::url() on an already-prefixed
        // path, producing "/storage//storage/products/x.jpg".
        $value = (string) preg_replace('#/storage//+storage/#', '/storage/', $value);

        // Legacy: a docroot-relative local URL that lost its leading slash.
        // Unambiguous — TenantStorage only ever writes under the configured
        // tenancy.storage_prefix, so it never produces a "storage/" path.
        if (str_starts_with($value, 'storage/')) {
            return '/'.$value;
        }

        // Everything else: a real storage path, or an absolute/root-relative
        // URL that resolveUrl() passes straight through.
        return app(TenantStorage::class)->resolveUrl($value);
    }
}
