<?php
/**
 * WooCommerce Store API Extension
 *
 * @package Jeremias\WcLicensedProduct\Checkout
 */

declare(strict_types=1);

namespace Jeremias\WcLicensedProduct\Checkout;

use Automattic\WooCommerce\StoreApi\Schemas\V1\CheckoutSchema;
use Automattic\WooCommerce\StoreApi\StoreApi;
use Automattic\WooCommerce\StoreApi\Schemas\ExtendSchema;
use Jeremias\WcLicensedProduct\Admin\SettingsController;
use Jeremias\WcLicensedProduct\License\LicenseManager;

/**
 * Extends the Store API to handle licensed product domain data
 */
final class StoreApiExtension
{
    private const IDENTIFIER = 'wc-licensed-product';

    private LicenseManager $licenseManager;

    public function __construct(LicenseManager $licenseManager)
    {
        $this->licenseManager = $licenseManager;
        $this->registerHooks();
    }

    /**
     * Register Store API hooks
     */
    private function registerHooks(): void
    {
        add_action('woocommerce_blocks_loaded', [$this, 'registerStoreApiExtension']);
    }

    /**
     * Register the Store API extension
     */
    public function registerStoreApiExtension(): void
    {
        if (!class_exists('Automattic\WooCommerce\StoreApi\StoreApi')) {
            return;
        }

        // Register endpoint data extension
        woocommerce_store_api_register_endpoint_data([
            'endpoint' => CheckoutSchema::IDENTIFIER,
            'namespace' => self::IDENTIFIER,
            'data_callback' => [$this, 'getExtensionData'],
            'schema_callback' => [$this, 'getExtensionSchema'],
            'schema_type' => ARRAY_A,
        ]);

        // Register update callback for the domain field
        woocommerce_store_api_register_update_callback([
            'namespace' => self::IDENTIFIER,
            'callback' => [$this, 'handleExtensionUpdate'],
        ]);

        // Hook into checkout order processing
        add_action('woocommerce_store_api_checkout_order_processed', [$this, 'processCheckoutOrder']);
    }

    /**
     * Get extension data for the checkout endpoint
     */
    public function getExtensionData(): array
    {
        if (SettingsController::isMultiDomainEnabled()) {
            return [
                'licensed_product_domains' => WC()->session ? WC()->session->get('licensed_product_domains', []) : [],
            ];
        }

        return [
            'licensed_product_domain' => WC()->session ? WC()->session->get('licensed_product_domain', '') : '',
        ];
    }

    /**
     * Get extension schema
     */
    public function getExtensionSchema(): array
    {
        if (SettingsController::isMultiDomainEnabled()) {
            return [
                'licensed_product_domains' => [
                    'description' => __('Domains for license activation by product', 'wc-licensed-product'),
                    'type' => 'array',
                    'context' => ['view', 'edit'],
                    'readonly' => false,
                    'items' => [
                        'type' => 'object',
                        'properties' => [
                            'product_id' => [
                                'type' => 'integer',
                            ],
                            'variation_id' => [
                                'type' => 'integer',
                            ],
                            'domains' => [
                                'type' => 'array',
                                'items' => [
                                    'type' => 'string',
                                ],
                            ],
                        ],
                    ],
                ],
            ];
        }

        return [
            'licensed_product_domain' => [
                'description' => __('Domain for license activation', 'wc-licensed-product'),
                'type' => 'string',
                'context' => ['view', 'edit'],
                'readonly' => false,
            ],
        ];
    }

    /**
     * Handle extension data updates from the frontend
     */
    public function handleExtensionUpdate(array $data): void
    {
        if (SettingsController::isMultiDomainEnabled()) {
            // Multi-domain mode
            if (isset($data['licensed_product_domains']) && is_array($data['licensed_product_domains'])) {
                $normalizedData = $this->normalizeDomainsData($data['licensed_product_domains']);

                if (WC()->session) {
                    WC()->session->set('licensed_product_domains', $normalizedData);
                }
            }
        } else {
            // Single domain mode
            if (isset($data['licensed_product_domain'])) {
                $sanitized = sanitize_text_field($data['licensed_product_domain']);
                $normalized = $this->licenseManager->normalizeDomain($sanitized);

                if (WC()->session) {
                    WC()->session->set('licensed_product_domain', $normalized);
                }
            }
        }
    }

    /**
     * Normalize domains data from frontend
     */
    private function normalizeDomainsData(array $domainsData): array
    {
        $normalized = [];

        foreach ($domainsData as $item) {
            if (!isset($item['product_id']) || !isset($item['domains']) || !is_array($item['domains'])) {
                continue;
            }

            $productId = (int) $item['product_id'];
            $variationId = isset($item['variation_id']) ? (int) $item['variation_id'] : 0;
            $domains = [];

            foreach ($item['domains'] as $domain) {
                $sanitized = sanitize_text_field($domain);
                if (!empty($sanitized)) {
                    $domains[] = $this->licenseManager->normalizeDomain($sanitized);
                }
            }

            if (!empty($domains)) {
                $entry = [
                    'product_id' => $productId,
                    'domains' => $domains,
                ];

                // Include variation_id if present
                if ($variationId > 0) {
                    $entry['variation_id'] = $variationId;
                }

                $normalized[] = $entry;
            }
        }

        return $normalized;
    }

