<?php

if (!defined('ABSPATH')) {
    exit;
}

class AIEO_DMM_COD_Country_Block {

    
    const OPTION_KEY = 'aieo_dmm_cod_blocked_countries';

    
    const OPTION_METHODS_KEY = 'aieo_dmm_cod_blocked_shipping_methods';

    
    const OPTION_RATES_KEY = 'aieo_dmm_cod_courier_rates';

    public static function bootstrap() {
        static $done = false;
        if ($done) { return; }
        $done = true;

        
        add_action('aieo_dmm_cod_card_after_fee_label', array(__CLASS__, 'render_field'));
        add_action('wp_ajax_aieo_dmm_free_shipping_save', array(__CLASS__, 'save'), 5);

        
        
        
        
        

        
        if (!empty(self::get_blocked()) || !empty(self::get_blocked_methods()) || self::hide_for_pickup()) {
            add_filter('woocommerce_available_payment_gateways', array(__CLASS__, 'gate_cod'), 1001);
            add_action('wp_enqueue_scripts', array(__CLASS__, 'enqueue_block_support'));
        }

        
        
        if (self::description_has_token()) {
            add_filter('option_woocommerce_' . self::cod_slug() . '_settings', array(__CLASS__, 'inject_fee_into_cod_settings'));
        }
    }

    
    public static function hide_for_pickup() {
        return get_option('aieo_dmm_cod_hide_for_pickup', 'yes') === 'yes';
    }

    
    private static function pickup_method_ids() {
        if (class_exists('Automattic\\WooCommerce\\StoreApi\\Utilities\\LocalPickupUtils')) {
            $ids = \Automattic\WooCommerce\StoreApi\Utilities\LocalPickupUtils::get_local_pickup_method_ids();
            if (is_array($ids) && !empty($ids)) { return array_values(array_map('strval', $ids)); }
        }
        return array('local_pickup', 'pickup_location');
    }

    
    private static function chosen_is_pickup() {
        if (!function_exists('WC') || !WC() || !WC()->session) { return false; }
        $chosen = WC()->session->get('chosen_shipping_methods');
        if (!is_array($chosen)) { return false; }
        $ids = self::pickup_method_ids();
        foreach ($chosen as $m) {
            $parts = explode(':', (string) $m, 2);
            if (in_array($parts[0], $ids, true)) { return true; }
        }
        return false;
    }

    
    private static function description_has_token() {
        $opt = get_option('woocommerce_' . self::cod_slug() . '_settings', array());
        if (!is_array($opt)) { return false; }
        foreach (array('description', 'instructions') as $k) {
            if (isset($opt[$k]) && strpos((string) $opt[$k], '{cod_fee}') !== false) {
                return true;
            }
        }
        return false;
    }

    
    
    

