<?php

namespace Rtc\PlantShopWC;

use Automattic\WooCommerce\Internal\DataStores\Orders\CustomOrdersTableController;
use Rtc\PlantShopWC\Admin\Controllers\GeneralSettingsController;
use Rtc\PlantShopWC\Admin\Controllers\LabelEditorController;
use Rtc\PlantShopWC\Admin\Controllers\ProductController;
use Rtc\PlantShopWC\Admin\Controllers\ProductListController;
use Rtc\PlantShopWC\Admin\Helpers\AjaxHelper;
use Rtc\PlantShopWC\Admin\Helpers\MiscHelper;
use Rtc\PlantShopWC\Admin\Models\GeneralSettingsModel;
use Rtc\PlantShopWC\Admin\Modules\BotanicalName;
use Rtc\PlantShopWC\Admin\Views\GeneralSettingsView;
use Rtc\PlantShopWC\Admin\Views\Partials\ProCta;
use Rtc\PlantShopWC\Emails\EmailService;
use Rtc\PlantShopWC\Frontend\Controllers\CartBlocksController;
use Rtc\PlantShopWC\Frontend\Controllers\CartController;
use Rtc\PlantShopWC\Frontend\Controllers\CheckoutBlocksController;
use Rtc\PlantShopWC\Frontend\Controllers\CheckoutClassicController;
use Rtc\PlantShopWC\Frontend\Controllers\SingleProductController;
use WC_Order;
class PlantShopWC {
    private const EMPTY_VALUE_DASH = '&mdash;';

    protected $settings_controller;

    protected $product_list_controller;

    protected $label_editor_controller;

    protected $product_controller;

    protected $single_product_controller;

    protected $cart_controller;

    protected $cart_blocks_controller;

    protected $checkout_blocks_controller;

    protected $checkout_classic_controller;

    protected $email_service;

    public function __construct() {
        $this->settings_controller = new GeneralSettingsController();
        $this->product_list_controller = new ProductListController();
    }

    // https://stackoverflow.com/a/77338767
    public static function imageToDataUrl( string $filename ) : string {
        if ( !file_exists( $filename ) ) {
            throw new Exception('File not found.');
        }
        $mime = mime_content_type( $filename );
        if ( $mime === false ) {
            throw new Exception('Illegal MIME type.');
        }
        // phpcs:ignore WordPress.WP.AlternativeFunctions.file_get_contents_file_get_contents -- reading a local file path to embed as data URI.
        $raw_data = file_get_contents( $filename );
        if ( empty( $raw_data ) ) {
            throw new Exception('File not readable or empty.');
        }
        // phpcs:ignore WordPress.PHP.DiscouragedPHPFunctions.obfuscation_base64_encode -- required for standards-compliant data URI generation.
        return "data:{$mime};base64," . base64_encode( $raw_data );
    }

    public function init() : void {
        add_action( 'woocommerce_init', array($this, 'plantshop_wc_init_emails'), 5 );
        add_filter(
            'woocommerce_order_item_name',
            array($this, 'plantshop_wc_order_email_products_title'),
            20,
            2
        );
        if ( is_admin() ) {
            $this->plantshop_wc_init_settings();
            new AjaxHelper();
            add_action( 'load-post.php', array($this, 'plantshop_wc_product') );
            add_action( 'load-post-new.php', array($this, 'plantshop_wc_product') );
            add_action( 'load-edit.php', array($this, 'plantshop_wc_product') );
            // Ensure order hooks are registered on both classic and HPOS order screens.
            // HPOS Orders list screen
            add_action( 'load-woocommerce_page_wc-orders', array($this, 'plantshop_wc_order') );
            // Classic order edit/list screens
            add_action( 'load-post.php', array($this, 'plantshop_wc_order') );
            add_action( 'load-post-new.php', array($this, 'plantshop_wc_order') );
            add_action( 'load-edit.php', array($this, 'plantshop_wc_order') );
        } else {
            $this->plantshop_wc_init_single_product();
            $this->plantshop_wc_init_cart();
            $this->plantshop_wc_init_cart_blocks();
            $this->plantshop_wc_init_checkout_blocks();
            $this->plantshop_wc_init_checkout_classic();
        }
    }

