<?php
/**
 * VatFields.php
 *
 * @since      1.0.0
 * @author     alfiopiccione <alfio.piccione@gmail.com>
 * @license    http://opensource.org/licenses/gpl-2.0.php GPL v2
 *
 * Copyright (C) 2025 POP
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License
 * as published by the Free Software Foundation; either version 2
 * of the License, or (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
 */

namespace WcElectronInvoice\WooCommerce\Fields;

if (! defined('ABSPATH')) {
    exit; // Exit if accessed directly.
}

use WcElectronInvoice\Admin\Settings\OptionPage;
use WcElectronInvoice\Functions\nusoap_client as NuSoapClient;
use WcElectronInvoice\Integrations;
use WcElectronInvoice\InvoiceApi;
use WcElectronInvoice\PeppolApi;
use WcElectronInvoice\Plugin;
use WcElectronInvoice\Providers\OrderQuery;
use WcElectronInvoice\Utils\Countries;
use WcElectronInvoice\Utils\TimeZone;
use function WcElectronInvoice\Functions\disableInvoiceOnOrderTotalZero;
use function WcElectronInvoice\Functions\appendDocumentEndpointActions;
use function WcElectronInvoice\Functions\getRivalsaTotals;
use function WcElectronInvoice\Functions\resolveDocumentEndpointActionVisibility;
use function WcElectronInvoice\Functions\sanitize;
use function WcElectronInvoice\Functions\sanMarinoSupport;
use function WcElectronInvoice\Functions\setFormattedInvoiceNumber;

/**
 * Class InvoiceFields
 *
 * @since  1.0.0
 * @author alfiopiccione <alfio.piccione@gmail.com>
 */
final class InvoiceFields
{
    /**
     * List type
     *
     * @since 1.0.0
     */
    const LIST_TYPE = 'shop_order';

    /**
     * Meta Key
     *
     * @since 1.0.0
     *
     * @var string
     */
    public static $metaKey = 'billing_';

    /**
     * Option Key
     *
     * @since 1.0.0
     *
     * @var string
     */
    public static $optionKey = 'wc_el_inv-settings-';

    /**
     * Regex Tax Code
     *
     * @since 1.0.0
     *
     * @var string
     */
    public $regexCF = "/^([A-Z]{6}[0-9LMNPQRSTUV]{2}[ABCDEHLMPRST]{1}[0-9LMNPQRSTUV]{2}[A-Za-z]{1}[0-9LMNPQRSTUV]{3}[A-Z]{1})$/i";

    /**
     * Regex Web Service Code
     *
     * @since 1.0.0
     *
     * @var string
     */
    public $regexWEBSERV = "/^[a-zA-Z0-9]{7}$/i";

    /**
     * Regex PEC
     *
     * @since 1.0.0
     *
     * @var string
     */
    public $regexPEC = "/^(?:[a-z0-9!#$%&'*+\/=?^_`{|}~-]+(?:\.[a-z0-9!#$%&'*+\/=?^_`{|}~-]+)*|\"(?:[\x01-\x08\x0b\x0c\x0e-\x1f\x21\x23-\x5b\x5d-\x7f]|\\[\x01-\x09\x0b\x0c\x0e-\x7f])*\")@(?:\w*.?pec(?:.?\w+)*)$/i";

    /**
     * Regex Legal Mail
     *
     * @since 1.0.0
     *
     * @var string
     */
    public $regexLEGALMAIL = "/^(?:[a-z0-9!#$%&'*+\/=?^_`{|}~-]+(?:\.[a-z0-9!#$%&'*+\/=?^_`{|}~-]+)*|\"(?:[\x01-\x08\x0b\x0c\x0e-\x1f\x21\x23-\x5b\x5d-\x7f]|\\[\x01-\x09\x0b\x0c\x0e-\x7f])*\")@(?:\w*.?legalmail(?:.?\w+)*)$/i";

    /**
     * Regex VAT Code
     *
     * @since 1.0.0
     *
     * @var string
     */
    public $regexVAT = "/^(ATU[0-9]{8}|BE0[0-9]{9}|BG[0-9]{9,10}|CY[0-9]{8}L|CZ[0-9]{8,10}|DE[0-9]{9}|DK[0-9]{8}|EE[0-9]{9}|(EL|GR)[0-9]{9}|ES[0-9A-Z][0-9]{7}[0-9A-Z]|FI[0-9]{8}|FR[0-9A-Z]{2}[0-9]{9}|GB([0-9]{9}([0-9]{3})?|[A-Z]{2}[0-9]{13})|HU[0-9]{8}|IE[0-9][A-Z0-9][0-9]{5}[A-Z]{1,2}|IT[0-9]{11}|LT([0-9]{9}|[0-9]{12})|LU[0-9]{8}|LV[0-9]{11}|MT[0-9]{8}|NL[0-9]{9}B[0-9]{2}|PL[0-9]{10}|PT[0-9]{9}|RO[0-9]{2,10}|SE[0-9]{12}|SI[0-9]{8}|SK[0-9]{10})$/i";

    /**
     * EU VAT Country
     *
     * @since 1.0.0
     *
     * @var
     */
    public static $euVatCountry;

    /**
     * Billing Fields
     *
     * @since 1.0.0
     *
     * @var array
     */
    private $fields;

    /**
     * Billing Keys
     *
     * @since 1.0.0
     *
     * @var array
     */
    private $keys = array();

    /**
     * Options
     *
     * @since 1.0.0
     *
     * @var OptionPage
     */
    private $options;

    /**
     * Countries
     *
     * @since 1.0.0
     *
     * @var \WC_Countries
     */
    private $countries;

    /**
     * InvoiceFields constructor.
     *
     * @param array      $fields
     * @param OptionPage $options
     *
     * @since 1.0.0
     *
     */
    public function __construct(array $fields, OptionPage $options)
    {
        $this->fields = $fields;
        if (! empty($this->fields)) {
            foreach ($this->fields as $key => $field) {
                $this->keys[] = $key;
            }
        }

        $this->countries    = new Countries();
        self::$euVatCountry = $this->countries->get_european_union_countries();
        $this->options      = $options->getOptions();
    }

    /**
     * Front Address Billing Fields
     *
     * @param $fields
     *
     * @return mixed
     * @since 1.0.0
     *
     */
    public function billingAddressFields($fields)
    {
        $invoiceFields = array();

        /**
         * Filter Invoice Fields position
         *
         * 0   = first position - TOP
         * 150 = last position - BOTTOM
         */
        $fieldPos = OptionPage::init()->getOptions('billing_fields_position') ?: false;

        $position = 150; // default

        if ('top' === $fieldPos) {
            $position = 0;
        }

        $priority = apply_filters('billing_invoice_fields_priority', $position);

        if (! empty($this->fields)) {
            foreach ($this->fields as $key => $field) {
                $userCountry = get_user_meta(get_current_user_id(), 'billing_country', true);
                $country     = is_user_logged_in() ? $userCountry : $this->countries->get_base_country();
                $hideOutUe   = isset($this->options[self::$optionKey . 'hide_outside_ue']) ? $this->options[self::$optionKey . 'hide_outside_ue'] : null;

                // No UE remove SDI field.
                if ('IT' !== $country &&
                    in_array($country, self::$euVatCountry, true) &&
                    'sdi_type' === $field['id']
                ) {
                    continue;
                }

                // Hide the VAT number and tax code field (via JS)
                // Set not required
                if (! in_array($country, self::$euVatCountry, true) &&
                    '' !== $userCountry &&
                    'hide' === $hideOutUe
                ) {
                    $field['required'] = false;
                    $field['value']    = '';
                }

                if (is_array($field)) {
                    if (isset($field['label'])) {
                        $field['label'] = esc_html__($field['label'], WC_EL_INV_TEXTDOMAIN);
                    }
                    if (isset($field['description'])) {
                        $field['description'] = esc_html__($field['description'], WC_EL_INV_TEXTDOMAIN);
                    }
                    if (isset($field['placeholder'])) {
                        $field['placeholder'] = esc_html__($field['placeholder'], WC_EL_INV_TEXTDOMAIN);
                    }
                    if (isset($field['options'])) {
                        foreach ($field['options'] as $value => $label) {
                            $field['options'][$value] = esc_html__($label, WC_EL_INV_TEXTDOMAIN);
                        }
                    }

                    $invoiceFields[$key]             = $field;
                    $invoiceFields[$key]['priority'] = $priority++;
                }

                /**
                 * Filter Invoice Field position
                 */
                $invoiceFields = apply_filters("billing_invoice_field_args", $invoiceFields, $key);
            }
        }

        return array_merge((array)$fields, $invoiceFields);
    }

    /**
     * Admin User billing fields
     *
     * @param $fields
     *
     * @return mixed
     * @since 1.0.0
     *
     */
    public function customerFieldsFilter($fields)
    {
        global $pagenow;

        $isUserProfileScreen = is_admin() && in_array((string)$pagenow, ['profile.php', 'user-edit.php'], true);
        $globalSectionAnchor = '<a href="#pop-global-invoice-fields">' . esc_html__('Go to POP Invoice Fields section',
                WC_EL_INV_TEXTDOMAIN) . '</a>';
        $globalSectionNotice = '<span class="dashicons dashicons-info-outline" aria-hidden="true"></span> '
                               . esc_html__('This provider section is read-only in this screen.', WC_EL_INV_TEXTDOMAIN)
                               . ' ' . $globalSectionAnchor;
        if ($isUserProfileScreen) {
            $existingDescription = isset($fields['billing']['description']) ? (string)$fields['billing']['description'] : '';
            if (false === strpos($existingDescription, 'pop-global-invoice-fields')) {
                $fields['billing']['description'] = trim($existingDescription . ' ' . $globalSectionNotice);
            }
        }

        $isPeppolContext = self::isPeppolCheckoutContext();
        $isKsefContext   = self::isKsefCheckoutContext();
        if ($isPeppolContext || $isKsefContext) {
            unset($fields['billing']['fields']['billing_sdi_type']);
            unset($fields['billing']['fields']['billing_tax_code']);
        }
        if (! empty($this->fields)) {
            foreach ($this->fields as $key => $field) {
                if (($isPeppolContext || $isKsefContext) && in_array($key, ['billing_sdi_type', 'billing_tax_code'], true)) {
                    continue;
                }
                $field['class'] = implode(' ', $field['class']);

                if ($isUserProfileScreen) {
                    $field['required'] = false;
                    if (! isset($field['custom_attributes']) || ! is_array($field['custom_attributes'])) {
                        $field['custom_attributes'] = [];
                    }
                    $field['custom_attributes']['disabled'] = 'disabled';
                }

                $fields['billing']['fields'][$key] = $field;
            }
        }

        return $fields;
    }

    /**
     * Admin Order Edit billing fields
     *
     * @param $fields
     *
     * @return mixed
     * @since 1.0.0
     *
     */
    public function editBillingFieldsFilter($fields)
    {
        $isPeppolContext = self::isPeppolCheckoutContext();
        $isKsefContext   = self::isKsefCheckoutContext();
        if ($isPeppolContext || $isKsefContext) {
            unset($fields['sdi_type']);
            unset($fields['tax_code']);
        }
        // Choice type
        $page             = \WcElectronInvoice\Admin\Settings\OptionPage::init();
        $choiceTypeOption = $page->getOptions('invoice_choice_type');

        $order = wc_get_order();
        if ($order && ! is_wp_error($order)) {
            $choiceType           = $order->get_meta('_billing_choice_type');
            $removeValueIfReceipt = array(
                'sdi_type',
                'vat_number',
                'tax_code',
            );

            if (! empty($this->fields)) {
                $reverseChargeFields = array(
                    'nature_rc' => array(
                        'id'          => 'nature_rc',
                        'type'        => 'text',
                        'label'       => esc_html__('Operation\'s Nature', WC_EL_INV_TEXTDOMAIN),
                        'description' => '',
                        'placeholder' => '',
                    ),
                );

                if (ReverseChargeSettings::shouldDisplayRefNormRc()) {
                    $reverseChargeFields['ref_norm_rc'] = array(
                        'id'          => 'ref_norm_rc',
                        'type'        => 'text',
                        'label'       => esc_html__('Tax rule reference', WC_EL_INV_TEXTDOMAIN),
                        'description' => '',
                        'placeholder' => '',
                    );
                }

                $this->fields = array_merge($this->fields, $reverseChargeFields);

                foreach ($this->fields as $key => $field) {
                    if (! is_array($field)) {
                        continue;
                    }

                    if ('on' !== $choiceTypeOption) {
                        if ('billing_choice_type' === $key && isset($field['options']) && is_array($field['options'])) {
                            unset($field['options']['receipt']);
                        }
                    }

                    $key = str_replace('billing_', '', $key);
                    if (($isPeppolContext || $isKsefContext) && in_array($key, ['sdi_type', 'tax_code'], true)) {
                        continue;
                    }
                    unset($field['class']);

                    if ('ref_norm_rc' === $key && ! ReverseChargeSettings::shouldDisplayRefNormRc()) {
                        continue;
                    }

                    if ('nature_rc' === $key || 'ref_norm_rc' === $key) {
                        $ref            = "_{$key}";
                        $field['value'] = $order->get_meta($key);
                    } else {
                        $ref = "_billing_{$key}";
                    }

                    $field['wrapper_class'] = 'form-field-wide';
                    $field['show']          = false;
                    $field['id']            = "_billing_{$key}";
                    $field['name']          = "_billing_{$key}";

                    // Remove value if receipt is current choice
                    if ('receipt' === $choiceType && in_array($key, $removeValueIfReceipt)) {
                        $field['value'] = '';
                    }

                    $fields[$key] = $field;
                }
            }
        }

        return $fields;
    }

    /**
     * Render tax information in order details after billing address.
     * Works for both classic and block order confirmation flows.
     *
     * @param string    $addressType
     * @param \WC_Order $order
     *
     * @return void
     */
    public function renderTaxInformationAfterBillingAddress($addressType, $order)
    {
        if ('billing' !== $addressType) {
            return;
        }

        $wcOrderClass = \WcElectronInvoice\Functions\wcOrderClassName($order, '\WC_Order');
        if (! is_a($order, $wcOrderClass)) {
            return;
        }

        $html = $this->getTaxInformationHtml($order);
        if ('' === $html) {
            return;
        }

        // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
        echo $html;
    }

    /**
     * Appends tax information after the billing address order-confirmation block.
     *
     * @param string $blockContent
     * @param array  $block
     *
     * @return string
     */
    public function appendTaxInformationToOrderConfirmationBillingBlock($blockContent, $block)
    {
        if (! is_array($block) || empty($block['blockName']) || 'woocommerce/order-confirmation-billing-address' !== $block['blockName']) {
            return $blockContent;
        }

        $orderID = absint(get_query_var('order-received'));
        if (! $orderID) {
            return $blockContent;
        }

        $order = wc_get_order($orderID);
        if (! $order) {
            return $blockContent;
        }

        $html = $this->getTaxInformationHtml($order);
        if ('' === $html) {
            return $blockContent;
        }

        return $blockContent . $html;
    }

    /**
     * Render tax information section inside WooCommerce emails that show customer details.
     *
     * @param \WC_Order $order
     * @param bool      $sentToAdmin
     * @param bool      $plainText
     * @param mixed     $email
     *
     * @return void
     */
    public function renderTaxInformationInEmail($order, $sentToAdmin, $plainText, $email): void
    {
        $wcOrderClass = \WcElectronInvoice\Functions\wcOrderClassName($order, '\WC_Order');
        if (! is_a($order, $wcOrderClass)) {
            return;
        }

        $rows = $this->getTaxInformationRows($order);
        if (empty($rows)) {
            return;
        }

        if ($plainText) {
            $lines   = [];
            $lines[] = esc_html__('Tax information', WC_EL_INV_TEXTDOMAIN);
            foreach ($rows as $row) {
                $lines[] = $row['label'] . ': ' . $row['value'];
            }

            echo "\n" . implode("\n", $lines) . "\n";

            return;
        }

        $output = sprintf('<h2>%s</h2>', esc_html__('Tax information', WC_EL_INV_TEXTDOMAIN));
        $output .= '<div style="color: #636363; border: 1px solid #e5e5e5; padding: 12px;">';
        $output .= '<p>';
        foreach ($rows as $row) {
            $output .= sprintf(
                '<strong>%s:</strong> %s<br/>',
                esc_html($row['label']),
                esc_html($row['value'])
            );
        }
        $output .= '</p>';
        $output .= '</div>';

        // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
        echo $output;
    }

    /**
     * Build normalized tax information rows from order metadata.
     *
     * @param \WC_Order $order
     *
     * @return array<int,array{label:string,value:string}>
     */
    private function getTaxInformationRows($order): array
    {
        $invoiceType = (string)$this->getTaxMetaValue($order, 'invoice_type');
        $vatNumber   = (string)$this->getTaxMetaValue($order, 'vat_number');
        $taxCode     = (string)$this->getTaxMetaValue($order, 'tax_code');
        $sdiType     = (string)$this->getTaxMetaValue($order, 'sdi_type');

        $isPeppolContext = self::isPeppolCheckoutContext();
        $isKsefContext   = self::isKsefCheckoutContext();
        if ($isPeppolContext || $isKsefContext) {
            $sdiType = '';
        }

        $hasRequiredData = false;
        if ('private' === $invoiceType) {
            $hasRequiredData = '' !== trim($taxCode);
        } elseif (in_array($invoiceType, ['company', 'freelance'], true)) {
            $hasRequiredData = '' !== trim($vatNumber);
        }

        if (! $hasRequiredData) {
            return [];
        }

        $typeLabel = '';
        switch ($invoiceType) {
            case 'company':
                $typeLabel = esc_html__('Company', WC_EL_INV_TEXTDOMAIN);
                break;
            case 'freelance':
                $typeLabel = esc_html__('Freelance', WC_EL_INV_TEXTDOMAIN);
                break;
            case 'private':
                $typeLabel = esc_html__('Private person', WC_EL_INV_TEXTDOMAIN);
                break;
        }

        $rows = [];
        if ('' !== $typeLabel) {
            $rows[] = [
                'label' => esc_html__('Customer type', WC_EL_INV_TEXTDOMAIN),
                'value' => $typeLabel,
            ];
        }
        if ('' !== trim($vatNumber)) {
            $rows[] = [
                'label' => esc_html__('VAT number', WC_EL_INV_TEXTDOMAIN),
                'value' => $vatNumber,
            ];
        }
        if (! $isPeppolContext && ! $isKsefContext && '' !== trim($taxCode)) {
            $rows[] = [
                'label' => esc_html__('Tax Code', WC_EL_INV_TEXTDOMAIN),
                'value' => $taxCode,
            ];
        }
        if (! $isPeppolContext && ! $isKsefContext && '' !== trim($sdiType)) {
            $rows[] = [
                'label' => esc_html__('Certified e-mail (PEC) or the unique code', WC_EL_INV_TEXTDOMAIN),
                'value' => $sdiType,
            ];
        }

        return $rows;
    }

    /**
     * Returns the Tax information HTML block for an order.
     *
     * @param \WC_Order $order
     *
     * @return string
     */
    private function getTaxInformationHtml($order): string
    {
        $rows = $this->getTaxInformationRows($order);

        if (empty($rows)) {
            return '';
        }

        $output = sprintf('<p><strong>%s</strong></p>', esc_html__('Tax information', WC_EL_INV_TEXTDOMAIN));
        $output .= '<div class="wc-block-order-confirmation-billing-address wc_el_inv-tax-information">';
        foreach ($rows as $row) {
            $output .= sprintf(
                '<p><strong>%s</strong> %s</p>',
                esc_html($row['label']),
                esc_html($row['value'])
            );
        }
        $output .= '</div>';

        return $output;
    }

    /**
     * Returns tax field value with fallback to Woo Blocks additional fields storage.
     *
     * @param \WC_Order $order
     * @param string    $key
     *
     * @return string
     */
    private function getTaxMetaValue($order, $key): string
    {
        $value = (string)$this->getMeta($order, $key);
        if ('' !== trim($value)) {
            return $value;
        }

        $blockFieldKey = '_wc_other/pop/billing_' . $key;
        $fallback      = $order->get_meta($blockFieldKey, true);

        return is_string($fallback) ? $fallback : '';
    }

    /**
     * Hide POP tax fields from block "Additional fields" section to avoid duplicates.
     *
     * @param bool  $show
     * @param array $field
     *
     * @return bool
     */
    public function filterOrderConfirmationFields($show, $field)
    {
        if (! is_array($field) || empty($field['id'])) {
            return $show;
        }

        $fieldID = (string)$field['id'];
        if (0 === strpos($fieldID, 'pop/')) {
            $fieldID = substr($fieldID, 4);
        }

        if (in_array($fieldID, $this->keys, true)) {
            return false;
        }

        return $show;
    }