    public static function render_field($settings = array()) {
        $countries        = self::shipping_countries();
        $blocked          = self::get_blocked();
        $carriers         = self::discover_carriers();
        $blocked_methods  = self::get_blocked_methods();
        $courier_rates    = self::get_courier_rates();
        ?>
        <tr>
            <th><?php esc_html_e('Disable COD for countries', 'ai-eshop-optimizer'); ?></th>
            <td>
                <?php if (empty($countries)) : ?>
                    <p class="description">
                        <?php esc_html_e('No shipping countries are configured in WooCommerce → Settings → Shipping yet.', 'ai-eshop-optimizer'); ?>
                    </p>
                <?php else : ?>
                    <fieldset style="margin:0;padding:0;border:0;">
                        <?php foreach ($countries as $code => $name) : ?>
                            <label style="display:block;margin:0 0 6px;line-height:1.4;">
                                <input type="checkbox" name="cod_blocked_countries[]"
                                       value="<?php echo esc_attr($code); ?>"
                                       <?php checked(in_array(strtoupper($code), $blocked, true)); ?>>
                                <?php echo esc_html($name . ' (' . $code . ')'); ?>
                            </label>
                        <?php endforeach; ?>
                    </fieldset>
                    <p class="description">
                        <?php esc_html_e('Tick a country to HIDE Cash on Delivery when the customer\'s BILLING country is that country.', 'ai-eshop-optimizer'); ?>
                    </p>
                <?php endif; ?>
            </td>
        </tr>
        <tr>
            <th><?php esc_html_e('COD per courier', 'ai-eshop-optimizer'); ?></th>
            <td>
                <?php if (empty($carriers)) : ?>
                    <p class="description">
                        <?php esc_html_e('No active shipping methods found.', 'ai-eshop-optimizer'); ?>
                    </p>
                <?php else : ?>
                    <fieldset style="margin:0;padding:0;border:0;">
                        <div style="display:flex;gap:10px;font-size:11px;color:#646970;text-transform:uppercase;letter-spacing:.03em;margin:0 0 4px;">
                            <span style="width:70px;"><?php esc_html_e('Disable', 'ai-eshop-optimizer'); ?></span>
                            <span style="flex:1;"><?php esc_html_e('Courier', 'ai-eshop-optimizer'); ?></span>
                            <span style="width:150px;"><?php esc_html_e('COD fee override', 'ai-eshop-optimizer'); ?></span>
                        </div>
                        <?php foreach ($carriers as $key => $label) :
                            $is_disabled = in_array($key, $blocked_methods, true);
                            $rate_val    = isset($courier_rates[$key]) ? (string) $courier_rates[$key] : '';
                            ?>
                            <div style="display:flex;align-items:center;gap:10px;padding:4px 0;line-height:1.4;">
                                <span style="width:70px;text-align:center;">
                                    <input type="checkbox" name="cod_blocked_shipping_methods[]"
                                           value="<?php echo esc_attr($key); ?>"
                                           <?php checked($is_disabled); ?>>
                                </span>
                                <span style="flex:1;"><?php echo esc_html($label); ?></span>
                                <span style="width:150px;">
                                    <input type="text" inputmode="decimal"
                                           name="cod_courier_rate[<?php echo esc_attr($key); ?>]"
                                           value="<?php echo esc_attr($rate_val); ?>"
                                           placeholder="<?php esc_attr_e('default', 'ai-eshop-optimizer'); ?>"
                                           style="width:110px;">
                                </span>
                            </div>
                        <?php endforeach; ?>
                    </fieldset>
                    <p class="description">
                        <?php esc_html_e('Tick "Disable" to HIDE Cash on Delivery when the customer chooses that courier (e.g. Box Now). Or set a COD fee override to charge a different amount than the default for that courier — leave blank to use the default fee above. Applies across every zone the courier appears in. (Overrides only apply when the COD fee is enabled.)', 'ai-eshop-optimizer'); ?>
                    </p>
                <?php endif; ?>
            </td>
        </tr>
        <tr>
            <th><?php esc_html_e('COD for store pickup', 'ai-eshop-optimizer'); ?></th>
            <td>
                <label style="display:block;line-height:1.5;">
                    <input type="checkbox" name="cod_hide_for_pickup" value="1" <?php checked(self::hide_for_pickup()); ?>>
                    <?php esc_html_e('Hide Cash on Delivery when the customer chooses store pickup (COD is for delivery only)', 'ai-eshop-optimizer'); ?>
                </label>
                <p class="description">
                    <?php esc_html_e('Covers both the legacy "Παραλαβή από κατάστημα" methods and the new Blocks pickup. Customers paying in cash at the store use the "Cash payment during pick-up" method instead.', 'ai-eshop-optimizer'); ?>
                </p>
            </td>
        </tr>
        <?php
    }

    public static function save() {
        
        $section = isset($_POST['form_section']) ? sanitize_key(wp_unslash($_POST['form_section'])) : '';
        if ($section !== 'cod') {
            return;
        }
        if (!check_ajax_referer(AIEO_DMM::NONCE_ACTION, 'nonce', false)) {
            return;
        }
        if (defined('AIEO_CAPABILITY') && !current_user_can(AIEO_CAPABILITY)) {
            return;
        }

        
        $allowed = self::allowed_country_codes();
        $blocked = array();
        if (isset($_POST['cod_blocked_countries']) && is_array($_POST['cod_blocked_countries'])) {
            $raw = array_map('sanitize_text_field', wp_unslash($_POST['cod_blocked_countries']));
            $blocked = array_values(array_intersect(array_map('strtoupper', $raw), $allowed));
        }
        update_option(self::OPTION_KEY, $blocked, false);

        
        $valid_keys = array_keys(self::discover_carriers());
        $methods = array();
        if (isset($_POST['cod_blocked_shipping_methods']) && is_array($_POST['cod_blocked_shipping_methods'])) {
            $raw = array_map('sanitize_text_field', wp_unslash($_POST['cod_blocked_shipping_methods']));
            $methods = array_values(array_intersect($raw, $valid_keys));
        }
        update_option(self::OPTION_METHODS_KEY, $methods, false);

        
        
        $rates = array();
        if (isset($_POST['cod_courier_rate']) && is_array($_POST['cod_courier_rate'])) {
            foreach (wp_unslash($_POST['cod_courier_rate']) as $key => $val) {
                $key = sanitize_text_field((string) $key);
                if (!in_array($key, $valid_keys, true)) { continue; }
                $val = trim((string) $val);
                if ($val === '') { continue; } 
                
                $val = str_replace(',', '.', $val);
                $rates[$key] = max(0, (float) $val);
            }
        }
        update_option(self::OPTION_RATES_KEY, $rates, false);

        
        update_option('aieo_dmm_cod_hide_for_pickup', !empty($_POST['cod_hide_for_pickup']) ? 'yes' : 'no', false);
        
    }

    
    
    