    private function plantshop_wc_init_settings() : void {
        $this->settings_controller->registerHooks();
        $this->product_list_controller->register_ajax_hooks();
    }

    private function plantshop_wc_init_single_product() : void {
        $this->single_product_controller = new SingleProductController();
        $this->single_product_controller->register_hooks();
    }

    private function plantshop_wc_init_cart() : void {
        $this->cart_controller = new CartController();
        $this->cart_controller->register_hooks();
    }

    private function plantshop_wc_init_cart_blocks() : void {
        $this->cart_blocks_controller = new CartBlocksController();
        $this->cart_blocks_controller->register_hooks();
    }

    private function plantshop_wc_init_checkout_blocks() : void {
        $this->checkout_blocks_controller = new CheckoutBlocksController();
        $this->checkout_blocks_controller->register_hooks();
    }

    private function plantshop_wc_init_checkout_classic() : void {
        $this->checkout_classic_controller = new CheckoutClassicController();
        $this->checkout_classic_controller->register_hooks();
    }

    public function plantshop_wc_init_emails() : void {
        $this->email_service = new EmailService();
        $this->email_service->register_hooks();
    }

    public function plantshop_wc_product() : void {
        $screen = get_current_screen();
        if ( !$screen || $screen->post_type !== 'product' ) {
            return;
        }
        if ( $screen->base === 'post' ) {
            $this->product_controller = new ProductController();
            $this->product_controller->register_hooks();
            return;
        }
        if ( $screen->base === 'edit' ) {
            $this->product_list_controller->register_hooks();
        }
    }

    private function plantshop_wc_echo_week( WC_Order $order ) : void {
        $code = (string) $order->get_meta( '_plantshop_shipping_week' );
        if ( $code === '' ) {
            echo wp_kses_post( self::EMPTY_VALUE_DASH );
            return;
        }
        $icon = '';
        $text = $code;
        if ( preg_match( '/^(\\d{4})-W(\\d{2})$/', $code, $m ) ) {
            $y = (int) $m[1];
            $w = (int) $m[2];
            // Determine status vs current ISO week
            $curY = (int) gmdate( 'o' );
            $curW = (int) gmdate( 'W' );
            if ( $y === $curY && $w === $curW ) {
                $icon = '<span title="' . esc_attr__( 'This is the current week', 'plantshop-wc' ) . '" aria-hidden="true" style="margin-right:4px;color:#d97706">&#9888;&#65039;</span>';
            } elseif ( $y < $curY || $y === $curY && $w < $curW ) {
                $icon = '<span title="' . esc_attr__( 'This week has already passed', 'plantshop-wc' ) . '" aria-hidden="true" style="margin-right:4px;color:#b91c1c">&#10071;</span>';
            }
            // translators: 1: ISO week number (zero-padded), 2: ISO year.
            $text = sprintf( __( 'W%1$02d %2$d', 'plantshop-wc' ), $w, $y );
        }
        // Output icon + text (escaped text, icon sanitized via kses)
        echo wp_kses_post( $icon ) . esc_html( $text );
    }

    private function plantshop_wc_echo_item_count( WC_Order $order ) : void {
        $count = (int) $order->get_item_count();
        if ( $count <= 0 ) {
            echo wp_kses_post( self::EMPTY_VALUE_DASH );
            return;
        }
        echo esc_html( (string) $count );
    }

