<?php

namespace Rtc\PlantShopWC\Frontend\Controllers;

use Automattic\WooCommerce\Blocks\Domain\Services\CheckoutFields;
use Rtc\PlantShopWC\Admin\Models\GeneralSettingsModel;
use Throwable;
use WC_Order;
use WP_Error;
use WP_REST_Request;

class CheckoutBlocksController {

    public function register_hooks(): void {
        // Register the fields on server-side so the Store API can validate/persist them.
        add_action( 'init', array( $this, 'register_blocks_checkout_field' ), 20 );
        // Persist from Store API checkout requests.
        add_action( 'woocommerce_store_api_checkout_update_order_from_request', array( $this, 'save_store_api_field' ), 10, 2 );
        // Enhance Blocks UI with description/link if configured.
        add_action( 'enqueue_block_assets', array( $this, 'enqueue_blocks_description_script' ) );
        // Fallback enqueue path for themes/setups where block assets hook does not run as expected.
        add_action( 'wp_enqueue_scripts', array( $this, 'enqueue_blocks_description_script' ), 30 );
        // Last-resort fallback: print a tiny inline script in footer.
        add_action( 'wp_footer', array( $this, 'render_footer_description_failsafe' ), 99 );
    }

    /**
     * Enqueue a tiny JS enhancer to ensure the info description/link is visible on Blocks checkout.
     */
    public function enqueue_blocks_description_script(): void {
        if ( ! function_exists( 'is_checkout' ) || ! is_checkout() ) {
            return;
        }
        $opts    = get_option( GeneralSettingsModel::get_option_key(), array() );
        $enabled = isset( $opts['enable_equivalent_replacement'] ) && (string) $opts['enable_equivalent_replacement'] === '1';
        if ( ! $enabled ) {
            return;
        }
        // Load only if setting is present.
        $opts     = get_option( GeneralSettingsModel::get_option_key(), array() );
        $info_url = isset( $opts['equivalent_replacement_info_url'] ) ? (string) $opts['equivalent_replacement_info_url'] : '';
        if ( empty( $info_url ) ) {
            return;
        }

        // Build the same translated description HTML used server-side.
        $description = sprintf(
            '<a href="%1$s" target="_blank" rel="noopener">%2$s</a>',
            esc_url( $info_url ),
            esc_html__( 'Learn more about equivalent replacements', 'plantshop-wc' )
        );

        // Register and enqueue the enhancer.
        wp_register_script(
            'plantshop-wc-checkout-block-enhance',
            PLANTSHOP_WC_PUBLIC_URL . 'frontend/js/checkout-block-enhance.js',
            array(),
            defined( 'PLANTSHOP_WC_PLUGIN_VERSION' ) ? PLANTSHOP_WC_PLUGIN_VERSION : null,
            true
        );
        wp_localize_script(
            'plantshop-wc-checkout-block-enhance',
            'plantshop_wc_er_info',
            array(
                'description' => $description,
            )
        );
        wp_enqueue_script( 'plantshop-wc-checkout-block-enhance' );

        // Failsafe: inject via inline script with no external dependencies.
        $inline_handle = 'plantshop-wc-checkout-block-enhance-failsafe';
        if ( ! wp_script_is( $inline_handle, 'registered' ) ) {
            wp_register_script( $inline_handle, '', array(), defined( 'PLANTSHOP_WC_PLUGIN_VERSION' ) ? PLANTSHOP_WC_PLUGIN_VERSION : null, true );
        }
        wp_enqueue_script( $inline_handle );
        $description_js = wp_json_encode( $description );
        $inline_js      = '(function(){'
            . 'var description=' . $description_js . ';'
            . 'if(!description){return;}'
            . 'function inject(){'
            . 'var container=document.querySelector("#order .wc-block-components-address-form__plantshop-wc-equivalent_replacement_consent");'
            . 'if(!container){return;}'
            . 'var existing=container.parentNode?container.parentNode.querySelector(".plantshop-wc-er-info[data-pswc-er-for=\\"equivalent_replacement_consent\\"]"):null;'
            . 'if(existing){return;}'
            . 'var p=document.createElement("p");'
            . 'p.className="plantshop-wc-er-info";'
            . 'p.setAttribute("data-pswc-er-for","equivalent_replacement_consent");'
            . 'p.style.display="block";'
            . 'p.style.margin="6px 0 0 28px";'
            . 'p.style.fontSize="0.875em";'
            . 'p.style.lineHeight="1.4";'
            . 'p.innerHTML=description;'
            . 'if(container.nextSibling){container.parentNode.insertBefore(p,container.nextSibling);}else{container.parentNode.appendChild(p);}'
            . '}'
            . 'if(document.readyState==="loading"){document.addEventListener("DOMContentLoaded",inject);}else{inject();}'
            . 'try{var mo=new MutationObserver(inject);mo.observe(document.body,{childList:true,subtree:true});}catch(e){}'
            . '})();';
        wp_add_inline_script( $inline_handle, $inline_js );
    }