    /**
     * Process the checkout order - save domains to order meta
     */
    public function processCheckoutOrder(\WC_Order $order): void
    {
        $requestData = json_decode(file_get_contents('php://input'), true);

        if (SettingsController::isMultiDomainEnabled()) {
            $this->processMultiDomainOrder($order, $requestData);
        } else {
            $this->processSingleDomainOrder($order, $requestData);
        }
    }

    /**
     * Process order in single domain mode (legacy)
     */
    private function processSingleDomainOrder(\WC_Order $order, ?array $requestData): void
    {
        $domain = '';

        // Check session first
        if (WC()->session) {
            $domain = WC()->session->get('licensed_product_domain', '');
        }

        // Check in the request data for block checkout (extension data)
        if (empty($domain) && isset($requestData['extensions'][self::IDENTIFIER]['licensed_product_domain'])) {
            $sanitized = sanitize_text_field($requestData['extensions'][self::IDENTIFIER]['licensed_product_domain']);
            $domain = $this->licenseManager->normalizeDomain($sanitized);
        }

        // Check for wclp_license_domain (from our hidden input)
        if (empty($domain) && isset($requestData['wclp_license_domain'])) {
            $sanitized = sanitize_text_field($requestData['wclp_license_domain']);
            $domain = $this->licenseManager->normalizeDomain($sanitized);
        }

        // Check for additional_fields (WC Blocks API)
        if (empty($domain) && isset($requestData['additional_fields']['wc-licensed-product/domain'])) {
            $sanitized = sanitize_text_field($requestData['additional_fields']['wc-licensed-product/domain']);
            $domain = $this->licenseManager->normalizeDomain($sanitized);
        }

        if (!empty($domain)) {
            $order->update_meta_data('_licensed_product_domain', $domain);
            $order->save();

            // Clear session data
            if (WC()->session) {
                WC()->session->set('licensed_product_domain', '');
            }
        }
    }

    /**
     * Process order in multi-domain mode
     */
    private function processMultiDomainOrder(\WC_Order $order, ?array $requestData): void
    {
        $domainData = [];

        // Check session first
        if (WC()->session) {
            $domainData = WC()->session->get('licensed_product_domains', []);
        }

        // Check in the request data for block checkout (extension data)
        if (empty($domainData) && isset($requestData['extensions'][self::IDENTIFIER]['licensed_product_domains'])) {
            $domainData = $this->normalizeDomainsData(
                $requestData['extensions'][self::IDENTIFIER]['licensed_product_domains']
            );
        }

        // Check for wclp_license_domains (from our hidden input - JSON string)
        if (empty($domainData) && isset($requestData['wclp_license_domains'])) {
            $parsed = json_decode($requestData['wclp_license_domains'], true);
            if (is_array($parsed)) {
                $domainData = $this->normalizeDomainsData($parsed);
            }
        }

        // Check for licensed_domains in classic format (from DOM injection)
        if (empty($domainData) && isset($requestData['licensed_domains']) && is_array($requestData['licensed_domains'])) {
            $domainData = [];
            $variationIds = $requestData['licensed_variation_ids'] ?? [];

            foreach ($requestData['licensed_domains'] as $key => $domains) {
                if (!is_array($domains)) {
                    continue;
                }

                // Parse key - could be "productId" or "productId_variationId"
                $parts = explode('_', (string) $key);
                $productId = (int) $parts[0];
                $variationId = isset($parts[1]) ? (int) $parts[1] : 0;

                // Also check for hidden variation ID field
                if ($variationId === 0 && isset($variationIds[$key])) {
                    $variationId = (int) $variationIds[$key];
                }

                $normalizedDomains = [];
                foreach ($domains as $domain) {
                    $sanitized = sanitize_text_field($domain);
                    if (!empty($sanitized)) {
                        $normalizedDomains[] = $this->licenseManager->normalizeDomain($sanitized);
                    }
                }
                if (!empty($normalizedDomains)) {
                    $entry = [
                        'product_id' => $productId,
                        'domains' => $normalizedDomains,
                    ];

                    if ($variationId > 0) {
                        $entry['variation_id'] = $variationId;
                    }

                    $domainData[] = $entry;
                }
            }
        }

        if (!empty($domainData)) {
            $order->update_meta_data('_licensed_product_domains', $domainData);
            $order->save();

            // Clear session data
            if (WC()->session) {
                WC()->session->set('licensed_product_domains', []);
            }
        }
    }
}