    /**
     * Front order actions
     *
     * @param $actions
     * @param $order
     *
     * @return mixed
     * @since 1.0.0
     *
     */
    public static function actionsFront($actions, $order)
    {
        // View invoice pdf link in my orders
        $myOrdersInvoice = OptionPage::init()->getOptions('invoice_in_my_orders');

        $key = OptionPage::getK();

        // No pdf if order is 0 zero
        if (0.00 === floatval($order->get_total())) {
            return $actions;
        }

        if (method_exists($order, 'get_status') &&
            'on' === $myOrdersInvoice &&
            'no' === apply_filters('wc_el_inv-disable_my_orders_pdf_invoice', 'no')
        ) {
            // FIC Addon.
            if (class_exists('WooPoPToFattureInCloud\Plugin')) {
                $actionsIsActive  = false;
                $ficInvoiceNumber = \WcElectronInvoice\Functions\getPostMeta('wfc-issued_invoice_number', null,
                    $order->get_id());
                if ($ficInvoiceNumber) {
                    $actionsIsActive = true;
                }
            } else {
                $actionsIsActive = true;
            }

            if ('completed' === $order->get_status() && $actionsIsActive) {
                $type  = $order->get_meta('_billing_choice_type') ?: 'invoice';
                $nonce = wp_create_nonce('wc_el_inv_pop_invoice');
                if ('invoice' === $type) {
                    $url                = esc_url_raw(add_query_arg([
                        'provider'    => 'woocommerce',
                        'key'         => $key,
                        'format'      => 'pdf',
                        'choice_type' => 'invoice',
                        'action'      => 'invoice_pdf',
                        'nonce'       => $nonce,
                        'v'           => time(),
                    ], rest_url('/pop-wp/v1/invoice/' . $order->get_id() . '/')));
                    $actions['invoice'] = array(
                        'url'  => $url,
                        'name' => apply_filters('wc_el_inv-invoice_my_account_button_text',
                            esc_html__('Invoice', WC_EL_INV_TEXTDOMAIN)
                        ),
                    );
                } elseif ('receipt' === $type) {
                    $url                = esc_url_raw(add_query_arg([
                        'order_id'    => $order->get_id(),
                        'provider'    => 'woocommerce',
                        'key'         => $key,
                        'format'      => 'pdf',
                        'choice_type' => 'receipt',
                        'action'      => 'receipt_pdf',
                        'nonce'       => $nonce,
                        'v'           => time(),
                    ], rest_url('/pop-wp/v1/invoice/' . $order->get_id() . '/')));
                    $actions['receipt'] = array(
                        'url'  => $url,
                        'name' => apply_filters('wc_el_inv-invoice_my_account_button_text',
                            esc_html__('Receipt', WC_EL_INV_TEXTDOMAIN)
                        ),
                    );
                }
            }
        }

        return $actions;
    }

    /**
     * Get Actions
     *
     * @param $id
     * @param $order
     * @param $docType
     *
     * @return string
     * @since 1.0.0
     *
     */
    public static function actions($id, $order, $docType = true)
    {
        // Get key
        $key    = OptionPage::getK();
        $output = '';
        $nonce  = wp_create_nonce('wc_el_inv_pop_invoice');

        // Check if invoice is sent
        $checkSent = \WcElectronInvoice\Functions\getPostMeta('_invoice_sent', null, $id);
        $checkSent = isset($checkSent) && 'sent' === $checkSent ? true : false;

        // Choice type
        $choiceTypeModifier = $order->get_meta('_billing_choice_type');
        $choiceTypeModifier = isset($choiceTypeModifier) ? esc_attr($choiceTypeModifier) : null;

        /**
         * Filter Check sent by Choice type modifier
         */
        $checkSent = apply_filters('wc_el_inv-actions_choice_type_modifier', $checkSent, $id, $choiceTypeModifier);

        $orderType = wc_get_order($id)->get_type();
        $output    .= '<div class="actions">';

        // Choice type
        $choiceTypeCheck = OptionPage::init()->getOptions('invoice_choice_type');
        $hiddenClass     = '';
        if ('on' !== $choiceTypeCheck) {
            $hiddenClass = 'hidden ';
        }

        $hiddenClassInvoiceReceiptInput = '';
        if ('shop_order_refund' === $orderType) {
            $hiddenClassInvoiceReceiptInput = 'hidden ';
        }

        $choiceType                = $order->get_meta('_billing_choice_type');
        $customerType              = $order->get_meta('_billing_invoice_type') ?: false;
        $shopCountry               = Integrations::getNormalizedShopCountry();
        $endpointActionsVisibility = resolveDocumentEndpointActionVisibility((string)$customerType, $shopCountry);

        if ((! class_exists('WooPoPToFattureInCloud\Plugin') &&
             ! class_exists('WooPoPToFattureAruba\Plugin'))
        ) {
            if (true === apply_filters('wc_el_inv-actions_doc_type_invoice', $docType)) {
                $output .= sprintf('<p class="nomarg %s"><strong>%s</strong></p>',
                    $hiddenClass,
                    esc_html__('Type of document to be created', WC_EL_INV_TEXTDOMAIN)
                );
                $output .= sprintf('<p class="' . $hiddenClass . 'doc-type-wrap">' .
                                   '<label for="doc_type_invoice-%1$s">%2$s ' .
                                   '<input class="doc-type-input" value="invoice" id="doc_type_invoice-%1$s" type="radio" name="doc_type-%1$s" %3$s></label>' .
                                   '<label class="' . $hiddenClassInvoiceReceiptInput . '" for="doc_type_receipt-%1$s">%4$s ' .
                                   '<input class="doc-type-input" value="receipt"  id="doc_type_receipt-%1$s" type="radio" name="doc_type-%1$s" %5$s></label>' .
                                   '</p>',
                    $id,
                    'shop_order' === $orderType ?
                        esc_html_x('Invoice', 'invoice_choice', WC_EL_INV_TEXTDOMAIN) :
                        esc_html_x('Refund', 'invoice_choice', WC_EL_INV_TEXTDOMAIN),
                    '' === $choiceType || 'invoice' === $choiceType || 'shop_order_refund' === $orderType ? 'checked' : '',
                    esc_html_x('Receipt', 'invoice_choice', WC_EL_INV_TEXTDOMAIN),
                    'receipt' === $choiceType && 'shop_order_refund' !== $orderType ? 'checked' : ''
                );
            }
        }
        $output .= sprintf('<input class="choice_type--current" type="hidden" value="%s">', $choiceType);

        if (true === apply_filters('wc_el_inv-actions_mark_trigger_invoice', true)) {
            $ajaxNonce = wp_create_nonce('wc_el_inv_ajax-ajax_nonce');
            if ($checkSent) {
                $urlUndo = esc_url_raw(add_query_arg([
                    self::LIST_TYPE => $id,
                    'id'            => $id,
                    'provider'      => 'woocommerce',
                    'undo'          => 'true',
                    'nonce'         => $ajaxNonce,
                ], site_url('/' . \WcElectronInvoice\EndPoint\Endpoints::ENDPOINT)));
                $output  .= sprintf(
                    '<a id="mark_as_sent-%1$s" class="mark_trigger mark_undo button button-secondary" href="%2$s" title="%3$s">' .
                    '<span class="dashicons dashicons-undo"></span></a>',
                    $id,
                    $urlUndo,
                    esc_html__('Undo', WC_EL_INV_TEXTDOMAIN)
                );
            } else {
                $urlSent = esc_url_raw(add_query_arg([
                    self::LIST_TYPE => $id,
                    'id'            => $id,
                    'provider'      => 'woocommerce',
                    'sent'          => 'true',
                    'nonce'         => $ajaxNonce,
                ], site_url('/' . \WcElectronInvoice\EndPoint\Endpoints::ENDPOINT)));
                $output  .= sprintf(
                    '<a id="mark_as_sent-%1$s" class="mark_trigger mark_as_sent button button-secondary" href="%2$s" title="%3$s">' .
                    '<span class="dashicons dashicons-yes"></span></a>',
                    $id,
                    true === $checkSent ? '' : $urlSent,
                    true === $checkSent ? esc_html__('Disabled', WC_EL_INV_TEXTDOMAIN) : esc_html__('Mark as Sent',
                        WC_EL_INV_TEXTDOMAIN)
                );
            }
        }

        $endpointActionUrls = [
            'xml'      => esc_url_raw(add_query_arg([
                self::LIST_TYPE => $id,
                'provider'      => 'woocommerce',
                'key'           => $key,
                'format'        => 'xml',
                'v'             => time(),
            ], site_url('/' . \WcElectronInvoice\EndPoint\Endpoints::ENDPOINT))),
            'xml_view' => esc_url_raw(add_query_arg([
                self::LIST_TYPE => $id,
                'provider'      => 'woocommerce',
                'key'           => $key,
                'format'        => 'xml',
                'view'          => 'true',
                'v'             => time(),
            ], site_url('/' . \WcElectronInvoice\EndPoint\Endpoints::ENDPOINT))),
            'xml_save' => esc_url_raw(add_query_arg([
                self::LIST_TYPE => $id,
                'provider'      => 'woocommerce',
                'key'           => $key,
                'format'        => 'xml',
                'save'          => 'true',
                'v'             => time(),
            ], site_url('/' . \WcElectronInvoice\EndPoint\Endpoints::ENDPOINT))),
            'pdf'      => esc_url_raw(add_query_arg([
                self::LIST_TYPE => $id,
                'provider'      => 'woocommerce',
                'key'           => $key,
                'format'        => 'pdf',
                'nonce'         => $nonce,
                'v'             => time(),
            ], site_url('/' . \WcElectronInvoice\EndPoint\Endpoints::ENDPOINT))),
            'zugferd'      => esc_url_raw(add_query_arg([
                self::LIST_TYPE => $id,
                'provider'      => 'woocommerce',
                'key'           => $key,
                'format'        => 'zugferd',
                'v'             => time(),
            ], site_url('/' . \WcElectronInvoice\EndPoint\Endpoints::ENDPOINT))),
            'zugferd_zip'  => esc_url_raw(add_query_arg([
                self::LIST_TYPE => $id,
                'provider'      => 'woocommerce',
                'key'           => $key,
                'format'        => 'zugferd_zip',
                'v'             => time(),
            ], site_url('/' . \WcElectronInvoice\EndPoint\Endpoints::ENDPOINT))),
        ];
        $output             = appendDocumentEndpointActions($output, $endpointActionUrls, $checkSent,
            $endpointActionsVisibility);

        $output .= '</div>';

        /**
         * Filter actions out put
         *
         * @since 1.0.0
         */
        return apply_filters('wc_el_inv-invoice_fields_actions', $output);
    }

    /**
     * Ajax Mark Invoice
     *
     * - Multi provider
     *
     * @return null
     * @since 2.0.0
     *
     */
    public function markInvoice()
    {
        if (! check_ajax_referer('wc_el_inv_ajax-ajax_nonce', 'nonce')) {
            return null;
        }

        if (! isset($_REQUEST) || false === wp_verify_nonce($_REQUEST['nonce'], 'wc_el_inv_ajax-ajax_nonce')) {
            return null;
        }

        if (defined('DOING_AJAX') && DOING_AJAX) {
            $urlParams = parse_url($_REQUEST['action_url']);
            $query     = isset($urlParams['query']) ? $urlParams['query'] : null;

            if (! $query) {
                return null;
            }

            $queryArgs = array();
            parse_str($query, $queryArgs);

            $provider = isset($queryArgs['provider']) ? sanitize_key((string)$queryArgs['provider']) : false;
            if (! $provider) {
                throw new \Exception('Provider not specified');
            }

            $orderID      = isset($queryArgs['id']) ? intval($queryArgs['id']) : 0;
            $shopOrderID  = isset($queryArgs['shop_order']) ? intval($queryArgs['shop_order']) : 0;
            $orderID      = $orderID ?: $shopOrderID;
            $documentType = isset($queryArgs['document_type']) ? sanitize_key((string)$queryArgs['document_type']) : 'shop_order';
            $parentId     = isset($queryArgs['parent_id']) ? intval($queryArgs['parent_id']) : 0;
            $isSentAction = isset($queryArgs['sent']) && 'true' === (string)$queryArgs['sent'];
            $isUndoAction = isset($queryArgs['undo']) && 'true' === (string)$queryArgs['undo'];

            $order = \WcElectronInvoice\Functions\resolveProviderDocument($orderID, $provider, $documentType,
                $parentId);
            if (! $order) {
                return null;
            }
            $checkSent = $order->get_invoice_sent($orderID);

            // Return if isset sent and action is sent
            if ('sent' === $checkSent &&
                $isSentAction
            ) {
                return null;
            }

            try {
                $timeZone = new TimeZone();
                $timeZone = new \DateTimeZone($timeZone->getTimeZone()->getName());
                $date     = new \DateTime('now');
                $date->setTimezone($timeZone);

                if ($isSentAction && 0 !== $orderID) {
                    $order->set_invoice_sent('sent');
                    $order->set_invoice_sent_timestamp($date->getTimestamp());
                } elseif ($isUndoAction && 0 !== $orderID) {
                    $uuidDocTypeMetaKey = $documentType === 'shop_order' ? 'invoice' : 'credit_note';
                    $order->set_invoice_sent('no_sent');
                    $order->set_invoice_sent_timestamp($date->getTimestamp());

                    $statusSdiViaPop = InvoiceApi::getSdiPOPIntegrationData();
                    if ($statusSdiViaPop->active_integration) {
                        // remove uuid and old notifications
                        $order->delete_meta(\WcElectronInvoice\Functions\buildUuidMetaKey('sdi_pop',
                            $uuidDocTypeMetaKey));
                        $order->delete_meta(\WcElectronInvoice\Functions\buildNotificationsMetaKey('sdi_pop',
                            $uuidDocTypeMetaKey));
                    }

                    $statusSdiViaPop = PeppolApi::getPEPPOLPOPIntegrationData();
                    if ($statusSdiViaPop->peppol_integration) {
                        // remove uuid
                        $order->delete_meta(\WcElectronInvoice\Functions\buildUuidMetaKey('peppol_pop',
                            $uuidDocTypeMetaKey));
                    }
                }

                // Save
                $order->save();
            } catch (\Exception $e) {
                echo esc_html__('Order Mark DateTime error: ', WC_EL_INV_TEXTDOMAIN) . esc_html__($e->getMessage());
            }
        }

        die();
    }

    /**
     * Invoice Number
     *
     * - Multi provider
     *
     * @param        $order
     * @param string $context null or "admin" for apply filter "wc_el_inv-list-table-invoice-number" used for FIC
     *                        numeration
     *
     * @return mixed|string|null
     * @throws \Exception
     */
    private function invoiceNumber($order, $context = null)
    {
        $options            = OptionPage::init();
        $wcOrderClass       = \WcElectronInvoice\Functions\wcOrderClassName($order, '\WC_Order');
        $wcOrderRefundClass = \WcElectronInvoice\Functions\wcOrderClassName($order, '\WC_Order_Refund');

        if ($order instanceof $wcOrderClass || $order instanceof $wcOrderRefundClass) {
            $order = OrderQuery::instance()->getProviderOrder($order->get_id(), 'woocommerce');
        }

        if (! is_subclass_of($order, '\WcElectronInvoice\Providers\Order') &&
            ! is_subclass_of($order, '\WcElectronInvoice\Providers\OrderRefund')
        ) {
            return '';
        }

        // Numeration type
        $numerationType = $order->get_meta('_billing_choice_type') ?: 'invoice';

        // Shop order number
        $number = $order->get_meta('order_number_invoice');

        if ('shop_order_refund' === $order->get_type()) {
            $parentOrder    = wc_get_order($order->get_parent_id());
            $numerationType = $parentOrder->get_meta('_billing_choice_type');
            $number         = $order->get_meta("refund_number_invoice-{$order->get_id()}");
            if ('receipt' === $numerationType) {
                $numerationType = 'credit_note_receipt';
            } else {
                $numerationType = 'credit_note';
            }
        }

        // Number of digits
        $digits = $options->getOptions('number_digits_in_invoice');
        $digits = isset($digits) && '' !== $digits ? $digits : 2;
        // Prefix
        $prefix = $options->getOptions("prefix_{$numerationType}_number");

        /**
         * Invoice prefix filter
         */
        $prefix = apply_filters("wc_el_inv-prefix_{$numerationType}", $prefix, $order);

        // Suffix
        $suffix           = $options->getOptions('suffix_invoice_number');
        $suffixYear       = $options->getOptions('suffix_year_invoice_number');
        $suffixYearFormat = $options->getOptions('suffix_year_format_invoice_number') ?: 'Y';
        if ('on' === $suffixYear) {
            if ('shop_order' === $order->get_type()) {
                $created = $order->has_status('completed') ? $order->get_date_completed() : $order->get_date_created();
            } else {
                $created = $order->get_date_created();
            }
            if (! $created instanceof \DateTimeInterface) {
                // fallback to now if we didn’t get a valid date object
                $created = new \DateTime();
            }
            $suffix = "/" . $created->format($suffixYearFormat);
        } else {
            $suffix = isset($suffix) && '' !== $suffix ? $suffix : '';
        }

        /**
         * Invoice suffix filter
         */
        $suffix = apply_filters('wc_el_inv-suffix_number', $suffix, $order);

        $formattedNumberMeta = "{$order->get_type()}_formatted_number_{$order->get_id()}";
        $formattedNumber     = $order->get_meta($formattedNumberMeta) ?? null;
        if ($formattedNumber) {
            $number = apply_filters('wc_el_inv-normalize_formatted_number', $formattedNumber, $order);
            // Update formatted if number invoice is numeric value
            if (is_numeric($number) && ($prefix || $suffix)) {
                $number = "{$prefix}{$number}{$suffix}";
            }
        } else {
            // Invoice number
            $invNumber = str_pad($number, $digits, '0', STR_PAD_LEFT);
            // Invoice number
            $number = isset($number) && 0 !== $number && '' !== $number ? "{$prefix}{$invNumber}{$suffix}" : '';
        }

        $is_backend_orders_list = is_admin() && (
                ($GLOBALS['pagenow'] === 'edit.php' && isset($_GET['post_type']) && $_GET['post_type'] === 'shop_order') ||
                ($GLOBALS['pagenow'] === 'admin.php' && isset($_GET['page']) && $_GET['page'] === 'wc-orders')
            );

        $number = apply_filters('wc_el_inv-invoice-number', $number, $order, $prefix);

        if ($number !== $formattedNumber && ! $is_backend_orders_list) {
            $order->update_meta($formattedNumberMeta, $number);
            $order->save();
        }

        if ('admin' === $context) {
            return apply_filters('wc_el_inv-list-table-invoice-number', $number, $order, $prefix);
        }

        return $number;
    }

    /**
     * Render admin invoice-number output without breaking trusted HTML returned by filters.
     *
     * @param mixed       $value
     * @param string|null $fallback
     *
     * @return string
     */
    private function invoiceNumberAdminDisplay($value, $fallback = null)
    {
        $value = is_scalar($value) ? (string)$value : '';

        if ($value !== wp_strip_all_tags($value)) {
            return $value;
        }

        if ($value !== '') {
            return esc_html($value);
        }

        return esc_html((string)($fallback ?? ''));
    }

    /**
     * Choice Type
     *
     * @param $item
     *
     * @return string
     */
    private function choiceType($order)
    {
        $orderType  = $order->get_type();
        $choiceType = $order->get_meta('_billing_choice_type');

        if ($orderType !== 'shop_order' && $orderType !== 'shop_order_refund') {
            $type = sprintf('<span style="color:green;" class="dashicons dashicons-media-text" title="%s"></span>',
                esc_html_x('Invoice', 'invoice_choice', WC_EL_INV_TEXTDOMAIN)
            );
        }

        switch ($choiceType) {
            case 'receipt':
                if ('shop_order_refund' === $orderType) {
                    $type = sprintf('<span style="color:red;" class="dashicons dashicons-media-text" title="%s"></span>',
                        esc_html_x('Refund', 'invoice_choice', WC_EL_INV_TEXTDOMAIN)
                    );
                } else {
                    $type = sprintf('<span style="color:dodgerblue;" class="dashicons dashicons-media-text" title="%s"></span>',
                        esc_html_x('Receipt', 'invoice_choice', WC_EL_INV_TEXTDOMAIN)
                    );
                }
                break;
            case 'invoice':
            case '':
                if ('shop_order' === $orderType) {
                    $type = sprintf('<span style="color:green;" class="dashicons dashicons-media-text" title="%s"></span>',
                        esc_html_x('Invoice', 'invoice_choice', WC_EL_INV_TEXTDOMAIN)
                    );
                } else {
                    $type = sprintf('<span style="color:red;" class="dashicons dashicons-media-text" title="%s"></span>',
                        esc_html_x('Refund', 'invoice_choice', WC_EL_INV_TEXTDOMAIN)
                    );
                }
                break;
            default:
                $type = sprintf('<span style="color:green;" class="dashicons dashicons-media-text" title="%s"></span>',
                    esc_html_x('Invoice', 'invoice_choice', WC_EL_INV_TEXTDOMAIN)
                );
                break;
        }

        return $type;
    }

