<?php

namespace PhotoSphereViewer\Includes;

if (!defined('ABSPATH')) {
    exit;
}

/**
 * Resolves an Elementor MEDIA value, attachment ID or URL to the original
 * (un-scaled) uploaded file URL.
 *
 * WordPress 5.3+ generates a "*-scaled.jpg" copy for images larger than
 * `big_image_size_threshold` (default 2560px). Both Elementor's MEDIA control
 * and `wp_get_attachment_image_src($id, 'full')` then return the SCALED url
 * as "full". For panoramas (DJI Matrice 4E etc.) this is a major quality loss.
 *
 * This helper returns the original URL whenever it can be safely identified,
 * and otherwise falls back to the input URL so external/manually-typed URLs
 * keep working untouched.
 */
class ImageResolver {

    /**
     * Resolve an image to its original (full resolution) URL.
     *
     * Accepts:
     *  - Elementor MEDIA array: ['id' => int, 'url' => string]
     *  - Bare attachment ID (int|string numeric)
     *  - URL string (will be reverse-mapped to an attachment ID via
     *    `attachment_url_to_postid()` when possible)
     *
     * @param mixed       $media          Elementor media array, attachment ID or URL.
     * @param bool        $prefer_original Whether to prefer the un-scaled original.
     * @param string|null $context        Optional context tag for the filter (e.g. 'panorama', 'gallery', 'tour-scene').
     * @return string Absolute URL — original when available, otherwise the supplied URL.
     */
    public static function resolve($media, $prefer_original = true, $context = null) {
        try {
            // Normalise inputs.
            $attachment_id = 0;
            $fallback_url  = '';

            if (is_array($media)) {
                $attachment_id = isset($media['id']) ? (int) $media['id'] : 0;
                $fallback_url  = isset($media['url']) ? (string) $media['url'] : '';
            } elseif (is_numeric($media)) {
                $attachment_id = (int) $media;
            } elseif (is_string($media)) {
                $fallback_url = $media;
            }

            // Recover ID from URL if needed (handles hand-typed shortcodes).
            if (!$attachment_id && $fallback_url && function_exists('attachment_url_to_postid')) {
                $maybe_id = attachment_url_to_postid($fallback_url);
                if ($maybe_id) {
                    $attachment_id = (int) $maybe_id;
                }
            }

            /**
             * Allow site owners / hosting providers to globally flip the
             * original-image preference (e.g. CDN constraints).
             *
             * @param bool        $prefer_original
             * @param int         $attachment_id
             * @param string|null $context
             */
            $prefer_original = (bool) apply_filters(
                'psv_use_original_image',
                (bool) $prefer_original,
                $attachment_id,
                $context
            );

            if ($attachment_id > 0 && $prefer_original) {
                // 1) WP 5.3+ — true original, bypassing -scaled.
                if (function_exists('wp_get_original_image_url')) {
                    $original = wp_get_original_image_url($attachment_id);
                    if (!empty($original)) {
                        return $original;
                    }
                }

                // 2) Pre 5.3 or no -scaled variant — wp_get_attachment_url already
                //    returns the original for non-scaled uploads.
                $url = wp_get_attachment_url($attachment_id);
                if (!empty($url)) {
                    return $url;
                }

                // 3) Last-resort core fallback.
                $src = wp_get_attachment_image_src($attachment_id, 'full');
                if (is_array($src) && !empty($src[0])) {
                    return $src[0];
                }
            }

            // Not preferring original (toggle off) — return the URL as supplied
            // (Elementor's MEDIA url, which is the scaled variant for big images).
            if ($fallback_url) {
                return $fallback_url;
            }

            // Toggle off but only an ID was supplied — give back the canonical URL.
            if ($attachment_id > 0) {
                $url = wp_get_attachment_url($attachment_id);
                if (!empty($url)) {
                    return $url;
                }
            }
        } catch (\Throwable $e) {
            if (defined('WP_DEBUG') && WP_DEBUG) {
                error_log('[PSV ImageResolver] ' . $e->getMessage());
            }
            // Fall through to the safest possible return below.
            if (is_array($media) && !empty($media['url'])) {
                return (string) $media['url'];
            }
            if (is_string($media)) {
                return $media;
            }
        }

        return '';
    }

    /**
     * Convenience wrapper for URL-only inputs (shortcode attribute strings).
     *
     * @param string $url
     * @param bool   $prefer_original
     * @param string|null $context
     * @return string
     */
    public static function resolve_url($url, $prefer_original = true, $context = null) {
        return self::resolve((string) $url, $prefer_original, $context);
    }
}