    public static function gate_cod($gateways) {
        if (!is_array($gateways)) {
            return $gateways;
        }
        if (is_admin() && !wp_doing_ajax()) {
            return $gateways;
        }

        $blocked       = self::get_blocked();
        $blocked_rates = self::blocked_rate_ids();
        $hide_pickup   = self::hide_for_pickup();
        if (empty($blocked) && empty($blocked_rates) && !$hide_pickup) {
            return $gateways;
        }

        $slug = self::cod_slug();
        if ($slug === '' || !isset($gateways[$slug])) {
            return $gateways;
        }

        
        if ($hide_pickup && self::chosen_is_pickup()) {
            unset($gateways[$slug]);
            return $gateways;
        }

        
        if (!empty($blocked)) {
            $country = self::billing_country();
            if ($country !== '' && in_array($country, $blocked, true)) {
                unset($gateways[$slug]);
                return $gateways;
            }
        }

        
        if (!empty($blocked_rates) && function_exists('WC') && WC() && WC()->session) {
            $chosen = WC()->session->get('chosen_shipping_methods');
            if (is_array($chosen)) {
                foreach ($chosen as $rate_id) {
                    if (in_array(self::base_rate_id($rate_id), $blocked_rates, true)) {
                        unset($gateways[$slug]);
                        return $gateways;
                    }
                }
            }
        }

        return $gateways;
    }

    
    
    

    public static function enqueue_block_support() {
        $blocked       = self::get_blocked();
        $blocked_rates = self::blocked_rate_ids();
        $hide_pickup   = self::hide_for_pickup();
        if (empty($blocked) && empty($blocked_rates) && !$hide_pickup) {
            return;
        }
        if (!(function_exists('is_checkout') && is_checkout()) && !(function_exists('is_cart') && is_cart())) {
            return;
        }
        $handle = 'wc-blocks-registry';
        if (!wp_script_is($handle, 'registered') && !wp_script_is($handle, 'enqueued')) {
            return;
        }
        wp_enqueue_script($handle);

        $cfg = wp_json_encode(array(
            'slug'          => self::cod_slug(),
            'blocked'       => $blocked,
            'blockedRates'  => array_values($blocked_rates),
            'hidePickup'    => $hide_pickup,
            'pickupIds'     => $hide_pickup ? self::pickup_method_ids() : array(),
        ));
        if (!is_string($cfg)) {
            return;
        }

        $js = <<<JS
( function () {
    var cfg = {$cfg};
    var wc = window.wc;
    if ( ! cfg || ! cfg.slug || ! wc || ! wc.wcBlocksRegistry ||
         typeof wc.wcBlocksRegistry.registerPaymentMethodExtensionCallbacks !== 'function' ) {
        return;
    }
    var blockedCountries = ( cfg.blocked || [] ).map( function ( c ) { return String( c ).toUpperCase(); } );
    var blockedRates = ( cfg.blockedRates || [] ).map( String );
    var hidePickup = !! cfg.hidePickup;
    var pickupIds = ( cfg.pickupIds || [] );
    var selectedIds = function ( arg ) {
        var sel = ( arg && arg.selectedShippingMethods ) || {};
        if ( Array.isArray( sel ) ) { return sel; }
        if ( sel && typeof sel === 'object' ) { return Object.keys( sel ).map( function ( k ) { return sel[ k ]; } ); }
        return [];
    };
    var baseRate = function ( rid ) {
        rid = String( rid );
        var c = rid.indexOf( ':' );
        if ( c === -1 ) { return rid; }
        var method = rid.slice( 0, c );
        var mm = rid.slice( c + 1 ).match( /^(\d+)/ );
        return mm ? method + ':' + mm[ 1 ] : rid;
    };
    var callbacks = {};
    callbacks[ cfg.slug ] = function ( arg ) {
        try {
            // (a) billing country
            var addr = ( arg && ( arg.billingAddress || arg.billingData ) ) || {};
            var country = String( addr.country || '' ).toUpperCase();
            if ( country && blockedCountries.indexOf( country ) !== -1 ) {
                return false;
            }
            // (b) chosen shipping method(s)
            var ids = selectedIds( arg );
            if ( blockedRates.length ) {
                for ( var i = 0; i < ids.length; i++ ) {
                    if ( blockedRates.indexOf( baseRate( ids[ i ] ) ) !== -1 ) {
                        return false;
                    }
                }
            }
            // (c) store pickup — COD is delivery-only
            if ( hidePickup && pickupIds.length ) {
                for ( var j = 0; j < ids.length; j++ ) {
                    var mid = String( ids[ j ] ).split( ':' )[ 0 ];
                    if ( pickupIds.indexOf( mid ) !== -1 ) { return false; }
                }
            }
            return true;
        } catch ( e ) {
            return true;
        }
    };
    wc.wcBlocksRegistry.registerPaymentMethodExtensionCallbacks( 'aieo-cod-country-block', callbacks );
} )();
JS;
        wp_add_inline_script($handle, $js);
    }

    
    
    