    /**
     * General Invoice data option order
     *
     * @param $order \WC_Order
     * @param $fields
     * @param $docType
     *
     * @return void
     * @since 1.0.0
     *
     */
    public function editGeneralFieldsFilter($order, $fields = true, $docType = true)
    {
        $key = OptionPage::getK();
        if (\WcElectronInvoice\Functions\noKey($key)) {
            return;
        }

        $wcOrderClass = \WcElectronInvoice\Functions\wcOrderClassName($order, '\WC_Order');

        if (! is_a($order, $wcOrderClass)) {
            return;
        }

        $invoiceNumber = $order->get_meta('order_number_invoice') ?: false;
        $customerType  = $order->get_meta('_billing_invoice_type') ?: false;

        $noXmlViaSdi      = false;
        $sanMarinoSupport = sanMarinoSupport();
        if ('private' === $customerType && 'SM' === $sanMarinoSupport->shopCountry) {
            $noXmlViaSdi = true;
        }

        $shopCountry     = Integrations::getNormalizedShopCountry();
        $sdiActions      = Integrations::isSdiCountryContext($shopCountry);
        $isPeppolContext = self::isPeppolCheckoutContext();
        $isKsefContext   = self::isKsefCheckoutContext();
        if ('private' === $customerType && ($isPeppolContext || $isKsefContext)) {
            $noXmlViaSdi = true;
        }

        if (apply_filters('wc_el_inv-edit_order_disabled_invoice_fields',
            ('completed' !== $order->get_status() && 'processing' !== $order->get_status() && ! $invoiceNumber),
            $order)
        ) {
            return;
        }

        // No IT country return
        if (isset($order->billing['country']) && 'IT' !== $order->billing['country']) {
            return;
        }

        // Disable invoice order whit total zero
        if (disableInvoiceOnOrderTotalZero($order)) {
            return;
        }

        echo '<div class="wc_el_inv__general-order">';
        echo sprintf('<h3>%s %s</h3>',
            // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
            $this->choiceType($order),
            esc_html__('Document data', WC_EL_INV_TEXTDOMAIN)
        );

        // Get date completed
        $checkSent      = $order->get_meta("_invoice_sent");
        $dateCompleted  = $order->get_date_completed() !== null ? $order->get_date_completed() : $order->get_date_modified();
        $invoiceNumber  = $order->get_meta('order_number_invoice');
        $processingDate = $order->get_meta('_date_processing_set');
        if (
            $checkSent === 'sent' &&
            ! is_null($processingDate) &&
            $processingDate !== ''
        ) {
            $dateCompleted = new \DateTime($processingDate);
        }

        $number               = $this->invoiceNumber($order, 'admin');
        $invoiceNumberDisplay = $this->invoiceNumberAdminDisplay($number, $invoiceNumber);

        echo '<div class="wc_el_inv__general-order invoice-date">';
        // Saved data.
        echo sprintf(
            '<p class="wc_el_inv__general-order--text-data"><strong>%s:</strong> %s<br><strong>%s:</strong> %s</p>',
            esc_html__('Number', WC_EL_INV_TEXTDOMAIN),
            // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
            $invoiceNumberDisplay,
            esc_html__('Date', WC_EL_INV_TEXTDOMAIN),
            esc_html__($dateCompleted->format('Y-m-d - H:i'))
        );

        // Fields.
        if ($fields) {
            echo '<div class="wc_el_inv__general-order--hidden-fields">';
            woocommerce_wp_text_input(array(
                'label'             => esc_html__('Invoice number', WC_EL_INV_TEXTDOMAIN),
                'class'             => 'wc_el_inv-order_fields',
                'id'                => 'order_number_invoice',
                'name'              => 'order_number_invoice',
                'value'             => $invoiceNumber,
                'custom_attributes' => array(
                    'disabled' => 'disabled',
                ),
            ));
            // DatePicker scripts.
            wp_script_is('wc_el_inv_datepicker', 'registered') ? wp_enqueue_script('wc_el_inv_datepicker') : null;
            wp_script_is('datepicker-lang', 'registered') ? wp_enqueue_script('datepicker-lang') : null;
            echo sprintf('<p><label for="order_date_invoice">%s</label></p>',
                esc_html__('Invoice Date', WC_EL_INV_TEXTDOMAIN));
            woocommerce_wp_text_input(array(
                'label'             => '',
                'id'                => 'order_date_invoice',
                'class'             => 'wc_el_inv-order_fields wc_el_inv-datepicker',
                'name'              => 'order_date_invoice',
                'value'             => $dateCompleted->format('Y-m-d'),
                'custom_attributes' => array(
                    'disabled' => 'disabled',
                ),
            ));
            echo '<span class="hours">@</span>';
            woocommerce_wp_text_input(array(
                'label'             => '',
                'type'              => 'number',
                'class'             => 'wc_el_inv-order_fields',
                'id'                => 'order_hours_invoice',
                'name'              => 'order_hours_invoice',
                'value'             => $dateCompleted->format('H'),
                'custom_attributes' => array(
                    'disabled' => 'disabled',
                ),
            ));
            echo '<span class="minutes">:</span>';
            woocommerce_wp_text_input(array(
                'label'             => '',
                'type'              => 'number',
                'class'             => 'wc_el_inv-order_fields',
                'id'                => 'order_minutes_invoice',
                'name'              => 'order_minutes_invoice',
                'value'             => $dateCompleted->format('i'),
                'custom_attributes' => array(
                    'disabled' => 'disabled',
                ),
            ));
            echo '</div>';
        }

        // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
        echo self::actions($order->get_id(), $order, $docType);

        echo Integrations::appendConfiguredActions('', $order->get_id());
        echo '</div></div>';
    }

    /**
     * Edit refund invoice data
     *
     * @param $orderID
     *
     * @since 1.0.0
     *
     */
    public function editInvoiceDataOrderRefund($orderID)
    {
        $level = \WcElectronInvoice\Wizard::popGetUserLevel();
        if (! \WcElectronInvoice\Wizard::isUserLevelGte($level, 'basic')) {
            return;
        }

        $order = null;

        if (is_int($orderID)) {
            $order = wc_get_order($orderID);
        }

        // No It return
        if (isset($order->billing['country']) && 'IT' !== $order->billing['country']) {
            return;
        }

        $wcOrderClass = \WcElectronInvoice\Functions\wcOrderClassName($order, '\WC_Order');

        if (is_a($order, $wcOrderClass)) {

            // Get check order sent meta
            $checkOrderSent     = \WcElectronInvoice\Functions\getPostMeta('_invoice_sent', null, $order->get_id());
            $checkOrderSent     = isset($checkOrderSent) && 'sent' === $checkOrderSent ? true : false;
            $checkOrderSentTime = \WcElectronInvoice\Functions\getPostMeta('_invoice_sent_timestamp', null,
                $order->get_id());
            $checkOrderSentTime = isset($checkOrderSentTime) && '' !== $checkOrderSentTime ? $checkOrderSentTime : false;

            // Get Refunds
            $refunds = $order->get_refunds() ?: [];
            if (! empty($refunds)) {
                foreach ($refunds as $index => $refund) {
                    // Order refund
                    $wcOrderRefundClass = \WcElectronInvoice\Functions\wcOrderClassName($refund, '\WC_Order_Refund');
                    if (! $refund instanceof $wcOrderRefundClass) {
                        return;
                    }

                    // Get refund sent meta
                    $invoiceRefundSentTime = \WcElectronInvoice\Functions\getPostMeta('_invoice_sent_timestamp', null,
                        $refund->get_id());
                    $invoiceRefundSentTime = isset($invoiceRefundSentTime) && '' !== $invoiceRefundSentTime ? $invoiceRefundSentTime : false;
                    if ($checkOrderSent &&
                        $checkOrderSentTime &&
                        $invoiceRefundSentTime &&
                        (intval($checkOrderSentTime) > intval($invoiceRefundSentTime))
                    ) {
                        continue;
                    }

                    if (! $checkOrderSent) {
                        continue;
                    }

                    // Check Refund sent.
                    $refundSent = \WcElectronInvoice\Functions\getPostMeta('_invoice_sent', null, $refund->get_id());
                    if (count($refunds) > 1) {
                        $wcOrderRefundClass = ! empty($refunds[$index - 1]) ?
                            \WcElectronInvoice\Functions\wcOrderClassName($refunds[$index - 1], '\WC_Order_Refund') :
                            false;

                        if ('no_sent' === $refundSent && isset($refunds[$index - 1]) && $refunds[$index - 1] instanceof $wcOrderRefundClass) {
                            continue;
                        }
                    }

                    if (! $checkOrderSent && 0.00 === (abs($order->get_total()) - abs($refund->get_total()))) {
                        continue;
                    }

                    $refundID = $refund->get_id();
                    // Get date refund
                    $dateRefund    = $refund->get_date_created();
                    $invoiceNumber = $refund->get_meta("refund_number_invoice-{$refundID}");

                    $refundNumber = $this->invoiceNumber($refund, 'admin');

                    echo sprintf("<tr class='refund wc_el_inv__refund-invoice' data-order_refund_id='%s'>",
                        esc_html($refundID));
                    echo '<td class="thumb"><div></div></td>';
                    echo '<td colspan="7">';
                    echo sprintf('<h3>%s #%s</h3>', esc_html__('Refund', WC_EL_INV_TEXTDOMAIN), esc_html($refundID));
                    // Saved data.
                    echo sprintf(
                        '<p class="wc_el_inv__refund-invoice--text-data"><strong>%s:</strong> %s<br><strong>%s:</strong> %s</p>%s',
                        esc_html__('Number', WC_EL_INV_TEXTDOMAIN),
                        // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
                        $this->invoiceNumberAdminDisplay($refundNumber, $invoiceNumber),
                        esc_html__('Date', WC_EL_INV_TEXTDOMAIN),
                        esc_html($dateRefund->format('Y-m-d - H:i')),
                        // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
                        self::actions($refundID, $order)
                    );

                    // Fields.
                    echo '<div class="wc_el_inv__refund-invoice--hidden-fields">';
                    woocommerce_wp_text_input(array(
                        'label'             => esc_html__('Invoice number', WC_EL_INV_TEXTDOMAIN),
                        'class'             => 'wc_el_inv-order_fields',
                        'id'                => "refund_number_invoice-{$refundID}",
                        'name'              => "refund_number_invoice-{$refundID}",
                        'value'             => $invoiceNumber,
                        'custom_attributes' => array(
                            'disabled' => 'disabled',
                        ),

                    ));
                    echo sprintf('<p><label for="order_date_invoice">%s</label></p>',
                        esc_html__('Invoice Date', WC_EL_INV_TEXTDOMAIN));
                    woocommerce_wp_text_input(array(
                        'label'             => '',
                        'id'                => "refund_date_invoice-{$refundID}",
                        'class'             => 'wc_el_inv-order_fields wc_el_inv-datepicker',
                        'name'              => "refund_date_invoice-{$refundID}",
                        'value'             => $dateRefund->format('Y-m-d'),
                        'custom_attributes' => array(
                            'disabled' => 'disabled',
                        ),
                    ));
                    echo '<span class="hours">@</span>';
                    woocommerce_wp_text_input(array(
                        'label'             => '',
                        'type'              => 'number',
                        'class'             => 'wc_el_inv-order_fields',
                        'id'                => "refund_hours_invoice-{$refundID}",
                        'name'              => "refund_hours_invoice-{$refundID}",
                        'value'             => $dateRefund->format('H'),
                        'custom_attributes' => array(
                            'disabled' => 'disabled',
                        ),
                    ));
                    echo '<span class="minutes">:</span>';
                    woocommerce_wp_text_input(array(
                        'label'             => '',
                        'type'              => 'number',
                        'class'             => 'wc_el_inv-order_fields',
                        'id'                => "refund_minutes_invoice-{$refundID}",
                        'name'              => "refund_minutes_invoice-{$refundID}",
                        'value'             => $dateRefund->format('i'),
                        'custom_attributes' => array(
                            'disabled' => 'disabled',
                        ),
                    ));

                    echo '</td>';

                    do_action('wc_el_inv-after_refund_order_item_td', $refundID, 'woocommerce');

                    echo '</tr>';
                }
            }
        }
    }

    /**
     * Refunded payment method
     *
     * @param $orderID
     *
     * @since 1.0.0
     *
     */
    public function refundedPaymentMethod($orderID)
    {
        $order = null;

        if (is_int($orderID)) {
            $order = wc_get_order($orderID);
        }

        // No It return
        if (isset($order->billing['country']) && 'IT' !== $order->billing['country']) {
            return;
        }

        $wcOrderClass = \WcElectronInvoice\Functions\wcOrderClassName($order, '\WC_Order');
        if (is_a($order, $wcOrderClass)) {
            // Get Refunds
            $refunds = $order->get_refunds();

            if (! empty($refunds)) {

                $refundPayment = $order->get_meta('refund_payment_method');

                // Fields.
                echo '<tr class="wc_el_inv__refund-invoice--payment-fields">';
                echo sprintf('<td class="label refunded-total">%s</td>',
                    esc_html__('* Payment method', WC_EL_INV_TEXTDOMAIN)
                );
                echo '<td width="1%"></td><td class="total refunded-total">';
                woocommerce_wp_select(array(
                    'label'    => '',
                    'id'       => 'refund_payment_method',
                    'name'     => 'refund_payment_method',
                    'desc_tip' => false,
                    'value'    => $refundPayment,
                    'options'  => array(
                        ''     => esc_html__('Set payment method', WC_EL_INV_TEXTDOMAIN),
                        'MP01' => esc_html__('Cash', WC_EL_INV_TEXTDOMAIN),
                        'MP02' => esc_html__('Bank cheque', WC_EL_INV_TEXTDOMAIN),
                        'MP03' => esc_html__('Circular check', WC_EL_INV_TEXTDOMAIN),
                        'MP05' => esc_html__('Wire transfer', WC_EL_INV_TEXTDOMAIN),
                        'MP08' => esc_html__('Payment Card', WC_EL_INV_TEXTDOMAIN),
                    ),
                ));
                echo '</td></tr>';
            }
        }
    }

    /**
     * Admin Order view billing details
     *
     * @param $order
     *
     * @since 1.0.0
     *
     */
    public function viewBillingFieldsFilter($order)
    {
        $output          = $type = $viesMsg = '';
        $isPeppolContext = self::isPeppolCheckoutContext();
        $isKsefContext   = self::isKsefCheckoutContext();

        if (! empty($this->fields)) {
            foreach ($this->fields as $key => $field) {
                $key  = str_replace('billing_', '', $key);
                $meta = $this->getMeta($order, $key);

                if (($isPeppolContext || $isKsefContext) && in_array($key, ['sdi_type', 'tax_code'], true)) {
                    continue;
                }

                // Get custom meta
                if ('ref_norm_rc' === $key && ! ReverseChargeSettings::shouldDisplayRefNormRc()) {
                    continue;
                }

                if ('nature_rc' === $key || 'ref_norm_rc' === $key) {
                    $meta = $this->getMeta($order, $key, '', '');
                }

                if ('invoice_type' === $key && 'private' === $meta) {
                    $type = $meta;
                }

                if ('private' === $type && ('sdi_type' === $key || 'vat_number' === $key)) {
                    continue;
                }

                // empty SDI IT
                if ('sdi_type' === $key && '' === $meta) {
                    $meta = '0000000';
                    // empty SDI extra UE
                    if (! in_array($order->get_billing_country(), self::$euVatCountry, true)) {
                        $meta = 'XXXXXXX';
                    }
                }

                // Vies check message.
                $viesMsg = '';
                if (in_array($order->get_billing_country(), self::$euVatCountry, true) &&
                    'IT' !== $order->get_billing_country() && 'vat_number' === $key
                ) {
                    $invoiceViesCheck = TaxFields::getViesCheck();
                    $invoiceType      = $this->getMeta($order, 'invoice_type');
                    $vatNumber        = $this->getMeta($order, 'vat_number');
                    if ('yes' === $invoiceViesCheck && ('company' === $invoiceType || 'freelance' === $invoiceType)) {
                        $check          = self::viesCheck($vatNumber, $order->get_billing_country());
                        $orderViesCheck = $order->get_meta('order_vies_check') ?: false;
                        if ($check) {
                            $viesMsg = sprintf('<span style="color:green;"> %s </span>',
                                esc_html__('VIES validation: VAT is valid', WC_EL_INV_TEXTDOMAIN)
                            );
                        } elseif (false === $check || 'yes' !== $orderViesCheck) {
                            $viesMsg = sprintf('<span style="color:red;"> %s <a target="_blank" href="%s">%s</a></span>',
                                esc_html__('VIES validation: The VAT is not valid', WC_EL_INV_TEXTDOMAIN),
                                esc_url('http://ec.europa.eu/taxation_customs/vies/vatRequest.html'),
                                esc_html__('(see VIES)', WC_EL_INV_TEXTDOMAIN)
                            );
                        }
                    }
                }

                switch ($meta) {
                    case 'company':
                        $meta = esc_html__('Company', WC_EL_INV_TEXTDOMAIN);
                        break;
                    case 'freelance':
                        $meta = esc_html__('Freelance', WC_EL_INV_TEXTDOMAIN);
                        break;
                    case 'private':
                        $meta = esc_html__('Private person', WC_EL_INV_TEXTDOMAIN);
                        break;
                    case 'invoice':
                        $meta = esc_html_x('Invoice', 'invoice_choice', WC_EL_INV_TEXTDOMAIN);
                        break;
                    case 'receipt':
                        $meta = esc_html_x('Receipt', 'invoice_choice', WC_EL_INV_TEXTDOMAIN);
                        break;
                    default:
                        break;
                }

                // Remove value if receipt is current choice
                $choiceType           = $order->get_meta('_billing_choice_type');
                $removeValueIfReceipt = array(
                    'sdi_type',
                    'vat_number',
                    'tax_code',
                );
                if ('receipt' === $choiceType && in_array($key, $removeValueIfReceipt)) {
                    $meta = '';
                }

                // Set label for choice type
                if ('choice_type' === $key) {
                    $field['label'] = esc_html__('Type of document', WC_EL_INV_TEXTDOMAIN);
                }

                $output .= sprintf('<p><strong>%s:%s</strong><br>%s</p>',
                    $field['label'],
                    $viesMsg,
                    strtoupper($meta)
                );
            }

            // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
            echo $output;
        }
    }

    /**
     * Order Formatted Billing Address
     *
     * @param $fields
     * @param $order
     *
     * @return array
     * @since 1.0.0
     *
     */
    public function orderFormattedBillingAddress($fields, $order)
    {
        $extraFields     = array();
        $isPeppolContext = self::isPeppolCheckoutContext();
        $isKsefContext   = self::isKsefCheckoutContext();
        if (! empty($this->fields)) {
            foreach ($this->fields as $key => $field) {
                $key = str_replace('billing_', '', $key);
                if (($isPeppolContext || $isKsefContext) && in_array($key, ['sdi_type', 'tax_code'], true)) {
                    continue;
                }
                $extraFields[$key] = $this->getMeta($order, $key);
            }
        }

        $fields = array_merge($fields, $extraFields);

        return $fields;
    }

    /**
     * Front My Account Address
     *
     * @param $fields
     * @param $customerID
     * @param $type
     *
     * @return mixed
     * @since 1.0.0
     *
     */
    public function myAccountFormattedAddress($fields, $customerID, $type)
    {
        if ('shipping' === $type) {
            return $fields;
        }

        $isPeppolContext = self::isPeppolCheckoutContext();
        $isKsefContext   = self::isKsefCheckoutContext();
        if (! empty($this->fields)) {
            foreach ($this->fields as $key => $field) {
                $key = str_replace('billing_', '', $key);
                if (($isPeppolContext || $isKsefContext) && in_array($key, ['sdi_type', 'tax_code'], true)) {
                    continue;
                }
                if ($type == 'billing') {
                    $fields[$key] = get_user_meta($customerID, "billing_{$key}", true);
                }
            }
        }

        return $fields;
    }