    /**
     * Last-resort fallback for environments where enqueued scripts don't run as expected.
     */
    public function render_footer_description_failsafe(): void {
        if ( is_admin() ) {
            return;
        }
        $opts    = get_option( GeneralSettingsModel::get_option_key(), array() );
        $enabled = isset( $opts['enable_equivalent_replacement'] ) && (string) $opts['enable_equivalent_replacement'] === '1';
        if ( ! $enabled ) {
            return;
        }
        $info_url = isset( $opts['equivalent_replacement_info_url'] ) ? (string) $opts['equivalent_replacement_info_url'] : '';
        if ( empty( $info_url ) ) {
            return;
        }
        $description = sprintf(
            '<a href="%1$s" target="_blank" rel="noopener">%2$s</a>',
            esc_url( $info_url ),
            esc_html__( 'Learn more about equivalent replacements', 'plantshop-wc' )
        );
        ?>
        <script id="plantshop-wc-er-footer-failsafe">
            (function () {
                var description = <?php echo wp_json_encode( $description ); ?>;
                if (!description) { return; }
                var marker = 'equivalent_replacement_consent';
                var infoUrl = <?php echo wp_json_encode( esc_url( $info_url ) ); ?>;

                function findBlockContainer() {
                    return document.querySelector('#order .wc-block-components-address-form__plantshop-wc-equivalent_replacement_consent');
                }

                function injectIntoBlock() {
                    var container = findBlockContainer();
                    if (!container) { return false; }
                    if (container.querySelector('.plantshop-wc-er-info[data-pswc-er-for="' + marker + '"]')) {
                        return true;
                    }
                    var existingLink = infoUrl ? container.querySelector('a[href="' + infoUrl + '"]') : null;
                    if (existingLink) { return true; }
                    var el = document.createElement('p');
                    el.className = 'plantshop-wc-er-info';
                    el.setAttribute('data-pswc-er-for', marker);
                    el.style.display = 'block';
                    el.style.margin = '6px 0 0 28px';
                    el.style.fontSize = '0.875em';
                    el.style.lineHeight = '1.4';
                    el.innerHTML = description;
                    container.appendChild(el);
                    return true;
                }

                function injectIntoClassic() {
                    var input = document.querySelector('input[type="checkbox"][name="plantshop_equivalent_replacement_consent"]');
                    if (!input) { return false; }
                    var row = input.closest('p.form-row, .form-row');
                    if (!row) { return false; }
                    if (row.querySelector('.plantshop-wc-er-info[data-pswc-er-for="' + marker + '"]')) {
                        return true;
                    }
                    var existingLink = infoUrl ? row.querySelector('a[href="' + infoUrl + '"]') : null;
                    if (existingLink) { return true; }
                    var wrapper = row.querySelector('.woocommerce-input-wrapper') || row;
                    var el = document.createElement('p');
                    el.className = 'plantshop-wc-er-info';
                    el.setAttribute('data-pswc-er-for', marker);
                    el.style.display = 'block';
                    el.style.margin = '4px 0 0 24px';
                    el.style.fontSize = '0.95em';
                    el.innerHTML = description;
                    wrapper.appendChild(el);
                    return true;
                }

                function inject() {
                    var didBlock = injectIntoBlock();
                    var didClassic = injectIntoClassic();
                    return didBlock || didClassic;
                }

                var attempts = 0;
                function tick() {
                    inject();
                    attempts++;
                    if (attempts < 25) {
                        setTimeout(tick, 300);
                    }
                }
                if (document.readyState === 'loading') {
                    document.addEventListener('DOMContentLoaded', tick);
                } else {
                    tick();
                }

                if (window.jQuery && window.jQuery(document.body).on) {
                    window.jQuery(document.body).on('updated_checkout', inject);
                }
            })();
        </script>
        <?php
    }

