<?php
/**
 * Resolves image references to attachments already in the site library.
 *
 * @package LolaCoreForBricks
 */

declare(strict_types=1);

namespace LolaCoreForBricks\Support;

/**
 * Accepts an attachment ID or a media-library URL. Never downloads remote files.
 */
final class MediaLibraryResolver
{
    /**
     * @return array{success: true, image: array<string, mixed>}|array{success: false, message: string, error: string}
     */
    public function resolve(mixed $image): array
    {
        if (is_int($image) || (is_string($image) && $image !== '' && ctype_digit($image))) {
            return $this->fromId((int) $image);
        }

        if (is_string($image) && $image !== '') {
            return $this->fromUrl($image);
        }

        if (is_array($image)) {
            if (isset($image['id']) && (int) $image['id'] > 0) {
                return $this->fromId((int) $image['id']);
            }

            if (isset($image['url']) && is_string($image['url']) && $image['url'] !== '') {
                return $this->fromUrl($image['url']);
            }
        }

        return $this->failure(
            'I need an image from this site\'s media library. Pass the attachment ID or its library URL.',
            'missing_image'
        );
    }

    /**
     * @return array{success: true, image: array<string, mixed>}|array{success: false, message: string, error: string}
     */
    private function fromId(int $id): array
    {
        if ($id <= 0) {
            return $this->failure('I could not find that image in the media library.', 'image_not_found');
        }

        $url = function_exists('wp_get_attachment_url') ? wp_get_attachment_url($id) : false;
        if (!is_string($url) || $url === '') {
            return $this->failure('I could not find that image in the media library.', 'image_not_found');
        }

        $size = 'full';

        return [
            'success' => true,
            'image'   => [
                'id'   => $id,
                'url'  => $url,
                'size' => $size,
            ],
        ];
    }

    /**
     * @return array{success: true, image: array<string, mixed>}|array{success: false, message: string, error: string}
     */
    private function fromUrl(string $url): array
    {
        $url = trim($url);
        if ($url === '') {
            return $this->failure('I could not find that image in the media library.', 'image_not_found');
        }

        if ($this->isExternalUrl($url)) {
            return $this->failure(
                'That image is not in this site\'s media library. Add it to the library first, then point me at it.',
                'external_image'
            );
        }

        $attachmentId = 0;
        if (function_exists('attachment_url_to_postid')) {
            $attachmentId = (int) attachment_url_to_postid($url);
            if ($attachmentId <= 0 && !preg_match('#^https?://#i', $url) && function_exists('home_url')) {
                $attachmentId = (int) attachment_url_to_postid(home_url($url));
            }
        }

        if ($attachmentId <= 0) {
            return $this->failure(
                'That image is not in this site\'s media library. Add it to the library first, then point me at it.',
                'external_image'
            );
        }

        return $this->fromId($attachmentId);
    }

    private function isExternalUrl(string $url): bool
    {
        $host = wp_parse_url($url, PHP_URL_HOST);
        if (!is_string($host) || $host === '') {
            return false;
        }

        $local = [];
        if (function_exists('home_url')) {
            $siteHost = wp_parse_url(home_url(), PHP_URL_HOST);
            if (is_string($siteHost) && $siteHost !== '') {
                $local[] = strtolower($siteHost);
            }
        }

        if (function_exists('wp_upload_dir')) {
            $upload     = wp_upload_dir();
            $uploadHost = wp_parse_url((string) ($upload['baseurl'] ?? ''), PHP_URL_HOST);
            if (is_string($uploadHost) && $uploadHost !== '') {
                $local[] = strtolower($uploadHost);
            }
        }

        return !in_array(strtolower($host), $local, true);
    }

    /**
     * @return array{success: false, message: string, error: string}
     */
    private function failure(string $message, string $error): array
    {
        return [
            'success' => false,
            'message' => $message,
            'error'   => $error,
        ];
    }
}