    /**
     * Formatted Address Replacements
     *
     * @param $address
     * @param $args
     *
     * @return mixed
     * @since 1.0.0
     *
     */
    public function formattedAddressReplacements($address, $args)
    {
        $isPeppolContext = self::isPeppolCheckoutContext();
        $isKsefContext   = self::isKsefCheckoutContext();
        if (! empty($this->fields)) {
            foreach ($this->fields as $key => $field) {
                $key = str_replace('billing_', '', $key);

                if (($isPeppolContext || $isKsefContext) && in_array($key, ['sdi_type', 'tax_code'], true)) {
                    $address["{{$key}}"] = '';
                    continue;
                }

                $value = isset($args[$key]) ? $args[$key] : '';
                // Capitalized Invoice Type.
                if ('invoice_type' === $key && '' !== $value) {
                    $value = esc_html__(ucfirst(str_replace('-', ' ', $value)), WC_EL_INV_TEXTDOMAIN);
                }

                if ('private' === $value && ($key === 'vat_number' || $key === 'sdi_type')) {
                    $value = '';
                }

                if ('vat_number' === $key && '11111111111' === $value) {
                    $value = '';
                }

                if ('sdi_type' === $key && '1111111' === $value) {
                    $value = '';
                }

                if ('tax_code' === $key && 'XXXXXX00L00L000X' === $value) {
                    $value = '';
                }

                $address["{{$key}}"] = $value;
            }
        }

        if (! $isPeppolContext &&
            array_key_exists('sdi_type', $args) &&
            '' === $address["{sdi_type}"] &&
            ('' !== $address["{tax_code}"] || '' !== $address["{vat_number}"])
        ) {
            $address['{sdi_type}'] = "0000000";
        }

        if (isset($address["{choice_type}"])) {
            switch ($address["{choice_type}"]) {
                case 'invoice':
                    $address["{choice_type}"] = esc_html_x('Invoice', 'invoice_choice', WC_EL_INV_TEXTDOMAIN);
                    break;
                case 'receipt':
                    $address["{choice_type}"] = esc_html_x('Receipt', 'invoice_choice', WC_EL_INV_TEXTDOMAIN);
                    break;
                default:
                    $address["{choice_type}"] = '';
                    break;
            }
        }

        return $address;
    }

    /**
     * Localization Address Format
     *
     * @param $formats
     *
     * @return mixed
     * @since 1.0.0
     *
     */
    public function localisationAddressFormat($formats)
    {
        $isPeppolContext = self::isPeppolCheckoutContext();
        $isKsefContext   = self::isKsefCheckoutContext();
        $checkoutPageID  = wc_get_page_id('checkout');
        $post            = get_post($checkoutPageID);
        if ($post && ! empty($post->post_content)) {
            $checkoutBlock = has_block('woocommerce/checkout', $post->post_content);
            if ($checkoutBlock) {
                return $formats;
            }
        }

        foreach ($formats as $country => $value) {
            if ('IT' === $country) {
                if ($isPeppolContext || $isKsefContext) {
                    $formats[$country] = $value . "\n{invoice_type}\n{vat_number}";
                } else {
                    $formats[$country] = $value . "\n{invoice_type}\n{vat_number}\n{tax_code}\n{sdi_type}";
                }
            } elseif (in_array($country, self::$euVatCountry, true)) {
                $formats[$country] = $isPeppolContext || $isKsefContext ?
                    $value . "\n{invoice_type}\n{vat_number}" :
                    $value . "\n{invoice_type}\n{vat_number}\n{tax_code}";
            }
        }

        return $formats;
    }

    /**
     * Ajax Found Custom Meta
     *
     * @param $customerData
     * @param $customer
     * @param $userID
     *
     * @return mixed
     * @since 1.0.0
     *
     */
    public function foundCustomerMeta($customerData, $customer, $userID)
    {
        if (! empty($this->fields)) {
            foreach ($this->fields as $key => $field) {
                $billingKey                           = str_replace('billing_', '', $key);
                $value                                = get_user_meta($userID, $key, true);
                $customerData['billing'][$billingKey] = $value;
            }
        }

        return $customerData;
    }

    /**
     * Get Meta
     *
     * @param        $order
     * @param        $key
     * @param string $default
     *
     * @return mixed|string
     * @since 1.0.0
     *
     */
    private function getMeta($order, $key, $default = '', $prefix = "_billing_")
    {
        $value = $default;

        if ($order) {
            if (defined('WC_VERSION') && version_compare(\WC_VERSION, '2.7', '<')) {
                $value = get_post_meta($order->get_id(), "{$prefix}{$key}", true);
            } else {
                if (method_exists($order, 'get_meta')) {
                    $value = $order->get_meta("{$prefix}{$key}", true);
                }
            }

            $value = '' !== $value ? $value : $default;
        }

        return $value;
    }

    /**
     * Check VIES VAT
     *
     * @param string $vatCode
     * @param string $country
     * @param bool   $forceCheck
     *
     * @return bool
     */
    public static function viesCheck($vatCode, $country, bool $forceCheck = false)
    {
        $country = \WcElectronInvoice\Functions\normalizeViesCountryCode($country);

        // Vies check options
        $optionShouldCheckVies = TaxFields::getViesCheck();

        if ('yes' !== $optionShouldCheckVies) {
            return false;
        }

        // Woo only: if setting is set to NOT check vies and it's NOT forced, skip.
        $wooPageContext = self::isCheckout() || self::isAccountPage();

        if ($wooPageContext && 'yes' !== $optionShouldCheckVies && false === $forceCheck) {
            return false;
        }

        if ('yes' !== $optionShouldCheckVies && false === $forceCheck) {
            return false;
        }

        // If one of the required arguments is empty, return false
        if (! $vatCode && ! $country) {
            return false;
        }

        // Normalize args: remove country code from vatNumber
        $vatCode = \WcElectronInvoice\Functions\normalizeVatForVies($vatCode, $country);

        // Use validation cache, if available and not forced to re-validate
        $validationCacheKey = 'wc_el_inv-vies_' . $country . '_' . $vatCode;
        $retryCacheKey      = $validationCacheKey . '_retries';

        $validVatList = self::getViesValidVatList();
        $vatKey       = $country . '_' . $vatCode;
        $cacheHit     = self::getValidVatWhitelistCacheHit($validVatList, $vatKey, $forceCheck);

        if (! empty($cacheHit['updated'])) {
            update_option('wc_el_inv_valid_vat_list', $validVatList, false);
        }

        if (! empty($cacheHit['hit'])) {
            return true;
        }

        $alreadyValidated = get_transient($validationCacheKey);
        if (false === $forceCheck && $alreadyValidated !== false) {
            if ($alreadyValidated === true) {
                return true;
            }

            $retryCount = (int)get_transient($retryCacheKey);

            if ($retryCount >= 5) {
                return false;
            }

            set_transient($retryCacheKey, $retryCount + 1, HOUR_IN_SECONDS);
        }

        try {
            // If soap not exist include NuSoapClient
            if (! class_exists('SoapClient')) {
                include_once \WcElectronInvoice\Plugin::getPluginDirPath('/src/Functions/NuSoap.php');
                $client = new NuSoapClient("https://ec.europa.eu/taxation_customs/vies/checkVatService.wsdl", 'wsdl');

                if (function_exists('curl_exec')) {
                    $client->setUseCurl(true);
                }

                if ($client->getError()) {
                    return false;
                }
            } else {
                $client = new \SoapClient("https://ec.europa.eu/taxation_customs/vies/checkVatService.wsdl");
            }

            if (class_exists('SoapClient')) {
                /* @var $client \SoapClient */
                $response = $client->checkVat(array(
                    'countryCode' => $country,
                    'vatNumber'   => $vatCode,
                ));
            } else {
                /* @var $client NuSoapClient */
                $response = $client->call('checkVat', array(
                    'countryCode' => $country,
                    'vatNumber'   => $vatCode,
                ));

                // Convert NuSoapClient response array to object
                if (! is_object($response) && is_array($response) && ! empty($response)) {
                    $response = (object)$response;
                }
            }

            // Save validation result in cache
            $viesValidatedYepnope = is_object($response) && property_exists($response, 'valid') && $response->valid;
            $cacheDuration        = $viesValidatedYepnope ? DAY_IN_SECONDS : HOUR_IN_SECONDS;
            set_transient($validationCacheKey, $viesValidatedYepnope, $cacheDuration);

            if ($viesValidatedYepnope) {
                delete_transient($retryCacheKey);

                $validVatList[$vatKey] = self::buildViesValidVatCacheEntry();
                update_option('wc_el_inv_valid_vat_list', $validVatList, false);
            } else {
                if (isset($validVatList[$vatKey])) {
                    unset($validVatList[$vatKey]);
                    update_option('wc_el_inv_valid_vat_list', $validVatList, false);
                }

                set_transient($retryCacheKey, 0, $cacheDuration);
            }

            return $viesValidatedYepnope;
        } catch (\SoapFault $e) {
            $errorType = esc_html($e->getMessage());

            // Catch errors which worth to be logged for debugging
            // Skipping useless to be logged errors: INVALID_INPUT
            $string = '';
            if ($errorType === 'VAT_BLOCKED') {
                $string = sprintf(__('The VAT number (%1$s) entered is blocked', WC_EL_INV_TEXTDOMAIN), $vatCode);
            }

            if ($errorType === 'INVALID_INPUT') {
                $string = sprintf(__('The VAT number (%1$s) entered is not valid', WC_EL_INV_TEXTDOMAIN), $vatCode);
            }

            if (in_array($errorType, ['MS_UNAVAILABLE', 'SERVICE_UNAVAILABLE'])) {
                $string = sprintf(__('Your request cannot be processed due to unreachability of the Member State (%1$s) you are trying to reach. Please try again later.',
                    WC_EL_INV_TEXTDOMAIN), $country);
            }

            if ($errorType === 'MS_MAX_CONCURRENT_REQ') {
                $string = sprintf(__('Your request cannot be processed due to heavy traffic to the Member State (%1$s) you are trying to reach. Please try again later.',
                    WC_EL_INV_TEXTDOMAIN), $country);
            }

            if (! empty($string)) {
                $exception = (object)array(
                    'valid'          => false,
                    'message'        => esc_html($e->getMessage()),
                    'message_string' => $string,
                );

                // Use for debug
                set_transient('wc_el_inv-vies_exception_' . $country . '_' . $vatCode, $exception, WEEK_IN_SECONDS);

                return false;
            }
        } catch (\Exception $e) {
            // Catch any non-SoapFault errors to avoid fatals.
            error_log($e->getTraceAsString());
        }

        return false;
    }

    /**
     * Return the persisted list of VIES-valid VAT numbers without expired entries.
     *
     * @return array<string, mixed>
     */
    private static function getViesValidVatList(): array
    {
        $validVatList = get_option('wc_el_inv_valid_vat_list', []);

        if (! is_array($validVatList)) {
            return [];
        }

        $now = time();

        foreach ($validVatList as $vatKey => $cacheEntry) {
            if (true === $cacheEntry) {
                continue;
            }

            if (
                ! is_array($cacheEntry) ||
                empty($cacheEntry['valid']) ||
                empty($cacheEntry['expires_at']) ||
                (int)$cacheEntry['expires_at'] <= $now
            ) {
                unset($validVatList[$vatKey]);
            }
        }

        return $validVatList;
    }

    /**
     * Resolve positive-cache whitelist hit for a VIES VAT key.
     *
     * @param array<string, mixed> $validVatList
     * @param string               $vatKey
     * @param bool                 $forceCheck
     *
     * @return array{hit: bool, updated: bool}
     */
    private static function getValidVatWhitelistCacheHit(array &$validVatList, string $vatKey, bool $forceCheck): array
    {
        if (true === $forceCheck || ! isset($validVatList[$vatKey])) {
            return array(
                'hit'     => false,
                'updated' => false,
            );
        }

        $cacheEntry = $validVatList[$vatKey];

        if (true === $cacheEntry) {
            $validVatList[$vatKey] = self::buildViesValidVatCacheEntry();

            return array(
                'hit'     => true,
                'updated' => true,
            );
        }

        if (
            is_array($cacheEntry) &&
            ! empty($cacheEntry['valid']) &&
            ! empty($cacheEntry['expires_at']) &&
            (int)$cacheEntry['expires_at'] > time()
        ) {
            return array(
                'hit'     => true,
                'updated' => false,
            );
        }

        unset($validVatList[$vatKey]);

        return array(
            'hit'     => false,
            'updated' => true,
        );
    }

    /**
     * Build a VIES-valid VAT cache entry with explicit expiry.
     *
     * @return array<string, int|bool>
     */
    private static function buildViesValidVatCacheEntry(): array
    {
        $checkedAt = time();
        $ttl       = (int)apply_filters('wc_el_inv-vies_valid_vat_cache_ttl', WEEK_IN_SECONDS);

        if ($ttl <= 0) {
            $ttl = WEEK_IN_SECONDS;
        }

        return array(
            'valid'      => true,
            'checked_at' => $checkedAt,
            'expires_at' => $checkedAt + $ttl,
        );
    }

    /**
     * Reverse Charge actions
     * Allowed RC
     *
     * @return bool
     */
    public static function allowedCheckoutReverseCharge()
    {
        if (! TaxFields::isPremiumViesReverseChargeEnabled()) {
            return false;
        }

        // Reverse Charge (global active)
        $reverseChargeGlobalActive = TaxFields::getReverseChargeActiveGlobally();
        if ('yes' === $reverseChargeGlobalActive) {
            return true;
        }

        $allowedReverseCharge = true;
        $cart                 = WC()->cart;
        $contents             = $cart->get_cart_contents();
        if (! empty($contents)) {
            foreach ($contents as $key => $content) {
                $id            = $content['product_id'];
                $reverseCharge = \WcElectronInvoice\Functions\getPostMeta(
                    '_active_reverse_charge',
                    '',
                    $id
                );

                if ('' === $reverseCharge || 'no' === $reverseCharge) {
                    $allowedReverseCharge = false;
                    break;
                }
            }
        }

        return $allowedReverseCharge;
    }

    /**
     * Reverse Charge actions
     * RC tax class
     *
     * @return object
     */
    public static function rcTaxClass()
    {
        $taxClassName = TaxFields::getReverseChargeTaxClass();
        if (\WcElectronInvoice\Functions\isWooCommerceActive()) {
            $taxClass = \WC_Tax::get_rates_for_tax_class($taxClassName);
            if (is_array($taxClass) && ! empty($taxClass)) {
                return (object)array(
                    'taxClass'     => $taxClass,
                    'taxClassName' => $taxClassName,
                    'haveTax'      => true,
                );
            } else {
                return (object)array(
                    'taxClass'     => array(),
                    'taxClassName' => '',
                    'haveTax'      => false,
                );
            }
        }

        return (object)array(
            'taxClass'     => array(),
            'taxClassName' => '',
            'haveTax'      => false,
        );
    }

    /**
     * Reverse Charge actions
     * Add meta for Reverse Charge
     *
     * @param $item
     * @param $cartItemKey
     * @param $values
     * @param $order
     */
    public static function addMetaCartItemLine($item, $cartItemKey, $values, $order)
    {
        // Active vies control
        $invoiceViesCheck = TaxFields::getViesCheck();

        if ('yes' !== $invoiceViesCheck) {
            return;
        }

        $item = is_array($item) ? reset($item) : $item;
        if (! $item instanceof \WC_Order_Item_Product) {
            return;
        }

        /**
         * Return id not Allowed Reverse Charge
         */
        if (! self::allowedCheckoutReverseCharge()) {
            return;
        }

        // Reverse charge (product)
        $level = \WcElectronInvoice\Wizard::popGetUserLevel();
        if (in_array($level, ['free', 'basic'], true)) {
            return;
        }

        $reverseCharge = \WcElectronInvoice\Functions\getPostMeta(
            '_active_reverse_charge',
            '',
            $item->get_product_id()
        );

        // Reverse Charge (global active)
        $reverseChargeGlobalActive = TaxFields::getReverseChargeActiveGlobally();

        $checkout = new \WC_Checkout();
        $postData = $checkout->get_posted_data();

        // Customer type, vat number and country
        $customerVatNumber   = ! empty($postData['billing_vat_number']) ? $postData['billing_vat_number'] : null;
        $customerInvoiceType = ! empty($postData['billing_invoice_type']) ? $postData['billing_invoice_type'] : null;
        $customerCountry     = ! empty($postData['billing_country']) ? $postData['billing_country'] : null;
        $sanMarinoSupport    = sanMarinoSupport($customerInvoiceType, $customerCountry);

        // WC checkout block
        if (defined('REST_REQUEST') && REST_REQUEST && $order instanceof \WC_Order) {
            $customerVatNumber   = $order->get_meta('_billing_vat_number') ?: null;
            $customerInvoiceType = $order->get_meta('_billing_invoice_type') ?: null;
            $customerCountry     = $order->get_billing_country() ?: null;
        }

        if (! $customerCountry) {
            return;
        }

        // Country IT return no SM
        if ('SM' !== $sanMarinoSupport->shopCountry && 'IT' === $customerCountry) {
            return;
        }

        // Set prefix type used for retrieved nature or ref normative value
        $prefix = null;
        if (in_array($customerCountry, GeneralFields::getEuCountries(), true)) {
            $prefix = 'ue_';
        } elseif (! in_array($customerCountry, GeneralFields::getEuCountries(), true)) {
            $prefix = 'extra_ue_';
        }

        // Set type
        switch ($customerInvoiceType) {
            case 'company':
            case 'freelance':
                $type = 'company';
                break;
            default:
                $type = 'private';
                break;
        }

        if (! $prefix) {
            return;
        }

        // No vies check
        // Used for company and Ref. N7
        if ($customerVatNumber && in_array($customerInvoiceType, ['company', 'freelance'])) {
            $vies = self::viesCheck($customerVatNumber, $customerCountry, true);
            if (false === $vies) {
                $type = "{$type}_no_vies";
            }
        }

        $nature            = TaxFields::getReverseChargeNature("{$prefix}{$type}");
        $refNormative      = TaxFields::getReverseChargeRefNormative("{$prefix}{$type}");
        $refNormativeValue = esc_html($refNormative);

        if ('SM' === $sanMarinoSupport->shopCountry) {
            $nature            = $sanMarinoSupport->nature;
            $refNormativeValue = $sanMarinoSupport->refNormative;
        }

        $nature            = apply_filters('wc_el_inv-before_nature_rc_wc_save', $nature, $item, $order);
        $refNormativeValue = apply_filters('wc_el_inv-before_ref_norm_rc_wc_save', $refNormativeValue, $item, $order);

        // Add custom meta to line item
        // Reverse charge is available from the Basic plan.
        if ('free' === $level) {
            return;
        }

        if (('yes' === $reverseCharge || 'yes' === $reverseChargeGlobalActive) && $order instanceof \WC_Order) {
            if ('' !== $nature) {
                // Store order vies check meta
                if ('yes' === WC()->session->get('wc_session_order_vies_check')) {
                    $order->update_meta_data('order_vies_check', 'yes');
                } else {
                    $order->update_meta_data('order_vies_check', 'no');
                }

                $order->add_meta_data('nature_rc', $nature);
                if ('' !== $refNormativeValue) {
                    $order->add_meta_data('ref_norm_rc', $refNormativeValue);
                }
                // Unset vies check session data
                WC()->session->__unset('wc_session_order_vies_check');
                // Save
                $order->save();
            }
        }
    }

