<?php

/**
 * Customizations for the online solution.
 *
 * @package northmill-online-shared
 */
declare (strict_types=1);
namespace Northmill_Online_Shared_Sync\Northmill_Online_Shared\Modules\Admin\Pages\Page\Admin_Sync_Settings;

use Northmill_Online_Shared_Sync\Northmill_Online_Shared\Abstract_Shared_Base;
use Northmill_Online_Shared_Sync\Northmill_Online_Shared\Modules\Sync\Orders\Models\Order_Base_Model;
use WC_Email;
use WC_Order;
use WC_Product;
use WP_Query;
defined('ABSPATH') || exit;
/**
 * Class Online_Solution_Customizations
 */
readonly class Online_Solution_Customizations
{
    /**
     * Constructor.
     *
     * @param Abstract_Online_Solution_Settings_Sync $syncer The syncer.
     */
    public function __construct(private Abstract_Online_Solution_Settings_Sync $syncer)
    {
        add_filter('woocommerce_order_number', array($this, 'filter_woocommerce_order_number'));
        add_filter('moreflo_sync_order_to_moreflo_order', array($this, 'filter_moreflo_order'), 10, 2);
        add_filter('nmf_sync_income_account_codes_api_payment_source_arg_1', array($this->syncer, 'get_settings_type_value'), 10, 0);
        add_filter('template_include', array($this, 'maybe_show_disabled_page'), 99);
        add_filter('woocommerce_email_format_string', array($this, 'custom_email_placeholders'), 10, 2);
        add_filter('the_title', array($this, 'wc_endpoint_view_order_title'), 20);
        add_filter('woocommerce_is_purchasable', array($this, 'woocommerce_is_purchasable'), 10, 2);
        add_action('pre_get_posts', array($this, 'pre_get_posts'));
        add_action('woocommerce_my_account_my_orders_column_order-number', array($this, 'wc_my_account_my_orders_column_order_number'));
    }
    /**
     * Filter the WooCommerce order number.
     *
     * @param int|string $order_id The order ID.
     *
     * @return string
     */
    public function filter_woocommerce_order_number(int|string $order_id): string
    {
        $prefix = $this->syncer->get_settings_type_value();
        if (!empty($prefix)) {
            $order_id = $prefix . '-' . $order_id;
        }
        return $order_id;
    }
    /**
     * Adds order info when transforming wc order to mf order
     *
     * @param array $mf_order Current order data to be sent to Hub.
     * @param int   $wc_order_id The WooCommerce order ID.
     *
     * @return array
     */
    public function filter_moreflo_order(array $mf_order, int $wc_order_id): array
    {
        $wc_order = wc_get_order($wc_order_id);
        if (isset($mf_order['State']) && 'Delivered' === $mf_order['State']) {
            if ('processing' === $wc_order->get_status()) {
                $mf_order['State'] = 'ReadyForHandOut';
            }
        }
        return $mf_order;
    }
    /**
     * Custom email placeholders.
     *
     * @param string   $email_string The email format string.
     * @param WC_Email $email        The email object.
     *
     * @return string
     */
    public function custom_email_placeholders(string $email_string, WC_Email $email): string
    {
        if (!is_a($email->object, 'WC_Order')) {
            return $email_string;
        }
        /**
         * Order for email.
         *
         * @var WC_Order $order
         */
        $placeholder = '{hub_order_id}';
        $order = $email->object;
        $order_model = new Order_Base_Model($order);
        $value = $order_model->get_hub_order_number();
        return is_null($value) ? $email_string : str_replace($placeholder, $value, $email_string);
    }
    /**
     * Maybe show the disabled page.
     * Hooked to `template_include` filter.
     *
     * @param string $template The template path.
     *
     * @return string
     */
    public function maybe_show_disabled_page(string $template): string
    {
        if ($this->syncer->get_settings_type() === Settings_Type::EXPRESS) {
            return $template;
            // Do not affect Express Order.
        }
        if ($this->syncer->get_settings_model()->is_enabled()) {
            return $template;
        }
        return Abstract_Shared_Base::base_instance()->package_info->paths->get_path() . 'online-shared/templates/online-solutions/disabled.php';
    }
    /**
     * Filter the title for the view order endpoint.
     *
     * @param string $title The title for the view order endpoint.
     *
     * @return string
     */
    public function wc_endpoint_view_order_title(string $title): string
    {
        global $wp;
        if ($this->syncer->get_settings_type() === Settings_Type::EXPRESS) {
            return $title;
            // Do not affect Express Order.
        }
        if (is_admin()) {
            return $title;
        }
        if (is_wc_endpoint_url('view-order') && is_main_query() && in_the_loop() && is_page()) {
            $order = wc_get_order($wp->query_vars['view-order']);
            if (!$order instanceof WC_Order) {
                return $title;
            }
            $order_model = new Order_Base_Model($order);
            $hub_order_number = $order_model->get_hub_order_number();
            if (!is_null($hub_order_number)) {
                // translators: %s is the order number.
                return sprintf(__('Order #%s', 'woocommerce'), $hub_order_number);
            }
        }
        return $title;
    }
    /**
     * Customizations for product purchasability.
     *
     * @param bool       $is_purchasable Whether the product is purchasable.
     * @param WC_Product $product        The product object.
     *
     * @return bool
     */
    public function woocommerce_is_purchasable(bool $is_purchasable, WC_Product $product): bool
    {
        switch ($this->syncer->get_settings_type()) {
            case Settings_Type::CATERING:
                // Has to be in a featured group.
                $settings_model = $this->syncer->get_settings_model();
                if (empty($settings_model->FeaturedGroups)) {
                    return \false;
                }
                $wp_group_ids = array_map(function ($featured_group) {
                    return $featured_group->get_wp_id();
                }, $settings_model->FeaturedGroups);
                if (empty(array_intersect($wp_group_ids, $product->get_category_ids()))) {
                    $is_purchasable = \false;
                }
                break;
            case Settings_Type::SELF_SCAN:
                // Has to have a valid bar code.
                $barcode = is_a($product, 'WC_Product_Variation') ? get_post_meta($product->get_parent_id(), '_custom_product_barcodes_field', \true) : get_post_meta($product->get_id(), '_custom_product_barcodes_field', \true);
                if (!$barcode) {
                    $is_purchasable = \false;
                }
                break;
            default:
                return $is_purchasable;
        }
        return $is_purchasable;
    }
    /**
     * Modify the main query for search results.
     *
     * @param WP_Query $query The WP_Query instance.
     */
    public function pre_get_posts(WP_Query $query): void
    {
        if (is_admin() || !$query->is_main_query() || !$query->is_search || Settings_Type::CATERING !== $this->syncer->get_settings_type()) {
            return;
        }
        // Has to be in a featured group.
        $settings_model = $this->syncer->get_settings_model();
        if (empty($settings_model->FeaturedGroups)) {
            return;
        }
        $wp_group_ids = array_map(function ($featured_group) {
            return $featured_group->get_wp_id();
        }, $settings_model->FeaturedGroups);
        $query->set('tax_query', array(array('taxonomy' => 'product_cat', 'terms' => $wp_group_ids, 'include_children' => \true, 'operator' => 'IN')));
    }
    /**
     * Display the Hub order number in the "My Orders" section.
     *
     * @param WC_Order $order The WooCommerce order object.
     */
    public function wc_my_account_my_orders_column_order_number(WC_Order $order): void
    {
        $order_model = new Order_Base_Model($order);
        $hub_order_number = $order_model->get_hub_order_number();
        if (!is_null($hub_order_number)) {
            echo '#' . esc_html($hub_order_number);
        }
    }
}
