<?php

// phpcs:ignore WordPress.NamingConventions.PrefixAllGlobals.NonPrefixedNamespaceFound -- APD is the established namespace shared with the Pro add-on and retained for backward compatibility.
namespace APD\WooCommerce;

use APD\Support\Assets;
use APD\Support\DesignSummary;
use Automattic\WooCommerce\StoreApi\Schemas\V1\CartItemSchema;

defined('ABSPATH') || exit;

final class StoreApiIntegration
{
    public const NAMESPACE = 'asuka_product_designer';

    private bool $endpointRegistered = false;

    public function boot() : void
    {
        add_filter('woocommerce_store_api_cart_item_images', [$this, 'filterCartItemImages'], 20, 3);
        add_action('wp_enqueue_scripts', [$this, 'enqueueBlockAssets'], 40);

        if (did_action('woocommerce_blocks_loaded')) {
            $this->registerEndpointData();
            return;
        }

        add_action('woocommerce_blocks_loaded', [$this, 'registerEndpointData']);
    }

    public function registerEndpointData() : void
    {
        if ($this->endpointRegistered || ! function_exists('woocommerce_store_api_register_endpoint_data')) {
            return;
        }

        $result = woocommerce_store_api_register_endpoint_data([
            'endpoint' => CartItemSchema::IDENTIFIER,
            'namespace' => self::NAMESPACE,
            'data_callback' => [$this, 'cartItemData'],
            'schema_callback' => [$this, 'cartItemSchema'],
            'schema_type' => ARRAY_A,
        ]);

        $this->endpointRegistered = $result === true;
    }

    public function cartItemSchema() : array
    {
        return [
            'customized' => [
                'description' => __('Whether this cart line contains an Asuka Designer customization.', 'asuka-product-designer'),
                'type' => 'boolean',
                'readonly' => true,
            ],
            'config_id' => [
                'description' => __('Public product configuration identifier.', 'asuka-product-designer'),
                'type' => 'integer',
                'readonly' => true,
            ],
            'config_title' => [
                'description' => __('Product configuration title.', 'asuka-product-designer'),
                'type' => 'string',
                'readonly' => true,
            ],
            'preview_url' => [
                'description' => __('Customer customization preview URL.', 'asuka-product-designer'),
                'type' => 'string',
                'format' => 'uri',
                'readonly' => true,
            ],
            'summary' => [
                'description' => __('Short customer-facing description of the customization.', 'asuka-product-designer'),
                'type' => 'string',
                'readonly' => true,
            ],
            'price_adjustment' => [
                'description' => __('Customization price adjustment in store currency units.', 'asuka-product-designer'),
                'type' => 'number',
                'readonly' => true,
            ],
            'price_total' => [
                'description' => __('Final customized unit price in store currency units.', 'asuka-product-designer'),
                'type' => 'number',
                'readonly' => true,
            ],
        ];
    }

    public function cartItemData(array $cartItem) : array
    {
        $apd = $this->payload($cartItem);
        if ($apd === []) {
            return [];
        }

        $summary = is_array($apd['design_summary'] ?? null) ? $apd['design_summary'] : [];

        return [
            'customized' => true,
            'config_id' => absint($apd['config_id'] ?? 0),
            'config_title' => sanitize_text_field((string) ($apd['config_title'] ?? '')),
            'preview_url' => $this->previewUrl($apd),
            'summary' => sanitize_text_field(DesignSummary::describe($summary)),
            'price_adjustment' => (float) ($apd['price_adjustment'] ?? 0),
            'price_total' => (float) ($apd['price_total'] ?? 0),
        ];
    }

    public function filterCartItemImages(array $images, array $cartItem, string $cartItemKey) : array
    {
        $apd = $this->payload($cartItem);
        if ($apd === []) {
            return $images;
        }

        $attachmentId = absint($apd['preview_attachment_id'] ?? 0);
        $src = $attachmentId > 0 ? (string) wp_get_attachment_image_url($attachmentId, 'full') : '';
        $thumbnail = $attachmentId > 0 ? (string) wp_get_attachment_image_url($attachmentId, 'woocommerce_thumbnail') : '';
        $fallback = $this->previewUrl($apd);
        $src = $this->httpUrl($src !== '' ? $src : $fallback);
        $thumbnail = $this->httpUrl($thumbnail !== '' ? $thumbnail : $src);

        if ($src === '' || $thumbnail === '') {
            return $images;
        }

        $srcset = $attachmentId > 0 ? wp_get_attachment_image_srcset($attachmentId, 'full') : false;
        $sizes = $attachmentId > 0 ? wp_get_attachment_image_sizes($attachmentId, 'woocommerce_thumbnail') : false;
        $attachmentAlt = $attachmentId > 0 ? trim((string) get_post_meta($attachmentId, '_wp_attachment_image_alt', true)) : '';
        $name = $attachmentId > 0 ? trim((string) get_the_title($attachmentId)) : '';

        return [
            (object) [
                'id' => $attachmentId,
                'src' => $src,
                'thumbnail' => $thumbnail,
                'srcset' => is_string($srcset) ? $srcset : '',
                'sizes' => is_string($sizes) ? $sizes : '',
                'name' => $name !== '' ? $name : __('Customized product preview', 'asuka-product-designer'),
                'alt' => $attachmentAlt !== '' ? $attachmentAlt : __('Customized product preview', 'asuka-product-designer'),
            ],
        ];
    }

    public function enqueueBlockAssets() : void
    {
        if (is_admin() || wp_doing_ajax() || ! $this->isCartOrCheckout() || ! $this->cartHasCustomization()) {
            return;
        }

        wp_enqueue_style('apd-front');

        if (! wp_script_is('wc-blocks-checkout', 'registered')) {
            return;
        }

        wp_enqueue_script(
            'apd-checkout-blocks',
            ASUKA_PRODUCT_DESIGNER_ASSETS_URL . 'js/checkout-blocks.js',
            ['wc-blocks-checkout'],
            Assets::version('assets/js/checkout-blocks.js'),
            true
        );
    }

    private function payload(array $cartItem) : array
    {
        return ! empty($cartItem['apd']) && is_array($cartItem['apd']) ? $cartItem['apd'] : [];
    }

    private function previewUrl(array $apd) : string
    {
        $attachmentId = absint($apd['preview_attachment_id'] ?? 0);
        if ($attachmentId > 0) {
            $url = wp_get_attachment_image_url($attachmentId, 'full');
            if (is_string($url) && $this->httpUrl($url) !== '') {
                return $this->httpUrl($url);
            }
        }

        return $this->httpUrl((string) ($apd['preview_url'] ?? ''));
    }

    private function httpUrl(string $url) : string
    {
        $url = esc_url_raw(trim($url), ['http', 'https']);
        return preg_match('#^https?://#i', $url) ? $url : '';
    }

    private function isCartOrCheckout() : bool
    {
        $isCart = function_exists('is_cart') && is_cart();
        $isCheckout = function_exists('is_checkout') && is_checkout();
        return $isCart || $isCheckout;
    }

    private function cartHasCustomization() : bool
    {
        if (! function_exists('WC') || ! WC()->cart) {
            return false;
        }

        foreach (WC()->cart->get_cart() as $cartItem) {
            if ($this->payload(is_array($cartItem) ? $cartItem : []) !== []) {
                return true;
            }
        }

        return false;
    }
}