    /**
     * Reverse Charge actions
     * Vies Calc totals on checkout process.
     *
     * - If Vies control is ok remove tax on update checkout
     */
    private static function viesCalcTotals()
    {
        // @codingStandardsIgnoreLine
        $invoiceType = \WcElectronInvoice\Functions\filterInput(
            $_POST,
            self::$metaKey . 'invoice_type',
            FILTER_UNSAFE_RAW
        );

        // @codingStandardsIgnoreLine
        $country = \WcElectronInvoice\Functions\filterInput(
            $_POST,
            'billing_country',
            FILTER_UNSAFE_RAW
        );

        // @codingStandardsIgnoreLine
        $shippingCountry = \WcElectronInvoice\Functions\filterInput(
            $_POST,
            'shipping_country',
            FILTER_UNSAFE_RAW
        );

        $country             = self::resolveReverseChargeCountry($country, $shippingCountry);
        $allowExtraEuZeroTax = self::canApplyExtraEuZeroTax(WC()->cart ?? null);

        // No set nature return
        $nature = TaxFields::checkNature($country, $invoiceType);

        $sanMarinoSupport = sanMarinoSupport($invoiceType, $country);
        $nature           = $nature ?: $sanMarinoSupport->nature;

        if (! $nature) {
            return;
        }

        $isEuCountry      = in_array($country, self::$euVatCountry, true);
        $isExtraEuCountry = ! $isEuCountry;

        if ($isExtraEuCountry && ! $allowExtraEuZeroTax) {
            return;
        }

        // Active vies control
        $invoiceViesCheck = TaxFields::getViesCheck();
        if ('yes' !== $invoiceViesCheck) {
            return;
        }

        // Reverse Charge (global active)
        $reverseChargeGlobalActive = TaxFields::getReverseChargeActiveGlobally();

        $rcTaxClass = self::rcTaxClass();
        if (! $rcTaxClass->haveTax) {
            return;
        }

        /**
         * Allowed Reverse Charge
         */
        if (self::allowedCheckoutReverseCharge()) {
            // Tax object
            $taxObj       = end($rcTaxClass->taxClass);
            $taxClassName = $rcTaxClass->taxClassName;

            // Remove shipping
            add_action('woocommerce_package_rates',
                function ($rates, $package) use ($taxObj, $country, $allowExtraEuZeroTax) {
                    if (! $allowExtraEuZeroTax &&
                        ! in_array($country, \WcElectronInvoice\WooCommerce\Fields\GeneralFields::getEuCountries(),
                            true)
                    ) {
                        return $rates;
                    }

                    foreach ($rates as $rate) {
                        $rateTax = array();
                        $cost    = $rate->cost;
                        foreach ($rate->taxes as $key => $tax) {
                            $vat           = (($taxObj->tax_rate * 1));
                            $taxCost       = (floatval($cost) * $vat / 100);
                            $rateTax[$key] = $taxCost;
                        }
                        $rate->taxes = $rateTax;
                    }

                    return $rates;
                }, 2, PHP_INT_MAX
            );

            // Remove fee
            add_action('woocommerce_cart_totals_get_fees_from_cart_taxes',
                function ($feeTaxes, $fee, $instance) use ($taxObj, $country, $allowExtraEuZeroTax) {
                    if (! $allowExtraEuZeroTax &&
                        ! in_array($country, \WcElectronInvoice\WooCommerce\Fields\GeneralFields::getEuCountries(),
                            true)
                    ) {
                        return $feeTaxes;
                    }

                    $feeTaxes = array();

                    $amount     = floatval($fee->object->amount);
                    $vat        = (($taxObj->tax_rate * 1));
                    $taxCost    = (floatval($amount) * $vat);
                    $feeTaxes[] = floatval($taxCost);

                    return $feeTaxes;
                }, 3, PHP_INT_MAX
            );

            // Set product tax based on Reverse Charge
            add_filter('woocommerce_product_get_tax_class',
                function ($taxClass, $product) use (
                    $taxClassName,
                    $reverseChargeGlobalActive,
                    $country,
                    $allowExtraEuZeroTax
                ) {

                    // Reverse charge (product)
                    $reverseCharge = \WcElectronInvoice\Functions\getPostMeta(
                        '_active_reverse_charge',
                        '',
                        $product->get_id()
                    );

                    if (! $allowExtraEuZeroTax &&
                        ! in_array($country, \WcElectronInvoice\WooCommerce\Fields\GeneralFields::getEuCountries(),
                            true)
                    ) {
                        return $taxClass;
                    }

                    if ('yes' === $reverseCharge || 'yes' === $reverseChargeGlobalActive) {
                        $taxClass = $taxClassName;
                    }

                    return $taxClass;
                }, 2, PHP_INT_MAX
            );

            // Set product variation tax based on Reverse Charge
            add_filter('woocommerce_product_variation_get_tax_class',
                function ($taxClass, $product) use (
                    $taxClassName,
                    $reverseChargeGlobalActive,
                    $country,
                    $allowExtraEuZeroTax
                ) {

                    // Reverse charge (product)
                    $reverseCharge = \WcElectronInvoice\Functions\getPostMeta(
                        '_active_reverse_charge',
                        '',
                        $product->get_id()
                    );

                    if (! $allowExtraEuZeroTax &&
                        ! in_array($country, \WcElectronInvoice\WooCommerce\Fields\GeneralFields::getEuCountries(),
                            true)
                    ) {
                        return $taxClass;
                    }

                    if ('yes' === $reverseCharge || 'yes' === $reverseChargeGlobalActive) {
                        $taxClass = $taxClassName;
                    }

                    return $taxClass;
                }, 2, PHP_INT_MAX
            );
        }
    }

    /**
     * Reverse Charge actions
     * Remove tax from order on update checkout
     *
     * @param $postData
     *
     * @since 3.0.0
     */
    public static function removeTaxFromOrder($postData)
    {
        // Active vies control
        $invoiceViesCheck = TaxFields::getViesCheck();
        if ('yes' !== $invoiceViesCheck) {
            return;
        }

        // Reverse Charge (global active)
        $reverseChargeGlobalActive = TaxFields::getReverseChargeActiveGlobally();

        if ($postData instanceof \WC_Order) {
            // @hooked: woocommerce_store_api_checkout_update_order_from_request (store api checkout)
            $metas           = [
                '_billing_invoice_type' => $postData->get_meta('_billing_invoice_type'),
                '_billing_tax_code'     => $postData->get_meta('_billing_tax_code'),
                '_billing_vat_number'   => $postData->get_meta('_billing_vat_number'),
                '_billing_country'      => $postData->get_billing_country(),
                '_shipping_country'     => $postData->get_shipping_country(),
            ];
            $customerType    = $metas['_billing_invoice_type'];
            $taxCode         = $metas['_billing_tax_code'];
            $vatNumber       = $metas['_billing_vat_number'];
            $billingCountry  = $metas['_billing_country'];
            $shippingCountry = $metas['_shipping_country'];

            if (! empty($metas)) {
                foreach ($metas as $key => $value) {
                    WC()->session->set($key, $value);
                }
            }
        } elseif ($postData instanceof \WC_Cart) {
            // @hooked woocommerce_before_calculate_totals (store api checkout)
            $customerType    = WC()->session->get('_billing_invoice_type') ?? null;
            $taxCode         = WC()->session->get('_billing_tax_code') ?? null;
            $vatNumber       = WC()->session->get('_billing_vat_number') ?? null;
            $billingCountry  = WC()->session->get('_billing_country') ?: WC()->customer->get_billing_country();
            $shippingCountry = WC()->session->get('_shipping_country');
            if (! $shippingCountry && isset(WC()->customer) && method_exists(WC()->customer, 'get_shipping_country')) {
                $shippingCountry = WC()->customer->get_shipping_country();
            }
        } else {
            // @hooked: woocommerce_checkout_update_order_review (classic checkout)
            $data = array();
            parse_str($postData, $data);
            $taxCode         = isset($data['billing_tax_code']) && '' !== $data['billing_tax_code'] ? $data['billing_tax_code'] : null;
            $vatNumber       = isset($data['billing_vat_number']) && '' !== $data['billing_vat_number'] ? $data['billing_vat_number'] : null;
            $customerType    = isset($data['billing_invoice_type']) && '' !== $data['billing_invoice_type'] ? $data['billing_invoice_type'] : null;
            $billingCountry  = isset($data['billing_country']) && '' !== $data['billing_country'] ? $data['billing_country'] : null;
            $shippingCountry = isset($data['shipping_country']) && '' !== $data['shipping_country'] ? $data['shipping_country'] : null;
        }

        $country             = self::resolveReverseChargeCountry($billingCountry ?? null, $shippingCountry ?? null);
        $allowExtraEuZeroTax = self::canApplyExtraEuZeroTax($postData);

        // Vies validation and tax removal only occurs when the customer's country is
        // different from the seller's country e.g. (FR customer, IT seller)
        if (\WcElectronInvoice\WooCommerce\Fields\GeneralFields::getGeneralInvoiceOptionCountryState() === $country) {
            return;
        }

        $outsideUE = OptionPage::init()->getOptions('hide_outside_ue');
        // If outside the EU for the Reverse Charge the user is always considered as private
        if ('hide' === $outsideUE && ! $customerType) {
            $customerType = 'private';
        }

        // No set nature return
        $nature = TaxFields::checkNature($country, $customerType);

        $sanMarinoSupport = sanMarinoSupport($customerType, $country);
        $nature           = $nature ?: $sanMarinoSupport->nature;
        $noViesCheck      = $sanMarinoSupport->noViesCheck;

        if (! $nature) {
            return;
        }

        // Init clear vies check session data
        WC()->session->__unset('wc_session_order_vies_check');

        // Company or Private
        if ($customerType) {
            $viesCheck = false;
            if ($noViesCheck) {
                $viesCheck = true;
            } else {
                // Vies check
                if ($vatNumber && $country) {
                    $viesCheck = self::viesCheck($vatNumber, $country, true);
                }
            }

            $isEuCountry      = in_array($country, self::$euVatCountry, true);
            $isExtraEuCountry = ! $isEuCountry;

            // Remove taxes if:
            // 1. the checkout is an extra-EU shippable-goods flow, or
            // 2. the customer is an EU company/freelance and VIES validation may apply.
            if (($isExtraEuCountry && $allowExtraEuZeroTax) ||
                ($isEuCountry && 'private' !== $customerType)
            ) {

                $rcTaxClass = self::rcTaxClass();
                if (! $rcTaxClass->haveTax) {
                    return;
                }

                /**
                 * Allowed Reverse Charge
                 */
                if (self::allowedCheckoutReverseCharge()) {
                    // Store meta order vies check
                    WC()->session->set('wc_session_order_vies_check', 'yes');

                    // Tax object
                    $taxObj       = end($rcTaxClass->taxClass);
                    $taxClassName = $rcTaxClass->taxClassName;

                    // Remove shipping
                    add_action('woocommerce_package_rates',
                        function ($rates, $package) use ($taxObj, $country, $viesCheck, $allowExtraEuZeroTax) {

                            if ($viesCheck ||
                                ($allowExtraEuZeroTax &&
                                 ! in_array($country,
                                     \WcElectronInvoice\WooCommerce\Fields\GeneralFields::getEuCountries(), true))
                            ) {
                                foreach ($rates as $rate) {
                                    $rateTax = array();
                                    $cost    = $rate->cost;
                                    foreach ($rate->taxes as $key => $tax) {
                                        $vat           = (($taxObj->tax_rate * 1));
                                        $taxCost       = (floatval($cost) * $vat / 100);
                                        $rateTax[$key] = $taxCost;
                                    }
                                    $rate->taxes = $rateTax;
                                }
                            }

                            return $rates;
                        }, 2, PHP_INT_MAX
                    );

                    // Remove fee
                    add_action('woocommerce_cart_totals_get_fees_from_cart_taxes',
                        function ($feeTaxes, $fee, $instance) use (
                            $taxObj,
                            $country,
                            $viesCheck,
                            $allowExtraEuZeroTax
                        ) {
                            if ($viesCheck ||
                                ($allowExtraEuZeroTax &&
                                 ! in_array($country,
                                     \WcElectronInvoice\WooCommerce\Fields\GeneralFields::getEuCountries(), true))
                            ) {
                                $feeTaxes   = array();
                                $cost       = floatval($fee->object->amount);
                                $vat        = (($taxObj->tax_rate * 1));
                                $taxCost    = (floatval($cost) * $vat);
                                $feeTaxes[] = floatval($taxCost);
                            }

                            return $feeTaxes;
                        }, 3, PHP_INT_MAX
                    );

                    // Set product tax based on Reverse Charge
                    add_filter('woocommerce_product_get_tax_class',
                        function ($taxClass, $product) use (
                            $taxClassName,
                            $country,
                            $reverseChargeGlobalActive,
                            $viesCheck,
                            $allowExtraEuZeroTax
                        ) {

                            // Reverse charge (product)
                            $reverseCharge = \WcElectronInvoice\Functions\getPostMeta(
                                '_active_reverse_charge',
                                '',
                                $product->get_id()
                            );

                            if ($viesCheck ||
                                ($allowExtraEuZeroTax &&
                                 ! in_array($country,
                                     \WcElectronInvoice\WooCommerce\Fields\GeneralFields::getEuCountries(), true))
                            ) {
                                if ('yes' === $reverseCharge || 'yes' === $reverseChargeGlobalActive) {
                                    $taxClass = $taxClassName;
                                }
                            }

                            return $taxClass;
                        }, 2, PHP_INT_MAX
                    );

                    // Set product variation tax based on Reverse Charge
                    add_filter('woocommerce_product_variation_get_tax_class',
                        function ($taxClass, $product) use (
                            $taxClassName,
                            $country,
                            $reverseChargeGlobalActive,
                            $viesCheck,
                            $allowExtraEuZeroTax
                        ) {

                            // Reverse charge (product)
                            $reverseCharge = \WcElectronInvoice\Functions\getPostMeta(
                                '_active_reverse_charge',
                                '',
                                $product->get_id()
                            );

                            if ($viesCheck ||
                                ($allowExtraEuZeroTax &&
                                 ! in_array($country,
                                     \WcElectronInvoice\WooCommerce\Fields\GeneralFields::getEuCountries(), true))
                            ) {
                                if ('yes' === $reverseCharge || 'yes' === $reverseChargeGlobalActive) {
                                    $taxClass = $taxClassName;
                                }
                            }

                            return $taxClass;
                        }, 2, PHP_INT_MAX
                    );
                }

                // Set totals and add trigger element for view vies message
                add_filter('woocommerce_calculated_total',
                    function ($total, $instance) use (
                        $viesCheck,
                        $country,
                        $vatNumber,
                        $customerType,
                        $allowExtraEuZeroTax
                    ) {

                        // Cart total html
                        add_filter('woocommerce_cart_totals_order_total_html',
                            function ($value) use (
                                $viesCheck,
                                $country,
                                $vatNumber,
                                $customerType,
                                $allowExtraEuZeroTax
                            ) {
                                // Set class used from js script
                                if (true === $viesCheck) {
                                    $code = 'vies_tax';
                                } else {
                                    $code = 'not_valid';
                                    if (! $viesCheck && ! $vatNumber) {
                                        $code = "not_vies_check_for_{$customerType}";
                                    }
                                }

                                $countryClass = "country_{$country}";
                                if ($viesCheck ||
                                    ($allowExtraEuZeroTax &&
                                     ! in_array($country,
                                         \WcElectronInvoice\WooCommerce\Fields\GeneralFields::getEuCountries(), true))
                                ) {
                                    $abbr = sprintf("<abbr style='color:green;' title='%s'>(*) <span style='line-height:1.2;'><small>%s</small></span></abbr>",
                                        esc_html__('Reverse Charge', WC_EL_INV_TEXTDOMAIN),
                                        esc_html__('VAT tax 0 (Taxes Removed)', WC_EL_INV_TEXTDOMAIN)
                                    );

                                    return $value . "<span id='wc_el_inv_vies_trigger' class='{$code} {$countryClass}'>{$abbr}</span>";
                                }

                                return $value;
                            }, PHP_INT_MAX);

                        return $total;
                    }, PHP_INT_MAX, 2
                );

                // Vies validation and tax removal only occurs when the customer's country is
                // different from the seller's country e.g. (FR customer, IT seller)
                if (\WcElectronInvoice\WooCommerce\Fields\GeneralFields::getGeneralInvoiceOptionCountryState() === $country) {
                    if (! $viesCheck) {
                        WC()->customer->set_is_vat_exempt(false);
                    } else {
                        WC()->customer->set_is_vat_exempt(true);
                    }
                }
            }
        }

        if ($postData instanceof \WC_Order) {
            self::addMetaCartItemLine($postData->get_items(), null, null, $postData);
        }
    }

    /**
     * Resolve the country used for reverse-charge / export checkout checks.
     * Shipping takes priority for shippable goods; billing is the fallback.
     *
     * @param string|null $billingCountry
     * @param string|null $shippingCountry
     *
     * @return string
     */
    public static function resolveReverseChargeCountry(?string $billingCountry, ?string $shippingCountry): string
    {
        $shippingCountry = strtoupper(trim((string)$shippingCountry));
        $billingCountry  = strtoupper(trim((string)$billingCountry));

        return '' !== $shippingCountry ? $shippingCountry : $billingCountry;
    }

    /**
     * Return whether the current WooCommerce flow can use the extra-EU
     * zero-tax shortcut reserved for shipped goods exports.
     *
     * @param mixed $postData
     *
     * @return bool
     */
    public static function canApplyExtraEuZeroTax($postData): bool
    {
        if ($postData instanceof \WC_Order) {
            foreach ($postData->get_items() as $item) {
                if (! is_object($item) || ! method_exists($item, 'get_product')) {
                    continue;
                }

                $product = $item->get_product();
                if (is_object($product) && method_exists($product, 'needs_shipping') && $product->needs_shipping()) {
                    return true;
                }
            }

            return false;
        }

        if ($postData instanceof \WC_Cart) {
            return method_exists($postData, 'needs_shipping') ? (bool)$postData->needs_shipping() : false;
        }

        return isset(WC()->cart) && method_exists(WC()->cart,
            'needs_shipping') ? (bool)WC()->cart->needs_shipping() : false;
    }

    /**
     * addStampDutyFee
     *
     * @return void
     */
    public static function addStampDutyFee()
    {
        $addDuty          = OptionPage::init()->getOptions('add_stamp_duty');
        $paidCustomerDuty = OptionPage::init()->getOptions('stamp_duty_paid_customer');
        if ('on' === $addDuty && 'on' === $paidCustomerDuty) {
            $cartItems          = WC()->cart->get_cart();
            $cartTax            = WC()->cart->get_cart_tax();
            $totalsNoTaxProduct = 0;
            if (! empty($cartItems)) {
                // No tax product totals
                foreach ($cartItems as $item) {
                    if (floatval($item['line_tax']) === 0.00) {
                        $totalsNoTaxProduct += floatval($item['line_subtotal']);
                    }
                }
            }

            if (! wc_tax_enabled() ||
                floatval($cartTax) === 0.00 ||
                ($totalsNoTaxProduct > 0.00)
            ) {
                if (floatval($totalsNoTaxProduct) > floatval('77.47')) {
                    $stampDutyFeeName = apply_filters('wc_el_inv-stamp_duty_name', 'Imposta di Bollo');
                    WC()->cart->add_fee($stampDutyFeeName, 2, false, '');
                }
            }
        }
    }

    /**
     * addRivalsaInpsFee
     *
     * @return void
     */
    public static function addRivalsaInpsFee()
    {
        if ('RF19' === GeneralFields::getGeneralInvoiceOptionTaxRegime() ||
            'RF02' === GeneralFields::getGeneralInvoiceOptionTaxRegime()
        ) {
            $addRivalsa = OptionPage::init()->getOptions('add_rivalsa_inps');
            if ('on' === $addRivalsa) {
                $cartItems          = WC()->cart->get_cart();
                $cartTax            = WC()->cart->get_cart_tax();
                $totalsNoTaxProduct = 0;
                if (! empty($cartItems)) {
                    // No tax product totals
                    foreach ($cartItems as $item) {
                        if (floatval($item['line_tax']) === 0.00) {
                            $totalsNoTaxProduct += floatval($item['line_subtotal']);
                        }
                    }
                }

                if ($totalsNoTaxProduct > 0.00) {
                    $rivalsa        = $totalsNoTaxProduct * apply_filters('wc_el_inv-rivalsa_inps_aliquota', '0.04');
                    $rivalsaFeeName = apply_filters('wc_el_inv-rivalsa_inps_name', 'Rivalsa INPS');
                    WC()->cart->add_fee($rivalsaFeeName, $rivalsa, false, '');
                }
            }
        }
    }

    /**
     * Set custom order meta for check shipping to different address
     *
     * @param $orderID
     * @param $postedData
     * @param $order
     *
     * @return mixed
     * @since 2.0.3
     *
     */
    public function haveShippingAddress($orderID, $postedData, $order)
    {
        $wcOrderClass = \WcElectronInvoice\Functions\wcOrderClassName($order, '\WC_Order');

        if ($order instanceof $wcOrderClass) {
            $order->update_meta_data(
                '_ship_to_different_address',
                esc_attr($postedData['ship_to_different_address'])
            );

            // Save
            $order->save();
        }

        return $orderID;
    }

