<?php

namespace DhlPolskaVendor\Octolize\Blocks\PickupPoint;

use Automattic\WooCommerce\StoreApi\Schemas\V1\CheckoutSchema;
use WC_Shipping_Method;
use WC_Shipping_Zones;
use DhlPolskaVendor\WPDesk\PluginBuilder\Plugin\Hookable;
/**
 * Shipping Workshop Extend Store API.
 */
class StoreEndpoint implements Hookable
{
    private const POINT_ID = 'point_id';
    protected string $integration_name;
    private string $field_name;
    /**
     * @var PickupPointValidator[]
     */
    private array $validators;
    public function __construct(string $integration_name, string $field_name, array $validators)
    {
        $this->integration_name = $integration_name;
        $this->field_name = $field_name;
        $this->validators = $validators;
    }
    public function hooks(): void
    {
        add_action('woocommerce_store_api_checkout_update_order_from_request', [$this, 'update_order_from_request'], 1, 2);
        add_action('woocommerce_blocks_loaded', function () {
            if (function_exists('woocommerce_store_api_register_endpoint_data')) {
                woocommerce_store_api_register_endpoint_data(['endpoint' => CheckoutSchema::IDENTIFIER, 'namespace' => $this->integration_name, 'data_callback' => [$this, 'data_callback'], 'schema_callback' => [$this, 'schema_callback'], 'schema_type' => \ARRAY_A]);
            }
            if (function_exists('woocommerce_store_api_register_update_callback')) {
                woocommerce_store_api_register_update_callback(['namespace' => $this->integration_name, 'callback' => [$this, 'update_callback']]);
            }
        });
    }
    /**
     * @param \WC_Order $order
     * @param \WP_REST_Request $request
     */
    public function update_order_from_request($order, $request): void
    {
        if (!$request instanceof \WP_REST_Request) {
            return;
        }
        if (!$request->has_param('extensions') || !isset($request['extensions'][$this->integration_name])) {
            return;
        }
        $request_data = $request['extensions'][$this->integration_name];
        $value = $request_data[$this->field_name];
        do_action('octolize-pickup-point-blocks-' . $this->integration_name . '-before_update_order_meta', $value, $order);
        $order->update_meta_data($this->field_name, $value);
        $customer_id = $order->get_customer_id();
        if ($customer_id !== 0) {
            update_user_meta($customer_id, $this->field_name, $value);
        }
        $session = WC()->session;
        if ($session) {
            $session->set($this->field_name, $value);
        }
    }
    public function data_callback(): array
    {
        $point_id = null;
        $session = WC()->session;
        if ($session) {
            $point_id = $session->get($this->field_name, null);
        }
        if (empty($point_id)) {
            $user_id = get_current_user_id();
            $point_id = get_user_meta($user_id, $this->field_name, \true) ?: '';
        }
        return apply_filters('octolize-pickup-point-blocks-' . $this->integration_name . '-data', [$this->field_name => $point_id, 'default_options' => apply_filters('octolize-pickup-point-blocks-' . $this->integration_name . '-default_options', [['label' => __('Please enter at least 3 characters', 'dhl-polska'), 'value' => '']], $point_id), 'field_label' => __('Selected pickup point', 'dhl-polska'), 'button_label' => __('Select from map', 'dhl-polska')]);
    }
    public function schema_callback(): array
    {
        return [$this->field_name => ['description' => __('Select pickup point', 'dhl-polska'), 'type' => ['string'], 'context' => ['view', 'edit'], 'readonly' => \false, 'optional' => \false, 'arg_options' => ['validate_callback' => function ($value) {
            try {
                $this->validate_value($value);
            } catch (\Exception $e) {
                return new \WP_Error('invalid_value', $e->getMessage());
            }
            return \true;
        }]]];
    }
    /**
     * @param mixed $value
     *
     * @throws SelectPickupPointException
     */
    private function validate_value($value): void
    {
        $value = trim($value ?? '');
        \WC()->initialize_session();
        $chosen_methods = \WC()->session ? \WC()->session->get('chosen_shipping_methods', array()) : array();
        foreach ($chosen_methods as $rate_id) {
            $parts = explode(':', $rate_id);
            $instance_id = isset($parts[1]) ? (int) $parts[1] : 0;
            if (!$instance_id) {
                continue;
            }
            /** @var WC_Shipping_Method|false $method_instance */
            $method_instance = WC_Shipping_Zones::get_shipping_method($instance_id);
            if ($method_instance) {
                foreach ($this->validators as $validator) {
                    $validator->validate($value, $method_instance);
                }
            }
        }
    }
    public function update_callback(array $data): void
    {
        if (isset($data[self::POINT_ID])) {
            WC()->session->set($this->field_name, $data[self::POINT_ID]);
            WC()->cart->calculate_shipping();
        }
    }
}