    public function plantshop_wc_week_column( $columns ) {
        if ( !is_array( $columns ) ) {
            return $columns;
        }
        $new = array();
        foreach ( $columns as $key => $label ) {
            $new[$key] = $label;
            if ( $key === 'order_status' ) {
                $new['plantshop_item_count'] = __( 'Items', 'plantshop-wc' );
                $new['plantshop_week'] = __( 'Week', 'plantshop-wc' );
            }
        }
        if ( !isset( $new['plantshop_item_count'] ) ) {
            $new['plantshop_item_count'] = __( 'Items', 'plantshop-wc' );
        }
        if ( !isset( $new['plantshop_week'] ) ) {
            $new['plantshop_week'] = __( 'Week', 'plantshop-wc' );
        }
        return $new;
    }

    public function plantshop_wc_order() : void {
        add_action(
            'add_meta_boxes',
            function ( $post_type = null, $post = null ) {
                if ( !current_user_can( 'manage_woocommerce' ) ) {
                    return;
                }
                $screen = ( class_exists( '\\Automattic\\WooCommerce\\Internal\\DataStores\\Orders\\CustomOrdersTableController' ) && wc_get_container()->get( CustomOrdersTableController::class )->custom_orders_table_usage_is_enabled() ? wc_get_page_screen_id( 'shop-order' ) : 'shop_order' );
                // Always add the metabox; callback decides Free vs Pro rendering.
                add_meta_box(
                    'plantshop-wc_print_single_order_actions',
                    __( 'Label printing', 'plantshop-wc' ),
                    array($this, 'plantshop_wc_order_label_print_meta_box_content'),
                    $screen,
                    'side',
                    'high'
                );
            },
            10,
            2
        );
        add_action( 'woocommerce_admin_order_data_after_shipping_address', function ( $order ) {
            // Display and edit custom order meta next to the shipping address in admin.
            $opts = get_option( GeneralSettingsModel::get_option_key(), array() );
            $equiv_feat_enabled = isset( $opts['enable_equivalent_replacement'] ) && (string) $opts['enable_equivalent_replacement'] === '1';
            $enable_shipping_periods = isset( $opts['enable_shipping_periods'] ) && (string) $opts['enable_shipping_periods'] === '1';
            if ( $equiv_feat_enabled ) {
                $equiv_meta = $order->get_meta( '_plantshop_equivalent_replacement_consent' );
                $equiv_enabled = !empty( $equiv_meta );
            }
            if ( $enable_shipping_periods ) {
                // Helper to format a week code like 2025-W12 into a readable label.
                $format_week = static function ( ?string $code ) : string {
                    $code = (string) $code;
                    if ( $code !== '' && preg_match( '/^(\\d{4})-W(\\d{2})$/', $code, $m ) ) {
                        $y = (int) $m[1];
                        $w = (int) $m[2];
                        // translators: 1: ISO week number, 2: ISO year.
                        return sprintf( __( 'Week %1$d, %2$d', 'plantshop-wc' ), $w, $y ) . ' (' . $code . ')';
                    }
                    return $code;
                };
                $shipping_week_raw = (string) $order->get_meta( '_plantshop_shipping_week' );
                $shipping_week_label = ( $shipping_week_raw !== '' ? $format_week( $shipping_week_raw ) : '' );
            }
            // Readable (view) output.
            ?>
			<div class="plantshop-wc-order-fields">
				<div class="address">
					<?php 
            if ( $equiv_feat_enabled ) {
                ?>
						<p><?php 
                echo esc_html( __( 'Equivalent Replacement', 'plantshop-wc' ) ) . ': ' . esc_html( ( $equiv_enabled ? __( 'Yes', 'plantshop-wc' ) : __( 'No', 'plantshop-wc' ) ) );
                ?></p>
					<?php 
            }
            ?>
					<?php 
            if ( $enable_shipping_periods && $shipping_week_label !== '' ) {
                ?>
						<p><?php 
                echo esc_html( __( 'Desired shipping week', 'plantshop-wc' ) ) . ': ' . esc_html( $shipping_week_label );
                ?></p>
					<?php 
            }
            ?>
				</div>
				<div class="edit_address" style="display:none;">
					<?php 
            wp_nonce_field( 'plantshop_wc_save_order_meta', 'plantshop_wc_nonce' );
            ?>
					<?php 
            if ( $equiv_feat_enabled ) {
                ?>
						<p class="form-field form-field-wide">
							<label for="plantshop_equivalent_replacement_consent"><strong><?php 
                echo esc_html( __( 'Equivalent Replacement', 'plantshop-wc' ) );
                ?></strong></label>
							<input type="checkbox" class="!checkbox checkbox-primary align-middle mr-2" name="plantshop_equivalent_replacement_consent" id="plantshop_equivalent_replacement_consent" value="1" <?php 
                checked( $equiv_enabled );
                ?> />
							<span class="description"><?php 
                echo esc_html( __( 'Allow equivalent replacement if item is unavailable', 'plantshop-wc' ) );
                ?></span>
						</p>
						<?php 
            }
            if ( $enable_shipping_periods ) {
                ?>
					<p class="form-field form-field-wide">
						<label for="plantshop_shipping_week"><strong><?php 
                echo esc_html( __( 'Desired shipping week', 'plantshop-wc' ) );
                ?></strong></label>
						<input type="text" class="short" name="plantshop_shipping_week" id="plantshop_shipping_week" value="<?php 
                echo esc_attr( $shipping_week_raw );
                ?>" placeholder="YYYY-Wnn" />
						<span class="description"><?php 
                echo esc_html( __( 'Format: YYYY-Wnn (example: 2025-W12). Leave empty to clear.', 'plantshop-wc' ) );
                ?></span>
					</p>
					<?php 
            }
            ?>
				</div>
			</div>
				<?php 
        } );
        // Save our custom admin order fields.
        add_action(
            'woocommerce_process_shop_order_meta',
            function ( $order_id, $order ) {
                if ( !current_user_can( 'manage_woocommerce' ) ) {
                    return;
                }
                // phpcs:ignore WordPress.Security.NonceVerification.Missing -- Nonce verified if present; saving occurs within admin order save.
                if ( !isset( $_POST['plantshop_wc_nonce'] ) || !wp_verify_nonce( sanitize_text_field( wp_unslash( $_POST['plantshop_wc_nonce'] ) ), 'plantshop_wc_save_order_meta' ) ) {
                    return;
                }
                if ( !$order instanceof \WC_Order ) {
                    $order = wc_get_order( $order_id );
                }
                if ( !$order ) {
                    return;
                }
                $opts = get_option( GeneralSettingsModel::get_option_key(), array() );
                $enabled = isset( $opts['enable_equivalent_replacement'] ) && (string) $opts['enable_equivalent_replacement'] === '1';
                if ( $enabled ) {
                    // Equivalent replacement (checkbox)
                    $equiv = ( isset( $_POST['plantshop_equivalent_replacement_consent'] ) ? '1' : '' );
                    if ( $equiv !== '' ) {
                        $order->update_meta_data( '_plantshop_equivalent_replacement_consent', $equiv );
                    } else {
                        $order->delete_meta_data( '_plantshop_equivalent_replacement_consent' );
                    }
                }
                // Shipping week (text) — robust server-side ISO week validation, not via simple regex.
                $week_in = ( isset( $_POST['plantshop_shipping_week'] ) ? sanitize_text_field( wp_unslash( $_POST['plantshop_shipping_week'] ) ) : '' );
                $week_in = strtoupper( trim( $week_in ) );
                if ( $week_in !== '' ) {
                    // Accept input like YYYY-Wnn, YYYY-Wn or YYYYWnn and normalize to YYYY-Wnn.
                    if ( preg_match( '/^(\\d{4})-?W(\\d{1,2})$/', $week_in, $m ) ) {
                        $year = (int) $m[1];
                        $week = (int) $m[2];
                        if ( $year >= 1970 && $year <= 2100 && $week >= 1 && $week <= 53 ) {
                            try {
                                $dt = new \DateTime();
                                $dt->setISODate( $year, $week, 1 );
                                $valid = (int) $dt->format( 'o' ) === $year && (int) $dt->format( 'W' ) === $week;
                            } catch ( \Exception $e ) {
                                $valid = false;
                            }
                            if ( $valid ) {
                                $normalized = sprintf( '%04d-W%02d', $year, $week );
                                $order->update_meta_data( '_plantshop_shipping_week', $normalized );
                            } else {
                                // Invalid ISO week for the given year — clear the meta.
                                $order->delete_meta_data( '_plantshop_shipping_week' );
                            }
                        } else {
                            // Out of sane range — clear the meta.
                            $order->delete_meta_data( '_plantshop_shipping_week' );
                        }
                    } else {
                        // Not in a recognizable pattern — clear the meta.
                        $order->delete_meta_data( '_plantshop_shipping_week' );
                    }
                } else {
                    // Empty input — clear the meta.
                    $order->delete_meta_data( '_plantshop_shipping_week' );
                }
                $order->save();
            },
            40,
            2
        );
        // Add Week column to shop_order post type and HPOS
        add_filter( 'manage_edit-shop_order_columns', array($this, 'plantshop_wc_week_column'), 20 );
        add_filter( 'woocommerce_shop_order_list_table_columns', array($this, 'plantshop_wc_week_column'), 20 );
        add_action(
            'manage_shop_order_posts_custom_column',
            function ( $column, $post_id ) {
                if ( !in_array( $column, array('plantshop_week', 'plantshop_item_count'), true ) ) {
                    return;
                }
                $order = wc_get_order( $post_id );
                if ( !$order ) {
                    echo wp_kses_post( self::EMPTY_VALUE_DASH );
                    return;
                }
                if ( $column === 'plantshop_item_count' ) {
                    $this->plantshop_wc_echo_item_count( $order );
                    return;
                }
                $this->plantshop_wc_echo_week( $order );
            },
            10,
            2
        );
        add_action(
            'woocommerce_shop_order_list_table_custom_column',
            function ( $column, $order ) {
                if ( !in_array( $column, array('plantshop_week', 'plantshop_item_count'), true ) ) {
                    return;
                }
                if ( !$order instanceof \WC_Order ) {
                    echo wp_kses_post( self::EMPTY_VALUE_DASH );
                    return;
                }
                if ( $column === 'plantshop_item_count' ) {
                    $this->plantshop_wc_echo_item_count( $order );
                    return;
                }
                $this->plantshop_wc_echo_week( $order );
            },
            10,
            2
        );
        // Make Week column sortable (legacy posts table)
        add_filter( 'manage_edit-shop_order_sortable_columns', function ( $columns ) {
            if ( !is_array( $columns ) ) {
                return $columns;
            }
            $columns['plantshop_week'] = 'plantshop_week';
            return $columns;
        }, 20 );
        add_action( 'pre_get_posts', function ( $query ) {
            if ( !is_admin() || !$query->is_main_query() ) {
                return;
            }
            $pt = $query->get( 'post_type' );
            if ( $pt !== 'shop_order' ) {
                return;
            }
            $orderby = $query->get( 'orderby' );
            if ( $orderby === 'plantshop_week' ) {
                // phpcs:ignore WordPress.DB.SlowDBQuery.slow_db_query_meta_key -- Set only to enable sorting by stored meta in admin list.
                $query->set( 'meta_key', '_plantshop_shipping_week' );
                $query->set( 'orderby', 'meta_value' );
            }
        } );
        // Make Week column sortable for HPOS (custom orders table)
        add_filter( 'woocommerce_shop_order_list_table_sortable_columns', function ( $columns ) {
            if ( !is_array( $columns ) ) {
                return $columns;
            }
            $columns['plantshop_week'] = 'plantshop_week';
            return $columns;
        }, 20 );
        add_filter( 'woocommerce_shop_order_list_table_prepare_items_query_args', function ( $args ) {
            // phpcs:ignore WordPress.Security.NonceVerification.Recommended -- Reading 'orderby' from URL for admin list sorting; no state change.
            $orderby = ( isset( $_GET['orderby'] ) ? sanitize_text_field( wp_unslash( $_GET['orderby'] ) ) : '' );
            if ( $orderby === 'plantshop_week' ) {
                // phpcs:ignore WordPress.DB.SlowDBQuery.slow_db_query_meta_key -- Set only to enable sorting by stored meta in admin list.
                $args['meta_key'] = '_plantshop_shipping_week';
                $args['orderby'] = 'meta_value';
            }
            return $args;
        } );
        add_action( 'admin_enqueue_scripts', function () {
            // Only enqueue these assets on order screens (classic and HPOS).
            $screen = ( function_exists( 'get_current_screen' ) ? get_current_screen() : null );
            if ( !$screen ) {
                return;
            }
            $orders_screen_id = ( class_exists( '\\Automattic\\WooCommerce\\Internal\\DataStores\\Orders\\CustomOrdersTableController' ) && wc_get_container()->get( CustomOrdersTableController::class )->custom_orders_table_usage_is_enabled() ? wc_get_page_screen_id( 'shop-order' ) : 'shop_order' );
            $allowed_ids = array($orders_screen_id, 'shop_order', 'edit-shop_order');
            if ( !in_array( $screen->id, $allowed_ids, true ) ) {
                return;
            }
            wp_enqueue_style(
                'plantshop-wc-admin-tw',
                PLANTSHOP_WC_PUBLIC_URL . 'admin/css/tw.css',
                array(),
                PLANTSHOP_WC_PLUGIN_VERSION
            );
        } );
    }