    /**
     * popCheckoutBlockValidation
     *
     * @return void
     */
    public static function popCheckoutBlockValidation($cartErrors, $cart)
    {
        $options         = OptionPage::init()->getOptions();
        $hideOutUe       = $options[self::$optionKey . 'hide_outside_ue'] ?? null;
        $userCountry     = get_user_meta(get_current_user_id(), 'billing_country', true);
        $disableTaxCode  = OptionPage::init()->getOptions('invoice_disable_cf');
        $required        = OptionPage::init()->getOptions('invoice_required');
        $disablePecSdi   = OptionPage::init()->getOptions('invoice_disable_pec_sdi');
        $isPeppolContext = self::isPeppolCheckoutContext();
        $isKsefContext   = self::isKsefCheckoutContext();
        if ($isPeppolContext || $isKsefContext) {
            $disablePecSdi  = 'on';
            $disableTaxCode = 'on';
        }

        $rawPost = file_get_contents('php://input');
        $data    = json_decode($rawPost, true);

        $checkoutFields = WC()->checkout()->get_checkout_fields();
        $billingCompany = isset($checkoutFields['billing']['billing_company']);

        if (! $data) {
            return;
        }

        $allCurrentData                = $data;
        $recalculateCheckoutTotalsHook = isset($_SERVER['HTTP_X_POP_RECALC_TOTALS']) &&
                                         (bool)$_SERVER['HTTP_X_POP_RECALC_TOTALS'];
        if (true === $recalculateCheckoutTotalsHook) {
            WC()->cart->calculate_totals();
        }

        $additionalFields = isset($data['additional_fields']) && is_array($data['additional_fields']) ?
            self::normalizeBlockAdditionalFields($data['additional_fields']) :
            [];
        if ($isPeppolContext || $isKsefContext) {
            $additionalFields['billing_sdi_type'] = '';
        }
        $billingFields = apply_filters('wc_el_inv-billing_fields', []);

        $instance  = new InvoiceFields($billingFields, OptionPage::init());
        $allFields = array_keys($billingFields);

        $submitValidation = array_key_exists('billing_address', $allCurrentData);

        $country = $allCurrentData['billing_address']['country'] ?? '';
        $company = $allCurrentData['billing_address']['company'] ?? '';

        $choiceType  = $additionalFields['billing_choice_type'] ?? null;
        $invoiceType = $additionalFields['billing_invoice_type'] ?? '';
        $vatCode     = $additionalFields['billing_vat_number'] ?? '';
        $taxCode     = $additionalFields['billing_tax_code'] ?? '';
        $sdiCode     = $additionalFields['billing_sdi_type'] ?? '';

        $vatWithCountry = $additionalFields['billing_vat_number_whit_country'] ?? '';
        if (! empty($additionalFields['billing_country'])) {
            $country = $additionalFields['billing_country'];
        } elseif (! empty($additionalFields['billing_vat_number_whit_country'])) {
            list($vatNumber, $countryVat) = explode('|', $vatWithCountry . '|');
            $country = $countryVat ?: '';
        }

        // No single validation (validate from JS)
        if (! $submitValidation) {
            return;
        }

        $isExtraEuCountry = ! empty($country) && ! in_array($country, self::$euVatCountry, true);

        // Extra-UE customers must never be blocked by POP fiscal required fields.
        if ($isExtraEuCountry) {
            return;
        }

        // Not required and not IT
        if ('IT' !== $country && 'required' !== $required) {
            return;
        }

        if ($isPeppolContext || $isKsefContext) {
            $taxCode                              = '';
            $additionalFields['billing_tax_code'] = '';
        }

        // Set missing fields
        $missingFields = [];
        foreach ($allFields as $field_id) {
            if (empty($additionalFields[$field_id])) {
                $missingFields[$field_id] = $additionalFields[$field_id] ?? null;
            }
        }

        if (! $choiceType) {
            unset($missingFields['billing_choice_type']);
        }

        if ('receipt' === $choiceType) {
            $missingFields = [];
        }

        if ('private' === $invoiceType) {
            unset($missingFields['billing_vat_number']);
            unset($missingFields['billing_sdi_type']);
            if ($isPeppolContext || $isKsefContext) {
                unset($missingFields['billing_tax_code']);
            }
        } elseif ('company' === $invoiceType || 'freelance' === $invoiceType) {
            if ('on' === $disableTaxCode) {
                unset($missingFields['billing_tax_code']);
            }
            if ('on' === $disablePecSdi || 'IT' !== $country) {
                unset($missingFields['billing_sdi_type']);
            }
        }

        if (! empty($missingFields)) {
            $cartErrors->add('missing_billing_fields',
                __('Fill in all required billing fields.', WC_EL_INV_TEXTDOMAIN)
            );
        }

        // If outside the EU for the Reverse Charge the user is always considered as private
        $invoiceViesCheck = TaxFields::getViesCheck();
        //var_dump($invoiceViesCheck);
        if ('yes' === $invoiceViesCheck &&
            ! in_array($country, self::$euVatCountry, true) &&
            'hide' === $hideOutUe &&
            ! $invoiceType
        ) {
            $invoiceType = 'private';
        }

        // No check if hide the VAT number and tax code field.
        if ('yes' !== $invoiceViesCheck &&
            ! in_array($country, self::$euVatCountry, true) &&
            'hide' === $hideOutUe &&
            '' !== $userCountry
        ) {
            return;
        }

        if (! empty($choiceType) && 'receipt' === $choiceType) {
            // Receipt
            return;
        } else {
            if (! empty($invoiceType) && 'private' === $invoiceType) {
                // It Private customer
                if ((! $isPeppolContext && ! $isKsefContext) && 'IT' === $country && $choiceType && 'receipt' !== $choiceType) {
                    if (! preg_match($instance->regexCF, $taxCode)) {
                        $code = strtoupper($taxCode);
                        $cartErrors->add(self::$metaKey . 'tax_code',
                            sprintf(
                                __('Tax ID Number %1$s is not correct', WC_EL_INV_TEXTDOMAIN),
                                "<strong>{$code}</strong>"
                            ),
                            array('id' => self::$metaKey . 'tax_code')
                        );
                    }
                }
            } elseif (! empty($invoiceType) && 'company' === $invoiceType || 'freelance' === $invoiceType) {
                // Company/Freelance IT
                if ('IT' === $country) {
                    // Definition of VAT Number Length
                    $vatCodeLength = isset($vatCode) ? strlen($vatCode) : 0;

                    if ($billingCompany && 'company' === $invoiceType && '' === $company) {
                        $cartErrors->add('billing_company',
                            sprintf('<strong>%s</strong> %s',
                                __('Name of the company', WC_EL_INV_TEXTDOMAIN),
                                __('it is a required field.', WC_EL_INV_TEXTDOMAIN)
                            ),
                            array('id' => self::$metaKey . 'company')
                        );
                    }

                    // VAT Check for Businesses and Freelancers
                    if (! preg_match($instance->regexVAT,
                            $country . $vatCode) || ! ctype_digit($vatCode) || $vatCodeLength !== 11) {
                        $cartErrors->add(self::$metaKey . 'vat_number',
                            sprintf(
                                __('VAT number %1$s is not correct', WC_EL_INV_TEXTDOMAIN),
                                "<strong>{$country}-{$vatCode}</strong>"
                            ),
                            array('id' => self::$metaKey . 'vat_number')
                        );
                    }

                    // Tax Code / VAT Number Check for Companies
                    if ('company' === $invoiceType) {
                        $isVATValid        = preg_match($instance->regexVAT, $country . $taxCode);
                        $isCFOrAssociation = ctype_digit($taxCode) && strlen($taxCode) === 11; // CF di un'associazione o azienda

                        if ('on' !== $disableTaxCode) {
                            if (! $isCFOrAssociation) {
                                // Invalid company/association CF
                                $cartErrors->add(self::$metaKey . 'tax_code',
                                    sprintf(
                                        __('TAX code %1$s is not correct', WC_EL_INV_TEXTDOMAIN),
                                        "<strong>" . strtoupper($taxCode) . "</strong>"
                                    ),
                                    array('id' => self::$metaKey . 'tax_code')
                                );
                            } elseif ($taxCode === $vatCode && ! $isVATValid) {
                                // If the CF and VAT number match, I check that it is a valid VAT number
                                $cartErrors->add(self::$metaKey . 'tax_code',
                                    sprintf(
                                        __('TAX code %1$s is not correct', WC_EL_INV_TEXTDOMAIN),
                                        "<strong>" . strtoupper($taxCode) . "</strong>"
                                    ),
                                    array('id' => self::$metaKey . 'tax_code')
                                );
                            }
                        }
                    }

                    // Tax Code Check for Freelancers
                    if ('freelance' === $invoiceType) {
                        if ('on' !== $disableTaxCode && ! preg_match($instance->regexCF, $taxCode)) {
                            $cartErrors->add(self::$metaKey . 'tax_code',
                                sprintf(
                                    __('TAX code %1$s is not correct', WC_EL_INV_TEXTDOMAIN),
                                    "<strong>" . strtoupper($taxCode) . "</strong>"
                                ),
                                array('id' => self::$metaKey . 'tax_code')
                            );
                        }
                    }

                    // Check PEC Email or SDI Recipient Code
                    if ((! $isPeppolContext && ! $isKsefContext) && ! empty($sdiCode)) {
                        $isValidSDI = preg_match($instance->regexPEC, $sdiCode) ||
                                      preg_match($instance->regexLEGALMAIL, $sdiCode) ||
                                      preg_match($instance->regexWEBSERV, $sdiCode);

                        if (! $isValidSDI) {
                            $cartErrors->add(self::$metaKey . 'sdi_type',
                                sprintf(
                                    __('E-mail (PEC) or Unique Code %1$s is not correct', WC_EL_INV_TEXTDOMAIN),
                                    "<strong>{$sdiCode}</strong>"
                                ),
                                array('id' => self::$metaKey . 'sdi_type')
                            );
                        }
                    } elseif ((! $isPeppolContext && ! $isKsefContext) && 'off' === $disablePecSdi) {
                        $cartErrors->add(self::$metaKey . 'sdi_type',
                            __('E-mail (PEC) or Unique Code is required', WC_EL_INV_TEXTDOMAIN),
                            array('id' => self::$metaKey . 'sdi_type')
                        );
                    }
                }
            }

            // EU Country VAT check
            if ('IT' !== $country && in_array($country, self::$euVatCountry)) {
                if ('required' === $required) {
                    if ('company' === $invoiceType || 'freelance' === $invoiceType) {
                        if ('on' !== $disableTaxCode) {
                            if (empty($taxCode)) {
                                $cartErrors->add(self::$metaKey . 'tax_code',
                                    __('Please enter your Tax Code', WC_EL_INV_TEXTDOMAIN),
                                    array('id' => self::$metaKey . 'tax_code')
                                );
                            }
                        }

                        if ('on' !== $disableTaxCode) {
                            if ((empty($vatCode) || strlen($vatCode) < 8)) {
                                $cartErrors->add(self::$metaKey . 'vat_number',
                                    __('Please enter your VAT number', WC_EL_INV_TEXTDOMAIN),
                                    array('id' => self::$metaKey . 'vat_number')
                                );
                            }
                        }

                        if (! preg_match($instance->regexVAT, $country . $vatCode)) {
                            $cartErrors->add(self::$metaKey . 'vat_number',
                                sprintf(
                                    __('VAT number %1$s is not correct', WC_EL_INV_TEXTDOMAIN),
                                    "<strong>{$country}-{$vatCode}</strong>"
                                ),
                                array('id' => self::$metaKey . 'vat_number')
                            );
                        }
                    } elseif ((! $isPeppolContext && ! $isKsefContext) && 'private' === $invoiceType && empty($taxCode) && $choiceType && 'receipt' !== $choiceType) {
                        $cartErrors->add(self::$metaKey . 'tax_code',
                            __('Please enter your Tax Code', WC_EL_INV_TEXTDOMAIN),
                            array('id' => self::$metaKey . 'tax_code')
                        );
                    }
                }
            }

            // Custom $invoiceType
            if ('IT' === $country && ('company' !== $invoiceType && 'freelance' !== $invoiceType && 'private' !== $invoiceType)) {
                do_action('wc_el_inv-validation_custom_type', $data, $cartErrors);
            }

            // No UE check
            if (! in_array($country, self::$euVatCountry)) {
                // Required and show fields for no UE
                if ('required' === $required && 'hide' !== $hideOutUe && $choiceType && 'receipt' !== $choiceType) {
                    if ('company' === $invoiceType || 'freelance' === $invoiceType) {
                        if ('on' !== $disableTaxCode) {
                            if (empty($taxCode)) {
                                $cartErrors->add(self::$metaKey . 'tax_code',
                                    __('Please enter your Tax Code', WC_EL_INV_TEXTDOMAIN),
                                    array('id' => self::$metaKey . 'tax_code')
                                );
                            }
                        }

                        if ('on' !== $disableTaxCode) {
                            if (empty($vatCode)) {
                                $cartErrors->add(self::$metaKey . 'vat_number',
                                    __('Please enter your VAT number', WC_EL_INV_TEXTDOMAIN),
                                    array('id' => self::$metaKey . 'vat_number')
                                );
                            }
                        }
                    } elseif ((! $isPeppolContext && ! $isKsefContext) && 'private' === $invoiceType && empty($taxCode)) {
                        $cartErrors->add(self::$metaKey . 'tax_code',
                            __('Please enter your Tax Code', WC_EL_INV_TEXTDOMAIN),
                            array('id' => self::$metaKey . 'tax_code')
                        );
                    }
                }
            }
        }

        // Vies check and remove tax from cart
        self::removeTaxFromOrder($cart);
        if (function_exists('WC') && WC()->customer) {
            WC()->customer->set_is_vat_exempt(false);
        }
    }

    /**
     * popRegisterAdditionalFieldsForWcBlocks
     *
     * @return void
     */
    public static function popRegisterAdditionalFieldsForWcBlocks()
    {
        $billingFields = apply_filters('wc_el_inv-billing_fields', []);
        if (function_exists('woocommerce_register_additional_checkout_field')) {
            foreach ($billingFields as $field) {
                if (! is_array($field) || empty($field['id'])) {
                    continue;
                }

                $fieldID = self::toBlockFieldId((string)$field['id']);
                $type    = isset($field['type']) && in_array($field['type'], ['text', 'select', 'checkbox'], true) ?
                    $field['type'] :
                    'text';
                $options = [
                    'id'       => $fieldID,
                    'label'    => isset($field['label']) ? (string)$field['label'] : (string)$field['id'],
                    'location' => 'order',
                    'type'     => $type,
                    'required' => ! empty($field['required']),
                    // Keep fields in Store API schema/persistence but do not auto-render them in
                    // Woo "Additional order information" because POP renders its own UI block.
                    'hidden'   => true,
                ];

                if ('select' === $type && ! empty($field['options']) && is_array($field['options'])) {
                    $selectOptions = [];
                    foreach ($field['options'] as $value => $label) {
                        $selectOptions[] = [
                            'value' => (string)$value,
                            'label' => (string)$label,
                        ];
                    }
                    $options['options'] = $selectOptions;
                }

                try {
                    woocommerce_register_additional_checkout_field($options);
                } catch (\Exception $e) {
                    // Keep checkout stable even if field registration fails on specific Woo versions.
                }
            }

            return;
        }

        // Backward compatibility for older Woo Blocks implementations.
        $field_ids = array_map(function ($field) {
            return isset($field['id']) ? self::toBlockFieldId((string)$field['id']) : '';
        }, $billingFields);
        $field_ids = array_filter($field_ids);
        add_filter('woocommerce_blocks_checkout_process_additional_fields',
            function ($additional_fields) use ($field_ids) {
                return array_unique(array_merge($additional_fields, $field_ids));
            });
    }

    /**
     * popCheckoutBlockInit
     *
     * @return void
     */
    public static function popCheckoutBlockInit()
    {
        // Get billing fields
        $billingFields = self::getBlockCheckoutFields();

        $scriptVersion   = defined('WC_EL_INV_ENV') && 'dev' === WC_EL_INV_ENV
            ? time()
            : WC_EL_INV_VERSION;
        $wcFieldPos      = OptionPage::init()->getOptions('billing_fields_position') ?: false;
        $blockScriptData = [
            'fields'            => $billingFields,
            'wc_fields_pos'     => $wcFieldPos,
            'pop_block_message' => [
                'required'        => __('The "%s" field is required.', WC_EL_INV_TEXTDOMAIN),
                'vat_tax__length' => __('The "%s" field must be at least 6 characters long.', WC_EL_INV_TEXTDOMAIN),
                'sdi_length'      => __('The "%s" field must be 7 characters long.', WC_EL_INV_TEXTDOMAIN),
                'min_length'      => __('The "%s" field must be at least 3 characters long.', WC_EL_INV_TEXTDOMAIN),
            ],
        ];

        $editorDeps = [
            'wp-blocks',
            'wp-element',
            'wp-i18n',
            'wp-data',
            'wp-components',
            'wp-dom-ready',
        ];

        if (wp_script_is('wc-blocks-checkout', 'registered')) {
            $editorDeps[] = 'wc-blocks-checkout';
        }

        wp_register_script(
            'pop-checkout-block-editor',
            Plugin::getPluginDirUrl('assets/js/pop-block.js'),
            $editorDeps,
            $scriptVersion,
            true
        );

        wp_localize_script('pop-checkout-block-editor', 'PopCheckoutData', $blockScriptData);

        // Register block type "wc/pop-checkout"
        register_block_type(
            'wc/pop-checkout', [
            'editor_script'   => 'pop-checkout-block-editor',
            'render_callback' => [self::class, 'popCheckoutBlockRender'],
            'title'           => 'POP Checkout Fields',
            'category'        => 'woocommerce',
            'supports'        => [
                'align' => false,
                'html'  => false,
            ],
            'attributes'      => [
                'fields' => [
                    'type'    => 'array',
                    'default' => $billingFields,
                ],
            ],
        ]);

        // Register additional fields
        self::popRegisterAdditionalFieldsForWcBlocks();

        // Enqueue script front and admin
        add_action('wp_enqueue_scripts', function () use ($blockScriptData) {
            wp_enqueue_script(
                'pop-checkout-block',
                Plugin::getPluginDirUrl('assets/js/pop-block.js'),
                [
                    'wp-i18n',
                    'wp-data',
                    'wp-components',
                    'wp-blocks',
                    'wp-element',
                    'wc_el_inv_invoice',
                    'wc-blocks-checkout',
                ],
                defined('WC_EL_INV_ENV') && 'dev' === WC_EL_INV_ENV ? time() : WC_EL_INV_VERSION,
                true
            );
            wp_localize_script('pop-checkout-block', 'PopCheckoutData', $blockScriptData);
        });
        add_action('enqueue_block_editor_assets', function () {
            wp_enqueue_script('pop-checkout-block-editor');
        });
    }

    /**
     * popCheckoutBlockValidationInit
     *
     * @return void
     */
    public static function popCheckoutBlockValidationInit()
    {
        if (! \WcElectronInvoice\Functions\isWooCommerceActive()) {
            return;
        }

        add_action('woocommerce_store_api_cart_errors', function ($cartErrors, $cart) {
            self::popCheckoutBlockValidation($cartErrors, $cart);
        }, 10, 2);
    }

    /**
     * popCheckoutBlockRender
     *
     * @return false|string
     */
    public static function popCheckoutBlockRender()
    {
        $billingFields = self::getBlockCheckoutFields();
        $fields_json   = wp_json_encode($billingFields);
        ob_start();
        ?>
        <div id="pop-checkout">
            <?php echo apply_filters('wc_el_inv-pop_checkout_block_title',
                sprintf("<h4>%s</h4>", esc_html__('Tax information', WC_EL_INV_TEXTDOMAIN))); ?>
            <div id="pop-checkout-root" data-fields='<?php echo esc_attr($fields_json); ?>'></div>
        </div>
        <?php
        return ob_get_clean();
    }