    /**
     * Register the custom fields with WooCommerce Blocks CheckoutFields service.
     */
    public function register_blocks_checkout_field(): void {
        if ( ! function_exists( 'wc_get_container' ) ) {
            return;
        }
        try {
            $container = wc_get_container();
            /** @var CheckoutFields $checkout_fields */
            $checkout_fields = $container->get( CheckoutFields::class );
            if ( ! $checkout_fields ) {
                return;
            }

            $opts    = get_option( GeneralSettingsModel::get_option_key(), array() );
            $enabled = isset( $opts['enable_equivalent_replacement'] ) && (string) $opts['enable_equivalent_replacement'] === '1';
            if ( $enabled ) {
                $info_url    = isset( $opts['equivalent_replacement_info_url'] ) ? (string) $opts['equivalent_replacement_info_url'] : '';
                $description = '';
                if ( ! empty( $info_url ) ) {
                    $description = sprintf(
                        '<a href="%1$s" target="_blank" rel="noopener">%2$s</a>',
                        esc_url( $info_url ),
                        esc_html__( 'Learn more about equivalent replacements', 'plantshop-wc' )
                    );
                }
                // Always register the consent checkbox.
                $args = array(
                    // id must be namespace/name
                    'id'                         => 'plantshop-wc/equivalent_replacement_consent',
                    'label'                      => __( 'I agree to receive an equivalent replacement if an ordered plant is unavailable', 'plantshop-wc' ),
                    'location'                   => 'order',
                    'type'                       => 'checkbox',
                    'required'                   => false,
                    'default_value'              => true, // Pre-check by default in Blocks checkout.
                    // Shown in order confirmation blocks by default.
                    'show_in_order_confirmation' => true,
                    'description'                => $description,
                    // Sanitize to a consistent string value.
                    'sanitize_callback'          => function ( $value ) {
                        return wc_string_to_bool( $value ) ? '1' : '0';
                    },
                );
                $checkout_fields->register_checkout_field( $args );
            }

            // Conditionally register the "Desired shipping week" select when enabled and configured.
            $opts    = get_option( GeneralSettingsModel::get_option_key(), array() );
            $enabled = isset( $opts['enable_shipping_periods'] ) && (string) $opts['enable_shipping_periods'] === '1';
            if ( $enabled ) {
                $weeks = $this->compute_allowed_weeks( $opts );
                if ( ! empty( $weeks ) ) {
                    // Build the options array for the checkout field select element.
                    $options = array();
                    foreach ( $weeks as $wk ) {
                        $options[] = array(
                            'value' => $wk,
                            'label' => $this->human_week_label( $wk ),
                        );
                    }

                    $default = $weeks[0];
                    $checkout_fields->register_checkout_field(
                        array(
                            'id'                         => 'plantshop-wc/shipping_week',
                            'label'                      => __( 'Desired shipping week', 'plantshop-wc' ),
                            'location'                   => 'order',
                            'type'                       => 'select',
                            'required'                   => true,
                            'options'                    => $options,
                            'default_value'              => $default,
                            'show_in_order_confirmation' => true,
                            'sanitize_callback'          => function ( $value ) {
                                return is_string( $value ) ? sanitize_text_field( $value ) : '';
                            },
                            'validate_callback'          => function ( $value ) use ( $weeks ) {
                                $val = is_string( $value ) ? $value : '';
                                if ( $val === '' || ! in_array( $val, $weeks, true ) ) {
                                    return new WP_Error( 'plantshop_wk_invalid', __( 'Please select a desired shipping week.', 'plantshop-wc' ) );
                                }
                                return true;
                            },
                        )
                    );
                }
            }
        } catch ( Throwable $e ) {
            \plantshop_wc_log( 'Checkout blocks registration failed: ' . $e->getMessage(), 'warning' );
        }
    }