    /**
     * Order metabox renderer (non-suffixed):
     * - In Pro: delegate to premium implementation.
     * - In Free: show a compact CTA banner to unlock Pro features.
     */
    public function plantshop_wc_order_label_print_meta_box_content( $order ) : void {
        try {
            if ( function_exists( 'plantshop_wc_fs' ) && \plantshop_wc_fs()->can_use_premium_code() ) {
                // Pro build: call the premium-only method (may be stripped in Free builds).
                if ( method_exists( $this, 'plantshop_wc_order_label_print_meta_box_content__premium_only' ) ) {
                    $this->plantshop_wc_order_label_print_meta_box_content__premium_only( wc_get_order( $order ) );
                    return;
                }
            }
        } catch ( \Throwable $e ) {
            // Swallow exception intentionally and fall through to CTA rendering.
            // Not logging here to avoid noisy errors in free builds.
            unset($e);
        }
        // Free build (or if premium method unavailable): render CTA banner.
        echo '<div id="plantshop-wc_print_box">';
        ProCta::render( array(
            'variant'      => 'inline',
            'feature_key'  => 'order_metabox',
            'title'        => __( 'Unlock label printing and templates', 'plantshop-wc' ),
            'button_label' => __( 'Get Pro', 'plantshop-wc' ),
            'icon'         => '🔒',
        ) );
        echo '</div>';
    }

    public function plantshop_wc_order_email_products_title( string $name, $item ) : string {
        if ( MiscHelper::is_email_context() || is_admin() ) {
            return $name;
        }
        $product = $item->get_product();
        if ( !$product || !GeneralSettingsModel::is_product_included( $product ) ) {
            return $name;
        }
        $botanical_name = new BotanicalName();
        if ( preg_match( '#^(<a[^>]*>)(.*?)(</a>)$#i', $name, $m ) ) {
            $inner = $botanical_name->build( $product, wp_strip_all_tags( $m[2] ), true );
            return $m[1] . $inner . $m[3];
        }
        return $botanical_name->build( $product, wp_strip_all_tags( $name ), true );
    }

}