    /**
     * popCheckoutBlockSaveData
     *
     * @return void
     */
    public static function popCheckoutBlockSaveData()
    {
        if (! \WcElectronInvoice\Functions\isWooCommerceActive()) {
            return;
        }

        add_action('woocommerce_store_api_checkout_update_order_from_request', function ($order, $request) {
            $additionalFields = [];
            if (is_object($request) && method_exists($request, 'get_param')) {
                $requestAdditionalFields = $request->get_param('additional_fields');
                if (is_array($requestAdditionalFields)) {
                    $additionalFields = $requestAdditionalFields;
                }
            }

            // Fallback: in some environments additional_fields may still be read from the raw body.
            if (empty($additionalFields)) {
                $rawPost = file_get_contents('php://input');
                $data    = json_decode($rawPost, true);
                if (is_array($data) && isset($data['additional_fields']) && is_array($data['additional_fields'])) {
                    $additionalFields = $data['additional_fields'];
                }
            }

            $additionalFields = self::normalizeBlockAdditionalFields($additionalFields);

            if (self::isPeppolCheckoutContext() || self::isKsefCheckoutContext()) {
                // In PEPPOL context, SdI and tax code are never used and must never be persisted.
                $additionalFields['billing_sdi_type'] = '';
                $additionalFields['billing_tax_code'] = '';
            }

            if (! empty($additionalFields)) {

                $choiceType = null;
                if (array_key_exists('billing_choice_type', $additionalFields)) {
                    $choiceType = $additionalFields['billing_choice_type'];
                }

                foreach ($additionalFields as $key => $value) {
                    if ('receipt' === $choiceType) {
                        if ('billing_choice_type' !== $key) {
                            $value = '';
                        }

                        if ('billing_invoice_type' === $key) {
                            $value = 'private';
                        }
                    }

                    $order->update_meta_data("_{$key}", $value);
                }
                $order->save();

                $userID = $order->get_customer_id();
                if ($userID) {
                    foreach ($additionalFields as $key => $value) {
                        if ('receipt' === $choiceType) {
                            if ('billing_choice_type' !== $key) {
                                $value = '';
                            }

                            if ('billing_invoice_type' === $key) {
                                $value = 'private';
                            }
                        }

                        update_user_meta($userID, "{$key}", $value);
                    }
                }
            }
        }, 20, 2);
    }

    /**
     * Returns true when checkout is in PEPPOL context.
     * Priority is the resolved active invoice channel; country rules are a fallback.
     *
     * @return bool
     */
    private static function isPeppolCheckoutContext(): bool
    {
        return Integrations::isPeppolContext();
    }

    /**
     * Returns true when checkout is in KSeF context.
     * Priority is the resolved active invoice channel; country rules are a fallback.
     *
     * @return bool
     */
    private static function isKsefCheckoutContext(): bool
    {
        return Integrations::isKsefContext();
    }

    /**
     * Returns true when the provided billing country should behave as PEPPOL context.
     * IT/SM are always treated as non-PEPPOL.
     *
     * @param string $country
     *
     * @return bool
     */
    private static function isPeppolCountry(string $country): bool
    {
        $country = strtoupper(trim($country));
        if ('' === $country) {
            return self::isPeppolCheckoutContext();
        }

        return Integrations::isPeppolCountryContext($country);
    }

    /**
     * Returns checkout block fields with namespaced IDs while preserving legacy IDs.
     *
     * @return array
     */
    private static function getBlockCheckoutFields(): array
    {
        $billingFields = apply_filters('wc_el_inv-billing_fields', []);
        if (! is_array($billingFields)) {
            return [];
        }

        foreach ($billingFields as $key => $field) {
            if (! is_array($field) || empty($field['id'])) {
                continue;
            }
            $legacyID                         = (string)$field['id'];
            $billingFields[$key]['id']        = self::toBlockFieldId($legacyID);
            $billingFields[$key]['legacy_id'] = $legacyID;
        }

        return $billingFields;
    }

    /**
     * Converts a legacy field ID to block namespaced ID.
     *
     * @param string $fieldID
     *
     * @return string
     */
    private static function toBlockFieldId(string $fieldID): string
    {
        if (0 === strpos($fieldID, 'pop/')) {
            return $fieldID;
        }

        return 'pop/' . $fieldID;
    }

    /**
     * Converts a block field ID to legacy field ID.
     *
     * @param string $fieldID
     *
     * @return string
     */
    private static function fromBlockFieldId(string $fieldID): string
    {
        return 0 === strpos($fieldID, 'pop/') ? substr($fieldID, 4) : $fieldID;
    }

    /**
     * Normalizes additional fields keys from namespaced block format to legacy format.
     *
     * @param array $additionalFields
     *
     * @return array
     */
    private static function normalizeBlockAdditionalFields(array $additionalFields): array
    {
        $normalized = [];
        foreach ($additionalFields as $key => $value) {
            $normalized[self::fromBlockFieldId((string)$key)] = $value;
        }

        return $normalized;
    }

    /**
     * validation checkout
     *
     * @param $data
     * @param $errors
     *
     * @return bool|void
     * @since 4.6.0
     */
    public function validation($data, $errors)
    {
        $hideOutUe       = $this->options[self::$optionKey . 'hide_outside_ue'] ?? null;
        $userCountry     = get_user_meta(get_current_user_id(), 'billing_country', true);
        $disableTaxCode  = OptionPage::init()->getOptions('invoice_disable_cf');
        $required        = OptionPage::init()->getOptions('invoice_required');
        $disablePecSdi   = OptionPage::init()->getOptions('invoice_disable_pec_sdi');
        $isPeppolContext = self::isPeppolCheckoutContext();
        $isKsefContext   = self::isKsefCheckoutContext();
        if ($isPeppolContext || $isKsefContext) {
            $disablePecSdi            = 'on';
            $disableTaxCode           = 'on';
            $data['billing_sdi_type'] = '';
            $data['billing_tax_code'] = '';
            self::removeClassicCheckoutSdiPostedData();
        }

        // Validation check
        $validation = false;
        if (! empty($data['payment_method'])) {
            switch ($data['payment_method']) {
                // Validation support on process
                case 'ppec_paypal':
                case 'ppcp':
                case 'ppcp-gateway':
                case 'ppcp-card-button-gateway':
                case 'ppcp-credit-card-gateway':
                    $validation = true;
                    break;
                default:
                    $validation = apply_filters('wc_el_inv-payment_method_validation', false, $data['payment_method']);
                    break;
            }
        }

        if (! $validation) {
            return false;
        }

        // @codingStandardsIgnoreLine
        $vatCode = \WcElectronInvoice\Functions\filterInput(
            $data,
            self::$metaKey . 'vat_number',
            FILTER_UNSAFE_RAW
        );

        $vatCode = sanitize($vatCode);

        // @codingStandardsIgnoreLine
        $taxCode = \WcElectronInvoice\Functions\filterInput(
            $data,
            self::$metaKey . 'tax_code',
            FILTER_UNSAFE_RAW
        );

        $taxCode = sanitize($taxCode);

        // @codingStandardsIgnoreLine
        $sdi = \WcElectronInvoice\Functions\filterInput(
            $data,
            self::$metaKey . 'sdi_type',
            FILTER_UNSAFE_RAW
        );

        $sdi = sanitize($sdi);

        // @codingStandardsIgnoreLine
        $choiceDocType = \WcElectronInvoice\Functions\filterInput(
            $data,
            self::$metaKey . 'choice_type',
            FILTER_UNSAFE_RAW
        );

        $choiceDocType = sanitize($choiceDocType);

        // @codingStandardsIgnoreLine
        $invoiceType = \WcElectronInvoice\Functions\filterInput(
            $data,
            self::$metaKey . 'invoice_type',
            FILTER_UNSAFE_RAW
        );

        $invoiceType = sanitize($invoiceType);

        // @codingStandardsIgnoreLine
        $country = \WcElectronInvoice\Functions\filterInput(
            $data,
            'billing_country',
            FILTER_UNSAFE_RAW
        );

        $country = sanitize($country);

        $company = \WcElectronInvoice\Functions\filterInput(
            $data,
            'billing_company',
            FILTER_UNSAFE_RAW
        );

        $company = sanitize($company);

        // Not required and not IT
        if ('IT' !== $country && 'required' !== $required) {
            if (self::isCheckout()) {
                add_filter('woocommerce_checkout_posted_data', function ($data) {
                    unset($data['billing_choice_type']);
                    if (! self::isPeppolCheckoutContext() &&
                        ! self::isKsefCheckoutContext() &&
                        empty($data['billing_vat_number']) &&
                        empty($data['billing_tax_code'])) {
                        unset($data['billing_invoice_type']);
                    }

                    return $data;
                });
            }
        }

        // Required - Not Receipt and country IT and customer type empty
        if ('required' === $required || 'IT' === $country) {
            if ('receipt' !== $choiceDocType &&
                '' === $invoiceType) {
                // Unset SDI
                if (self::isCheckout()) {
                    add_filter('woocommerce_checkout_posted_data', function ($data) {
                        unset($data['billing_sdi_type']);
                        unset($data['billing_vat_number']);
                        unset($data['billing_tax_code']);

                        return $data;
                    });
                }

                $errors->add(self::$metaKey . 'invoice_type',
                    sprintf('<strong>%s</strong> %s',
                        __('Customer type', WC_EL_INV_TEXTDOMAIN),
                        __('it is a required field.', WC_EL_INV_TEXTDOMAIN)
                    ),
                    array('id' => self::$metaKey . 'invoice_type')
                );
            }
        }

        if ('company' === $invoiceType && '' === $company) {
            $errors->add(self::$metaKey . 'billing_company',
                sprintf('<strong>%s</strong> %s',
                    __('Name of the company', WC_EL_INV_TEXTDOMAIN),
                    __('it is a required field.', WC_EL_INV_TEXTDOMAIN)
                ),
                array('id' => self::$metaKey . 'billing_company')
            );
        }

        // If outside the EU for the Reverse Charge the user is always considered as private
        $invoiceViesCheck = TaxFields::getViesCheck();
        if ('yes' === $invoiceViesCheck &&
            ! in_array($country, self::$euVatCountry, true) &&
            'hide' === $hideOutUe &&
            ! $invoiceType
        ) {
            $invoiceType = 'private';
        }

        // No check if hide the VAT number and tax code field.
        if ('yes' !== $invoiceViesCheck &&
            ! in_array($country, self::$euVatCountry, true) &&
            'hide' === $hideOutUe &&
            '' !== $userCountry
        ) {
            return true;
        }

        // Tax code length
        $vatCodeLength = isset($vatCode) ? strlen($vatCode) : 0;

        // Default billing_invoice_type filter
        $invoiceTypeDefault = apply_filters('wc_el_inv-billing_invoice_type_default_data', null, $data);
        if ($invoiceTypeDefault) {
            $data['billing_invoice_type'] = $invoiceTypeDefault;
        }

        // Receipt ? reset sdi, vat and tax code fake data
        if ('receipt' === $choiceDocType) {
            $data['billing_sdi_type']     = '';
            $data['billing_vat_number']   = '';
            $data['billing_tax_code']     = '';
            $data['billing_invoice_type'] = 'private';

            if ($errors instanceof \WP_Error) {
                $errors->remove('billing_choice_type_required');
                $errors->remove('billing_invoice_type_required');
                $errors->remove('billing_sdi_type_required');
                $errors->remove('billing_vat_number_required');
                $errors->remove('billing_tax_code_required');
            }
        }

        // IT Invoice for company and freelance
        if ('IT' === $country && ('company' === $invoiceType || 'freelance' === $invoiceType)) {
            // Definition of VAT Number Length
            $vatCodeLength = isset($vatCode) ? strlen($vatCode) : 0;

            // VAT Check for Businesses and Freelancers
            if (! preg_match($this->regexVAT,
                    $country . $vatCode) || ! ctype_digit($vatCode) || $vatCodeLength !== 11) {
                $errors->add(self::$metaKey . 'vat_number',
                    sprintf(
                        __('VAT number %1$s is not correct', WC_EL_INV_TEXTDOMAIN),
                        "<strong>{$country}-{$vatCode}</strong>"
                    ),
                    array('id' => self::$metaKey . 'vat_number')
                );
            }

            // Tax Code / VAT Number Check for Companies
            if ('company' === $invoiceType) {
                $isVATValid        = preg_match($this->regexVAT, $country . $taxCode);
                $isCFOrAssociation = ctype_digit($taxCode) && strlen($taxCode) === 11; // CF di un'associazione o azienda

                if ('on' !== $disableTaxCode) {
                    if (! $isCFOrAssociation) {
                        // Invalid company/association CF
                        $errors->add(self::$metaKey . 'tax_code',
                            sprintf(
                                __('TAX code %1$s is not correct', WC_EL_INV_TEXTDOMAIN),
                                "<strong>" . strtoupper($taxCode) . "</strong>"
                            ),
                            array('id' => self::$metaKey . 'tax_code')
                        );
                    } elseif ($taxCode === $vatCode && ! $isVATValid) {
                        // If the CF and VAT number match, I check that it is a valid VAT number
                        $errors->add(self::$metaKey . 'tax_code',
                            sprintf(
                                __('TAX code %1$s is not correct', WC_EL_INV_TEXTDOMAIN),
                                "<strong>" . strtoupper($taxCode) . "</strong>"
                            ),
                            array('id' => self::$metaKey . 'tax_code')
                        );
                    }
                }
            }

            // Tax Code Check for Freelancers
            if ('freelance' === $invoiceType) {
                if ('on' !== $disableTaxCode && ! preg_match($this->regexCF, $taxCode)) {
                    $errors->add(self::$metaKey . 'tax_code',
                        sprintf(
                            __('TAX code %1$s is not correct', WC_EL_INV_TEXTDOMAIN),
                            "<strong>" . strtoupper($taxCode) . "</strong>"
                        ),
                        array('id' => self::$metaKey . 'tax_code')
                    );
                }
            }

            // Check PEC Email or SDI Recipient Code
            if ((! $isPeppolContext && ! $isKsefContext) && ! empty($sdi)) {
                $isValidSDI = preg_match($this->regexPEC, $sdi) ||
                              preg_match($this->regexLEGALMAIL, $sdi) ||
                              preg_match($this->regexWEBSERV, $sdi);

                if (! $isValidSDI) {
                    $errors->add(self::$metaKey . 'sdi_type',
                        sprintf(
                            __('E-mail (PEC) or Unique Code %1$s is not correct', WC_EL_INV_TEXTDOMAIN),
                            "<strong>{$sdi}</strong>"
                        ),
                        array('id' => self::$metaKey . 'sdi_type')
                    );
                }
            } elseif ((! $isPeppolContext && ! $isKsefContext) && empty($sdi) && 'off' === $disablePecSdi) {
                $errors->add(self::$metaKey . 'sdi_type',
                    __('E-mail (PEC) or Unique Code is required', WC_EL_INV_TEXTDOMAIN),
                    array('id' => self::$metaKey . 'sdi_type')
                );
            }
        }

        // EU Country VAT check
        if ('IT' !== $country && in_array($country, self::$euVatCountry)) {
            // Unset SDI
            if (self::isCheckout()) {
                if ($errors instanceof \WP_Error) {
                    $errors->remove('billing_sdi_type_required');
                }

                add_filter('woocommerce_checkout_posted_data', function ($data) {
                    unset($data['billing_sdi_type']);

                    return $data;
                });
            }

            if ('required' === $required) {
                if ('company' === $invoiceType || 'freelance' === $invoiceType) {
                    if ('on' !== $disableTaxCode) {
                        if (empty($taxCode)) {
                            $errors->add(self::$metaKey . 'tax_code',
                                __('Please enter your Tax Code', WC_EL_INV_TEXTDOMAIN),
                                array('id' => self::$metaKey . 'tax_code')
                            );
                        }
                    }

                    if ('on' !== $disableTaxCode) {
                        if ((empty($vatCode) || strlen($vatCode) < 8)) {
                            $errors->add(self::$metaKey . 'vat_number',
                                __('Please enter your VAT number', WC_EL_INV_TEXTDOMAIN),
                                array('id' => self::$metaKey . 'vat_number')
                            );
                        }
                    }

                    if (! preg_match($this->regexVAT, $country . $vatCode)) {
                        $errors->add(self::$metaKey . 'vat_number',
                            sprintf(
                                __('VAT number %1$s is not correct', WC_EL_INV_TEXTDOMAIN),
                                "<strong>{$country}-{$vatCode}</strong>"
                            ),
                            array('id' => self::$metaKey . 'vat_number')
                        );
                    }
                } elseif ((! $isPeppolContext && ! $isKsefContext) && 'private' === $invoiceType && empty($taxCode) && 'receipt' !== $choiceDocType) {
                    $errors->add(self::$metaKey . 'tax_code',
                        __('Please enter your Tax Code', WC_EL_INV_TEXTDOMAIN),
                        array('id' => self::$metaKey . 'tax_code')
                    );
                }
            }
        }

        // It Private customer
        if ((! $isPeppolContext && ! $isKsefContext) && 'IT' === $country && 'receipt' !== $choiceDocType && 'private' === $invoiceType) {
            // Unset SDI and VAT
            if (self::isCheckout()) {
                if ($errors instanceof \WP_Error) {
                    $errors->remove('billing_sdi_type_required');
                    $errors->remove('billing_vat_number_required');
                }

                add_filter('woocommerce_checkout_posted_data', function ($data) {
                    unset($data['billing_sdi_type']);
                    unset($data['billing_vat_number']);

                    return $data;
                });
            }

            if (! preg_match($this->regexCF, $taxCode)) {
                $code = strtoupper($taxCode);
                $errors->add(self::$metaKey . 'tax_code',
                    sprintf(
                        __('Tax ID Number %1$s is not correct', WC_EL_INV_TEXTDOMAIN),
                        "<strong>{$code}</strong>"
                    ),
                    array('id' => self::$metaKey . 'tax_code')
                );
            }
        }

        // Custom $invoiceType
        if ('IT' === $country && ('company' !== $invoiceType && 'freelance' !== $invoiceType && 'private' !== $invoiceType)) {
            // Like a private customer
            $data['billing_sdi_type']     = '';
            $data['billing_vat_number']   = '';
            $data['billing_invoice_type'] = sanitize($invoiceType);

            if ($errors instanceof \WP_Error) {
                $errors->remove('billing_choice_type_required');
                $errors->remove('billing_invoice_type_required');
                $errors->remove('billing_sdi_type_required');
                $errors->remove('billing_vat_number_required');
                $errors->remove('billing_tax_code_required');
            }

            do_action('wc_el_inv-validation_custom_type', $data, $errors);
        }

        // No UE check
        if (! in_array($country, self::$euVatCountry)) {
            // Unset SDI
            if (self::isCheckout()) {
                if ($errors instanceof \WP_Error) {
                    $errors->remove('billing_sdi_type_required');
                }

                add_filter('woocommerce_checkout_posted_data', function ($data) {
                    unset($data['billing_sdi_type']);

                    return $data;
                });
            }

            // Required and show fields for no UE
            if ('required' === $required && 'hide' !== $hideOutUe && 'receipt' !== $choiceDocType) {
                if ('company' === $invoiceType || 'freelance' === $invoiceType) {
                    if ('on' !== $disableTaxCode) {
                        if (empty($taxCode)) {
                            $errors->add(self::$metaKey . 'tax_code',
                                __('Please enter your Tax Code', WC_EL_INV_TEXTDOMAIN),
                                array('id' => self::$metaKey . 'tax_code')
                            );
                        }
                    }

                    if ('on' !== $disableTaxCode) {
                        if (empty($vatCode)) {
                            $errors->add(self::$metaKey . 'vat_number',
                                __('Please enter your VAT number', WC_EL_INV_TEXTDOMAIN),
                                array('id' => self::$metaKey . 'vat_number')
                            );
                        }
                    }
                } elseif ((! $isPeppolContext && ! $isKsefContext) && 'private' === $invoiceType && empty($taxCode)) {
                    $errors->add(self::$metaKey . 'tax_code',
                        __('Please enter your Tax Code', WC_EL_INV_TEXTDOMAIN),
                        array('id' => self::$metaKey . 'tax_code')
                    );
                }
            }
        }
    }