    private static function billing_country() {
        
        if (isset($_POST['billing_country'])) {
            $c = strtoupper(sanitize_text_field((string) wp_unslash($_POST['billing_country'])));
            if ($c !== '') {
                return $c;
            }
        }
        if (isset($_POST['post_data'])) {
            parse_str((string) wp_unslash($_POST['post_data']), $pd);
            if (is_array($pd) && !empty($pd['billing_country'])) {
                return strtoupper(sanitize_text_field((string) $pd['billing_country']));
            }
        }
        
        if (function_exists('WC') && WC() && WC()->customer) {
            return strtoupper((string) WC()->customer->get_billing_country());
        }
        return '';
    }

    
    public static function get_blocked() {
        $v = get_option(self::OPTION_KEY, array());
        if (!is_array($v)) { $v = array(); }
        $v = array_map('strtoupper', array_map('strval', $v));
        return array_values(array_filter($v));
    }

    
    public static function get_blocked_methods() {
        $v = get_option(self::OPTION_METHODS_KEY, array());
        if (!is_array($v)) { $v = array(); }
        return array_values(array_filter(array_map('strval', $v)));
    }

    
    public static function get_courier_rates() {
        $v = get_option(self::OPTION_RATES_KEY, array());
        if (!is_array($v)) { $v = array(); }
        $out = array();
        foreach ($v as $k => $amount) {
            $out[(string) $k] = (float) $amount;
        }
        return $out;
    }

    
    public static function cod_fee_override_for_chosen() {
        $rates = self::get_courier_rates();
        if (empty($rates)) { return null; }
        if (!function_exists('WC') || !WC() || !WC()->session) { return null; }
        $chosen = WC()->session->get('chosen_shipping_methods');
        if (!is_array($chosen) || empty($chosen)) { return null; }
        $map = self::rate_id_to_carrier_map();
        foreach ($chosen as $rate_id) {
            $base = self::base_rate_id($rate_id);
            if (isset($map[$base]) && isset($rates[$map[$base]])) {
                return (float) $rates[$map[$base]];
            }
        }
        return null;
    }

    
    public static function inject_fee_into_cod_settings($settings) {
        if (!is_array($settings)) {
            return $settings;
        }
        
        if (is_admin() && !wp_doing_ajax() && !(defined('REST_REQUEST') && REST_REQUEST)) {
            return $settings;
        }
        $has = (isset($settings['description']) && strpos((string) $settings['description'], '{cod_fee}') !== false)
            || (isset($settings['instructions']) && strpos((string) $settings['instructions'], '{cod_fee}') !== false);
        if (!$has) {
            return $settings;
        }
        $fee = self::format_fee_number(self::effective_cod_fee());
        if (isset($settings['description'])) {
            $settings['description'] = str_replace('{cod_fee}', $fee, (string) $settings['description']);
        }
        if (isset($settings['instructions'])) {
            $settings['instructions'] = str_replace('{cod_fee}', $fee, (string) $settings['instructions']);
        }
        return $settings;
    }

    
    public static function effective_cod_fee() {
        $fs = get_option('aieo_dmm_free_shipping', array());
        if (!is_array($fs)) { $fs = array(); }
        if ((isset($fs['cod_enabled']) ? $fs['cod_enabled'] : 'no') !== 'yes') {
            return 0.0;
        }
        $override = self::cod_fee_override_for_chosen();
        if ($override !== null) {
            return (float) $override;
        }
        return (float) (isset($fs['cod_fee']) ? $fs['cod_fee'] : 0);
    }

    
    private static function format_fee_number($amount) {
        $s = rtrim(rtrim(number_format((float) $amount, 2, '.', ''), '0'), '.');
        return $s === '' ? '0' : $s;
    }

    
    public static function rate_id_to_carrier_map() {
        static $memo = null;
        if ($memo !== null) { return $memo; }
        $map = array();
        foreach (self::iterate_zone_methods() as $m) {
            $iid = (int) (method_exists($m, 'get_instance_id') ? $m->get_instance_id() : 0);
            if ($iid <= 0) { continue; }
            $mid   = (string) $m->id;
            $title = method_exists($m, 'get_title') ? (string) $m->get_title() : '';
            if ($title === '') { $title = $mid; }
            $map[$mid . ':' . $iid] = self::carrier_key($mid, $title);
        }
        $memo = $map;
        return $memo;
    }