    /**
     * Persist our custom fields to order meta when using the Store API (Blocks checkout).
     *
     * @param WC_Order $order
     * @param WP_REST_Request $request
     */
    public function save_store_api_field( $order, $request ): void {
        if ( ! $order || ! $request ) {
            return;
        }
        // Store API nests additional fields under customer.additional_fields (order group "other").
        $params = $request->get_params();

        // Equivalent replacement consent
        $value = '';
        if ( isset( $params['customer']['additional_fields']['plantshop-wc/equivalent_replacement_consent'] ) ) {
            $value = (string) $params['customer']['additional_fields']['plantshop-wc/equivalent_replacement_consent'];
        } elseif ( isset( $params['additional_fields']['plantshop-wc/equivalent_replacement_consent'] ) ) {
            // Older shapes / future-proofing.
            $value = (string) $params['additional_fields']['plantshop-wc/equivalent_replacement_consent'];
        }
        $flag = wc_string_to_bool( $value ) ? '1' : '0';
        // Always persist, even if unchecked (will be '0').
        $order->update_meta_data( '_plantshop_equivalent_replacement_consent', $flag );

        // Desired shipping week (already validated by the service if registered)
        $shipWeek = '';
        if ( isset( $params['customer']['additional_fields']['plantshop-wc/shipping_week'] ) ) {
            $shipWeek = (string) $params['customer']['additional_fields']['plantshop-wc/shipping_week'];
        } elseif ( isset( $params['additional_fields']['plantshop-wc/shipping_week'] ) ) {
            $shipWeek = (string) $params['additional_fields']['plantshop-wc/shipping_week'];
        }
        if ( $shipWeek !== '' ) {
            $order->update_meta_data( '_plantshop_shipping_week', sanitize_text_field( $shipWeek ) );
        }
    }

    /**
     * Compute allowed weeks from settings array. Returns list like ["2025-W12", ...] sorted ascending.
     */
    private function compute_allowed_weeks( array $opts ): array {
        $raw = isset( $opts['shipping_week_ranges'] ) ? (string) $opts['shipping_week_ranges'] : '';
        if ( $raw === '' ) {
            return array();
        }
        $lines          = preg_split( '/\n+/', str_replace( array( "\r\n", "\r" ), "\n", $raw ) );
        $set            = array();
        $currentIsoYear = (int) gmdate( 'o' );
        $currentIsoWeek = (int) gmdate( 'W' );
        foreach ( $lines as $line ) {
            $line = trim( $line );
            if ( $line === '' ) {
                continue; }
            // Accept formats: Wnn or ranges Wnn-Wnn (and legacy Wnn..Wnn)
            if ( preg_match( '/^W(\d{1,2})(?:\-{1}|\.{2})W(\d{1,2})$/i', $line, $m ) ) {
                $w1 = max( 1, min( 53, intval( $m[1] ) ) );
                $w2 = max( 1, min( 53, intval( $m[2] ) ) );
                if ( $w1 > $w2 ) {
                    [$w1, $w2] = array( $w2, $w1 ); }
                for ( $w = $w1; $w <= $w2; $w++ ) {
                    $targetYear = ( $w >= $currentIsoWeek ) ? $currentIsoYear : ( $currentIsoYear + 1 );
                    $yy         = $this->find_valid_iso_year_for_week( $targetYear, $w );
                    if ( $yy !== null ) {
                        $set[ sprintf( '%04d-W%02d', $yy, $w ) ] = true;
                    }
                }
            } elseif ( preg_match( '/^W(\d{1,2})$/i', $line, $m ) ) {
                $w          = max( 1, min( 53, intval( $m[1] ) ) );
                $targetYear = ( $w >= $currentIsoWeek ) ? $currentIsoYear : ( $currentIsoYear + 1 );
                $yy         = $this->find_valid_iso_year_for_week( $targetYear, $w );
                if ( $yy !== null ) {
                    $set[ sprintf( '%04d-W%02d', $yy, $w ) ] = true;
                }
            }
        }
        $weeks = array_keys( $set );
        sort( $weeks, SORT_STRING );
        return $weeks;
    }

    /**
     * Find a valid ISO year for a given week number starting from startYear moving forward.
     * Returns null if a matching year is not found within the next few years.
     */
    private function find_valid_iso_year_for_week( int $startYear, int $week ): ?int {
        if ( $week < 1 || $week > 53 ) {
            return null; }
        for ( $i = 0; $i < 6; $i++ ) {
            $y = $startYear + $i;
            try {
                $dt = new \DateTime();
                $dt->setISODate( $y, $week, 1 );
                $yy = (int) $dt->format( 'o' );
                $ww = (int) $dt->format( 'W' );
                if ( $yy === $y && $ww === $week ) {
                    return $y;
                }
            } catch ( \Throwable $e ) {
                continue;
            }
        }
        return null;
    }

    private function human_week_label( string $code ): string {
        if ( ! preg_match( '/^(\d{4})-W(\d{2})$/', $code, $m ) ) {
            return $code;
        }
        $y = intval( $m[1] );
        $w = intval( $m[2] );
        // translators: 1: ISO week number, 2: ISO year.
        return sprintf( __( 'Week %1$d, %2$d', 'plantshop-wc' ), $w, $y ) . ' (' . $code . ')';
    }
}