    /**
     * Checkout Process
     *
     * @since 1.0.0
     */
    public function process()
    {
        $hideOutUe       = $this->options[self::$optionKey . 'hide_outside_ue'] ?? null;
        $userCountry     = get_user_meta(get_current_user_id(), 'billing_country', true);
        $disableTaxCode  = OptionPage::init()->getOptions('invoice_disable_cf');
        $required        = OptionPage::init()->getOptions('invoice_required');
        $disablePecSdi   = OptionPage::init()->getOptions('invoice_disable_pec_sdi');
        $isPeppolContext = self::isPeppolCheckoutContext();
        $isKsefContext   = self::isKsefCheckoutContext();
        if ($isPeppolContext || $isKsefContext) {
            $disablePecSdi             = 'on';
            $disableTaxCode            = 'on';
            $_POST['billing_sdi_type'] = '';
            $_POST['billing_tax_code'] = '';
            self::removeClassicCheckoutSdiPostedData();
        }

        if (! empty($this->keys)) {

            // Clear notice
            wc_clear_notices();

            // @codingStandardsIgnoreLine
            $vatCode = \WcElectronInvoice\Functions\filterInput(
                $_POST,
                self::$metaKey . 'vat_number',
                FILTER_UNSAFE_RAW
            );

            $vatCode = sanitize($vatCode);

            // @codingStandardsIgnoreLine
            $taxCode = \WcElectronInvoice\Functions\filterInput(
                $_POST,
                self::$metaKey . 'tax_code',
                FILTER_UNSAFE_RAW
            );

            $taxCode = sanitize($taxCode);

            // @codingStandardsIgnoreLine
            $sdi = \WcElectronInvoice\Functions\filterInput(
                $_POST,
                self::$metaKey . 'sdi_type',
                FILTER_UNSAFE_RAW
            );

            $sdi = sanitize($sdi);

            // @codingStandardsIgnoreLine
            $choiceDocType = \WcElectronInvoice\Functions\filterInput(
                $_POST,
                self::$metaKey . 'choice_type',
                FILTER_UNSAFE_RAW
            );

            $choiceDocType = sanitize($choiceDocType);

            // @codingStandardsIgnoreLine
            $invoiceType = \WcElectronInvoice\Functions\filterInput(
                $_POST,
                self::$metaKey . 'invoice_type',
                FILTER_UNSAFE_RAW
            );

            $invoiceType = sanitize($invoiceType);

            // @codingStandardsIgnoreLine
            $country = \WcElectronInvoice\Functions\filterInput(
                $_POST,
                'billing_country',
                FILTER_UNSAFE_RAW
            );

            $country = sanitize($country);

            $company = \WcElectronInvoice\Functions\filterInput(
                $_POST,
                'billing_company',
                FILTER_UNSAFE_RAW
            );

            $company = sanitize($company);

            $isExtraEuCountry = ! empty($country) && ! in_array($country, self::$euVatCountry, true);

            // Not required and not IT
            if ('IT' !== $country && 'required' !== $required) {
                if (self::isCheckout()) {
                    add_filter('woocommerce_checkout_posted_data', function ($data) {
                        unset($data['billing_choice_type']);
                        if (! self::isPeppolCheckoutContext() &&
                            ! self::isKsefCheckoutContext() &&
                            empty($data['billing_vat_number']) &&
                            empty($data['billing_tax_code'])) {
                            unset($data['billing_invoice_type']);
                        }

                        return $data;
                    });
                }
            }

            // Required - Not Receipt and country IT and customer type empty
            if ((! $isPeppolContext && ! $isKsefContext) && ('required' === $required || 'IT' === $country)) {
                if ('receipt' !== $choiceDocType &&
                    '' === $invoiceType) {
                    // Unset SDI
                    if (self::isCheckout()) {
                        add_filter('woocommerce_checkout_posted_data', function ($data) {
                            unset($data['billing_sdi_type']);
                            unset($data['billing_vat_number']);
                            unset($data['billing_tax_code']);

                            return $data;
                        });
                    }

                    wc_add_notice(sprintf('<strong>%s</strong> %s', __('Customer type', WC_EL_INV_TEXTDOMAIN),
                        __('it is a required field.', WC_EL_INV_TEXTDOMAIN)), 'error');
                }
            }

            // Company name
            if (! $isExtraEuCountry && 'company' === $invoiceType && '' === $company) {
                wc_add_notice(sprintf('<strong>%s</strong> %s', __('Name of the company', WC_EL_INV_TEXTDOMAIN),
                    __('it is a required field.', WC_EL_INV_TEXTDOMAIN)), 'error');
            }

            // If outside the EU for the Reverse Charge the user is always considered as private
            $invoiceViesCheck = TaxFields::getViesCheck();
            if ('yes' === $invoiceViesCheck &&
                ! in_array($country, self::$euVatCountry, true) &&
                'hide' === $hideOutUe &&
                ! $invoiceType
            ) {
                $invoiceType = 'private';
            }

            // No check if hide the VAT number and tax code field.
            if ('yes' !== $invoiceViesCheck &&
                ! in_array($country, self::$euVatCountry, true) &&
                'hide' === $hideOutUe &&
                '' !== $userCountry
            ) {
                return true;
            }

            // Tax code length
            $vatCodeLength = isset($vatCode) ? strlen($vatCode) : 0;

            // Default billing_invoice_type filter
            $invoiceTypeDefault = apply_filters('wc_el_inv-billing_invoice_type_default_data', null, $_POST);
            if ($invoiceTypeDefault) {
                $_POST['billing_invoice_type'] = $invoiceTypeDefault;
            }

            // Receipt ? reset sdi, vat and tax code fake data
            if ('receipt' === $choiceDocType) {
                $_POST['billing_sdi_type']     = '';
                $_POST['billing_vat_number']   = '';
                $_POST['billing_tax_code']     = '';
                $_POST['billing_invoice_type'] = 'private';
            }

            // IT Invoice for company and freelance
            if ('IT' === $country && ('company' === $invoiceType || 'freelance' === $invoiceType)) {
                // Definition of VAT Number Length
                $vatCodeLength = isset($vatCode) ? strlen($vatCode) : 0;

                // VAT Check for Businesses and Freelancers
                if (! preg_match($this->regexVAT,
                        $country . $vatCode) || ! ctype_digit($vatCode) || $vatCodeLength !== 11) {
                    wc_add_notice(
                        sprintf(
                            __('VAT number %1$s is not correct', WC_EL_INV_TEXTDOMAIN),
                            "<strong>{$country}-{$vatCode}</strong>"
                        ),
                        'error'
                    );
                }

                // Tax Code / VAT Number Check for Companies
                if ('company' === $invoiceType) {
                    $isVATValid        = preg_match($this->regexVAT, $country . $taxCode);
                    $isCFOrAssociation = ctype_digit($taxCode) && strlen($taxCode) === 11; // CF of an association or company

                    if ('on' !== $disableTaxCode) {
                        if (! $isCFOrAssociation) {
                            // Invalid company/association CF
                            wc_add_notice(
                                sprintf(
                                    __('TAX code %1$s is not correct', WC_EL_INV_TEXTDOMAIN),
                                    "<strong>" . strtoupper($taxCode) . "</strong>"
                                ),
                                'error'
                            );
                        } elseif ($taxCode === $vatCode && ! $isVATValid) {
                            // If the CF and VAT number match, I check that it is a valid VAT number
                            wc_add_notice(
                                sprintf(
                                    __('TAX code %1$s is not correct', WC_EL_INV_TEXTDOMAIN),
                                    "<strong>" . strtoupper($taxCode) . "</strong>"
                                ),
                                'error'
                            );
                        }
                    }
                }

                // Tax Code Check for Freelancers
                if ('freelance' === $invoiceType) {
                    if ('on' !== $disableTaxCode && ! preg_match($this->regexCF, $taxCode)) {
                        wc_add_notice(
                            sprintf(
                                __('TAX code %1$s is not correct', WC_EL_INV_TEXTDOMAIN),
                                "<strong>" . strtoupper($taxCode) . "</strong>"
                            ),
                            'error'
                        );
                    }
                }

                // Check PEC Email or SDI Recipient Code
                if ((! $isPeppolContext && ! $isKsefContext) && ! empty($sdi)) {
                    $isValidSDI = preg_match($this->regexPEC, $sdi) ||
                                  preg_match($this->regexLEGALMAIL, $sdi) ||
                                  preg_match($this->regexWEBSERV, $sdi);

                    if (! $isValidSDI) {
                        wc_add_notice(
                            sprintf(
                                __('E-mail (PEC) or Unique Code %1$s is not correct', WC_EL_INV_TEXTDOMAIN),
                                "<strong>{$sdi}</strong>"
                            ),
                            'error'
                        );
                    }
                } elseif ((! $isPeppolContext && ! $isKsefContext) && empty($sdi) && 'off' === $disablePecSdi) {
                    wc_add_notice(
                        __('E-mail (PEC) or Unique Code is required', WC_EL_INV_TEXTDOMAIN),
                        'error'
                    );
                }
            }

            // EU Country VAT check
            if ('IT' !== $country && in_array($country, self::$euVatCountry)) {
                // Unset SDI
                if (self::isCheckout()) {
                    add_filter('woocommerce_checkout_posted_data', function ($data) {
                        unset($data['billing_sdi_type']);

                        return $data;
                    });
                }

                if ('required' === $required) {
                    if ('company' === $invoiceType || 'freelance' === $invoiceType) {
                        if ('on' !== $disableTaxCode) {
                            if (empty($taxCode)) {
                                wc_add_notice(__('Please enter your Tax Code', WC_EL_INV_TEXTDOMAIN), 'error');
                            }
                        }

                        if ('on' !== $disableTaxCode) {
                            if ((empty($vatCode) || strlen($vatCode) < 8)) {
                                wc_add_notice(__('Please enter your VAT number', WC_EL_INV_TEXTDOMAIN), 'error');
                            }
                        }

                        if (! preg_match($this->regexVAT, $country . $vatCode)) {
                            wc_add_notice(
                                sprintf(
                                    __('VAT number %1$s is not correct', WC_EL_INV_TEXTDOMAIN),
                                    "<strong>{$country}-{$vatCode}</strong>"
                                ),
                                'error'
                            );
                        }
                    } elseif ((! $isPeppolContext && ! $isKsefContext) && 'private' === $invoiceType && empty($taxCode) && 'receipt' !== $choiceDocType) {
                        wc_add_notice(__('Please enter your Tax Code', WC_EL_INV_TEXTDOMAIN), 'error');
                    }
                }
            }

            // IT Private customer
            if ((! $isPeppolContext && ! $isKsefContext) && 'IT' === $country && 'receipt' !== $choiceDocType && 'private' === $invoiceType) {
                // Unset SDI and VAT
                if (self::isCheckout()) {
                    add_filter('woocommerce_checkout_posted_data', function ($data) {
                        unset($data['billing_sdi_type']);
                        unset($data['billing_vat_number']);

                        return $data;
                    });
                }

                if (! preg_match($this->regexCF, $taxCode)) {
                    $code = strtoupper($taxCode);
                    wc_add_notice(
                        sprintf(
                            __('Tax ID Number %1$s is not correct', WC_EL_INV_TEXTDOMAIN),
                            "<strong>{$code}</strong>"
                        ),
                        'error'
                    );
                }
            }

            // No UE check
            if ($country && ! in_array($country, self::$euVatCountry)) {
                // Unset SDI
                if (self::isCheckout()) {
                    add_filter('woocommerce_checkout_posted_data', function ($data) {
                        unset($data['billing_sdi_type']);

                        return $data;
                    });
                }

                // Required and show fields for no UE
                if (! $isExtraEuCountry && 'required' === $required && 'hide' !== $hideOutUe && 'receipt' !== $choiceDocType) {
                    if ('company' === $invoiceType || 'freelance' === $invoiceType) {
                        if ('on' !== $disableTaxCode) {
                            if (empty($taxCode)) {
                                wc_add_notice(__('Please enter your Tax Code', WC_EL_INV_TEXTDOMAIN), 'error');
                            }
                        }

                        if ('on' !== $disableTaxCode) {
                            if (empty($vatCode)) {
                                wc_add_notice(__('Please enter your VAT number', WC_EL_INV_TEXTDOMAIN), 'error');
                            }
                        }
                    } elseif ((! $isPeppolContext && ! $isKsefContext) && 'private' === $invoiceType && empty($taxCode)) {
                        wc_add_notice(__('Please enter your Tax Code', WC_EL_INV_TEXTDOMAIN), 'error');
                    }
                }
            }

            // Custom $invoiceType
            if ('IT' === $country && ('company' !== $invoiceType && 'freelance' !== $invoiceType && 'private' !== $invoiceType)) {
                // Like a private customer
                $_POST['billing_sdi_type']     = '';
                $_POST['billing_vat_number']   = '';
                $_POST['billing_invoice_type'] = sanitize($invoiceType);

                do_action('wc_el_inv-process_custom_type');
            }

            $sanMarinoSupport    = sanMarinoSupport($invoiceType, $country);
            $noViesCheck         = $sanMarinoSupport->noViesCheck;
            $allowExtraEuZeroTax = self::canApplyExtraEuZeroTax(WC()->cart ?? null);

            // -- Reverse Charge Company vies check or extra ue -- //
            // 1. private and company extra UE
            // 1. company UE vies ok
            if ($country &&
                // No UE and no check vies for SM
                (($allowExtraEuZeroTax && ! in_array($country, self::$euVatCountry, true)) || $noViesCheck) xor
                // No IT UE check
                ('IT' !== $country &&
                 in_array($country, self::$euVatCountry, true) &&
                 self::viesCheck($vatCode, $country) &&
                 ('company' === $invoiceType || 'freelance' === $invoiceType)
                )
            ) {
                self::viesCalcTotals();
            }
            // -- Reverse Charge Company vies check or extra ue -- //
        }
    }

    /**
     * Admin Store meta
     *
     * @param $orderID
     *
     * @since 1.0.0
     *
     */
    public function saveOrderMetaBox($orderID)
    {
        $order        = wc_get_order($orderID);
        $wcOrderClass = \WcElectronInvoice\Functions\wcOrderClassName($order, '\WC_Order');

        if (! $order instanceof $wcOrderClass) {
            return;
        }

        // @codingStandardsIgnoreLine
        $number  = \WcElectronInvoice\Functions\filterInput($_POST, 'order_number_invoice', FILTER_SANITIZE_NUMBER_INT);
        $date    = \WcElectronInvoice\Functions\filterInput($_POST, 'order_date_invoice', FILTER_UNSAFE_RAW);
        $hour    = \WcElectronInvoice\Functions\filterInput($_POST, 'order_hours_invoice', FILTER_UNSAFE_RAW);
        $minute  = \WcElectronInvoice\Functions\filterInput($_POST, 'order_minutes_invoice', FILTER_UNSAFE_RAW);
        $payment = \WcElectronInvoice\Functions\filterInput($_POST, 'refund_payment_method', FILTER_UNSAFE_RAW);
        // Get custom meta
        $nature  = \WcElectronInvoice\Functions\filterInput($_POST, '_billing_nature_rc', FILTER_UNSAFE_RAW);
        $refNorm = \WcElectronInvoice\Functions\filterInput($_POST, '_billing_ref_norm_rc', FILTER_UNSAFE_RAW);
        if (! ReverseChargeSettings::supportsNormativeReference()) {
            $refNorm = '';
        }

        $orderPaymentMethod = \WcElectronInvoice\Functions\invoicePaymentMethodOrderCode($order);
        if (! $payment) {
            $payment = $orderPaymentMethod;
        }

        try {
            // Update custom meta
            $metaData = $order->get_meta_data();
            if (! empty($metaData)) {
                foreach ($metaData as $meta) {
                    if ($meta instanceof \WC_Meta_Data) {
                        $data = $meta->get_data();
                        if ('nature_rc' === $data['key'] || '_billing_nature_rc' === $data['key']) {
                            $order->update_meta_data('nature_rc', $nature);
                        } elseif ('ref_norm_rc' === $data['key'] || '_billing_ref_norm_rc' === $data['key']) {
                            $order->update_meta_data('ref_norm_rc', $refNorm);
                        }
                    }
                }
            }

            if ($number) {
                $order->update_meta_data('order_number_invoice', intval($number));
                // Update formatted
                setFormattedInvoiceNumber($order, 'invoice', true);
            }

            if ($payment) {
                $order->update_meta_data('refund_payment_method', $payment);
            }

            if ($date && $hour && $minute) {
                $date = gmdate('Y-m-d H:i', strtotime($date . ' ' . (int)$hour . ':' . (int)$minute));
                $order->set_date_completed($date);
            }

            // Save
            $order->save();
        } catch (\Exception $e) {
            echo 'dev' === WC_EL_INV_ENV ? esc_html__("No date completed updated: ",
                    WC_EL_INV_TEXTDOMAIN) . esc_html($e->getMessage()) : '';
        }
    }

    /**
     * Admin Store meta
     *
     * @param $orderID
     *
     * @since 1.0.0
     *
     */
    public function saveRefundMetaBox($orderID)
    {
        $order        = wc_get_order($orderID);
        $wcOrderClass = \WcElectronInvoice\Functions\wcOrderClassName($order, '\WC_Order');

        if (! $order instanceof $wcOrderClass) {
            return;
        }

        // Get Refunds
        $refunds = $order->get_refunds();
        if (! empty($refunds)) {
            foreach ($refunds as $refund) {
                // Order refund
                $wcOrderRefundClass = \WcElectronInvoice\Functions\wcOrderClassName($refund, '\WC_Order_Refund');
                if (! $refund instanceof $wcOrderRefundClass) {
                    return;
                }

                $refundID = $refund->get_id();

                // @codingStandardsIgnoreLine
                $number = \WcElectronInvoice\Functions\filterInput($_POST, "refund_number_invoice-{$refundID}",
                    FILTER_SANITIZE_NUMBER_INT);
                $date   = \WcElectronInvoice\Functions\filterInput($_POST, "refund_date_invoice-{$refundID}",
                    FILTER_UNSAFE_RAW);
                $hour   = \WcElectronInvoice\Functions\filterInput($_POST, "refund_hours_invoice-{$refundID}",
                    FILTER_UNSAFE_RAW);
                $minute = \WcElectronInvoice\Functions\filterInput($_POST, "refund_minutes_invoice-{$refundID}",
                    FILTER_UNSAFE_RAW);

                try {
                    if ($number) {
                        $refund->update_meta_data("refund_number_invoice-{$refundID}", intval($number));
                        // Update formatted
                        setFormattedInvoiceNumber($refund, 'credit_note', true);
                    }

                    if ($date && $hour && $minute) {
                        $date = gmdate('Y-m-d H:i', strtotime($date . ' ' . (int)$hour . ':' . (int)$minute));
                        $refund->set_date_created($date);
                    }

                    // Save
                    $refund->save();
                } catch (\Exception $e) {
                    echo 'dev' === WC_EL_INV_ENV ? esc_html__("No date created updated: ",
                            WC_EL_INV_TEXTDOMAIN) . esc_html($e->getMessage()) : '';
                }
            }
        }
    }

    /**
     * Safe wrapper for WooCommerce checkout check.
     *
     * @return bool
     */
    private static function isCheckout(): bool
    {
        return function_exists('\\is_checkout') && \is_checkout();
    }

    /**
     * In PEPPOL context, prevent classic checkout from persisting billing_sdi_type.
     *
     * @return void
     */
    private static function removeClassicCheckoutSdiPostedData(): void
    {
        static $hooked = false;

        if (! $hooked) {
            add_filter('woocommerce_checkout_posted_data', function ($data) {
                unset($data['billing_sdi_type']);

                return $data;
            }, PHP_INT_MAX);
            $hooked = true;
        }

        if (isset($_POST['billing_sdi_type'])) {
            $_POST['billing_sdi_type'] = '';
        }
    }

    /**
     * Safe wrapper for WooCommerce account page check.
     *
     * @return bool
     */
    private static function isAccountPage(): bool
    {
        return function_exists('\\is_account_page') && \is_account_page();
    }

    /**
     * Checkout Store
     *
     * @param $orderID
     *
     * @since 1.0.0
     *
     */
    public function store($orderID)
    {
        if (! empty($this->keys)) {
            $order         = wc_get_order($orderID);
            $postedCountry = (string)\WcElectronInvoice\Functions\filterInput($_POST, 'billing_country',
                FILTER_UNSAFE_RAW);
            $orderCountry  = '' !== trim($postedCountry) ? $postedCountry : (string)$order->get_billing_country();
            $isPeppolOrder = self::isPeppolCountry($orderCountry);

            foreach ($this->keys as $key) {
                if ($isPeppolOrder && (false !== strpos((string)$key, 'sdi_type') || false !== strpos((string)$key,
                            'tax_code'))) {
                    $order->update_meta_data(self::$metaKey . $key, '');
                    continue;
                }

                // @codingStandardsIgnoreLine
                $value = \WcElectronInvoice\Functions\filterInput($_POST, self::$metaKey . $key,
                    FILTER_UNSAFE_RAW);

                if (! empty($_POST[self::$metaKey . $key]) && $value) {
                    $order->update_meta_data(self::$metaKey . $key, \WcElectronInvoice\Functions\sanitize($value));
                }
            }

            // Save
            $order->save();
        }
    }
}