    private static function shipping_countries() {
        if (!function_exists('WC') || !WC() || !WC()->countries) {
            return array();
        }
        $c = WC()->countries->get_shipping_countries();
        return is_array($c) ? $c : array();
    }

    private static function allowed_country_codes() {
        return array_map('strtoupper', array_keys(self::shipping_countries()));
    }

    private static function cod_slug() {
        $fs = get_option('aieo_dmm_free_shipping', array());
        if (is_array($fs) && !empty($fs['cod_gateway_slug'])) {
            $slug = sanitize_key($fs['cod_gateway_slug']);
            if ($slug !== '') {
                return $slug;
            }
        }
        return 'cod';
    }

    
    public static function carrier_key($method_id, $title) {
        return $method_id . '|' . trim((string) $title);
    }

    
    public static function base_rate_id($rate_id) {
        $rate_id = (string) $rate_id;
        $colon = strpos($rate_id, ':');
        if ($colon === false) {
            return $rate_id;
        }
        $method = substr($rate_id, 0, $colon);
        $rest   = substr($rate_id, $colon + 1);
        if (preg_match('/^(\d+)/', $rest, $mm)) {
            return $method . ':' . $mm[1];
        }
        return $rate_id;
    }

    
    public static function discover_carriers() {
        $out = array();
        foreach (self::iterate_zone_methods() as $m) {
            if (method_exists($m, 'is_enabled') && !$m->is_enabled()) {
                continue; 
            }
            $iid = (int) (method_exists($m, 'get_instance_id') ? $m->get_instance_id() : 0);
            if ($iid <= 0) { continue; }
            $mid   = (string) $m->id;
            $title = method_exists($m, 'get_title') ? (string) $m->get_title() : '';
            if ($title === '') { $title = $mid; }
            $key = self::carrier_key($mid, $title);
            if (!isset($out[$key])) {
                $out[$key] = $title;
            }
        }
        return $out;
    }

    
    public static function blocked_rate_ids() {
        static $memo = null;
        if ($memo !== null) { return $memo; }

        $blocked_keys = self::get_blocked_methods();
        if (empty($blocked_keys)) { $memo = array(); return $memo; }

        $rate_ids = array();
        foreach (self::iterate_zone_methods() as $m) {
            $iid = (int) (method_exists($m, 'get_instance_id') ? $m->get_instance_id() : 0);
            if ($iid <= 0) { continue; }
            $mid   = (string) $m->id;
            $title = method_exists($m, 'get_title') ? (string) $m->get_title() : '';
            if ($title === '') { $title = $mid; }
            if (in_array(self::carrier_key($mid, $title), $blocked_keys, true)) {
                $rate_ids[] = $mid . ':' . $iid;
            }
        }
        $memo = array_values(array_unique($rate_ids));
        return $memo;
    }

    
    private static function iterate_zone_methods() {
        $methods = array();
        if (!class_exists('WC_Shipping_Zones')) { return $methods; }
        $zones = WC_Shipping_Zones::get_zones();
        foreach ($zones as $zone) {
            foreach ((isset($zone['shipping_methods']) ? $zone['shipping_methods'] : array()) as $m) {
                $methods[] = $m;
            }
        }
        $rest = WC_Shipping_Zones::get_zone(0);
        if ($rest) {
            foreach ($rest->get_shipping_methods(false) as $m) {
                $methods[] = $m;
            }
        }
        return $methods;
    }
}
