<?php
/**
 * OxygenOrder Class File
 *
 * @package Oxygen
 * @summary Class to add WooCommerce order hooks
 * @version 2.0.40
 * @since  1.0.0
 */

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

use Automattic\WooCommerce\Internal\DataStores\Orders\CustomOrdersTableController;

/**
 * Oxygen MyData Class
 */
class OxygenOrder {

    /**
     * Singleton Instance of OxygenOrder
     *
     * @var OxygenOrder
     **/
    private static $instance = null;

    /**
     * WooCommerce order ID
     *
     * @var int order ID
     */
    private static $order_id = null;


    /**
     * Singleton init Function
     *
     * @static
     */
    public static function init() {
        if ( ! self::$instance ) {
            self::$instance = new self();
        }

        return self::$instance;
    }

    /**
     * Oxygen Constructor
     */
    private function __construct() {
        $this->init_hooks();
    }

    /**
     *  Add all order hooks
     *
     * @return void
     */
    private function init_hooks() {

        add_action( 'add_meta_boxes', array( $this, 'add_meta_box' ) );
        add_action( 'admin_init', array( $this, 'oxygen_actions' ) );

        add_action( 'woocommerce_new_order', array( $this, 'on_order_create' ), 10, 1 );
        add_action( 'woocommerce_thankyou', array( $this, 'on_order_create' ), 10, 1 );
        add_action( 'woocommerce_order_status_changed', array( $this, 'run_on_woocommerce_bulk_order_status' ), 5, 4 );

        // add extra order list column(s).
        add_filter( 'manage_edit-shop_order_columns', array( $this, 'shop_order_column' ), 20 );
        add_filter( 'woocommerce_shop_order_list_table_columns', array( $this, 'shop_order_column' ), 20 );
        add_action( 'manage_shop_order_posts_custom_column', array( $this, 'orders_list_column_content' ), 20, 2 );
        add_action( 'woocommerce_shop_order_list_table_custom_column', array( $this, 'orders_list_column_content' ), 20, 2 );

        if( 'yes' === get_option( 'oxygen_enable_shipping_data' ) ) {
            add_action( 'woocommerce_process_shop_order_meta', array( $this, 'save_custom_order_fields'),10, 1 );
            add_action( 'woocommerce_admin_order_data_after_order_details',  array( $this, 'display_custom_order_fields'), 20, 2 );
        }

        $user_view_invoices = OxygenHelperFunctions::get_option( 'oxygen_users_view_settings', true );
        if ( 'yes' === $user_view_invoices ) {
            add_filter( 'woocommerce_my_account_my_orders_actions', array( $this, 'my_account_my_orders_actions' ), 9999, 2 );
        }

        if ( 'yes' !== get_option( 'oxygen_only_receipts' ) ) {/* otan 8elw kai apodeixeis kai timologia */
            if ( 'yes' === get_option( 'oxygen_self_fields' ) ) {
                /*  Otan to pedio me ta pedia tou oxygen einai enabled  */
                add_filter( 'woocommerce_checkout_fields', array( $this, 'override_checkout_fields' ) );
                add_filter( 'woocommerce_checkout_process', array( $this, 'check_invoice_fields' ) );
                add_filter( 'woocommerce_address_to_edit', array( $this, 'oxygen_address_to_edit' ), 10, 2 );
                add_filter( 'woocommerce_order_formatted_billing_address', array( $this, 'oxygen_order_formatted_billing_address' ), 10, 2 );
                add_filter( 'woocommerce_my_account_my_address_formatted_address', array( $this, 'oxygen_my_account_my_address_formatted_address' ), 10, 3 );
                add_filter( 'woocommerce_formatted_address_replacements', array( $this, 'oxygen_formatted_address_replacements' ), 10, 2 );
                add_filter( 'woocommerce_admin_billing_fields', array( $this, 'oxygen_admin_billing_fields' ), 10, 1 );
                add_filter( 'woocommerce_ajax_get_customer_details', array( $this, 'oxygen_found_customer_details' ), 10, 3 );
                add_filter( 'woocommerce_customer_meta_fields', array( $this, 'oxygen_customer_meta_fields' ), 10, 1 );
            }
        }
        /* Otan exw MONO apodeixeis den 8elw na emfanizetai to checkbox sto checkout , oute na fortwnontai ola ta parapanw hooks */
    }

    /**
     *  Create the metabox for Oxygen order data.
     *
     *  @return void
     */
    public function add_meta_box() {

        try {
            $screen = function_exists( 'wc_get_page_screen_id' )
                    ? wc_get_page_screen_id( 'shop-order' )
                    : 'shop_order';

            add_meta_box( 'oxygen_order_extra', __( 'Oxygen', 'oxygen' ), array( $this, 'order_metabox_content' ), $screen, 'side', 'core' );

        } catch ( \Exception $e ) {
            OxygenHelperFunctions::debug( array('At function add_meta_box wc_get_container is null.') );
        }

    }

    /**
     *  Create the content of the Oxygen order metabox.
     *
     *  @param object $post_or_order_object WC_Order | WP_Post .
     *
     *  @return void
     */
    public function order_metabox_content( $post_or_order_object ) {

        $order = ( $post_or_order_object instanceof WP_Post ) ? wc_get_order( $post_or_order_object->ID ) : $post_or_order_object;

        if ( ! $order ) {
            return;
        }

        self::$order_id = $order->get_id();

        $check = OxygenApi::check_connection();

        if ( !$check || $check['code'] !== 200) {
            ?>
            <a href="<?php echo esc_url( get_admin_url() . 'admin.php?page=wc-settings&tab=oxygen_tab' ); ?>">
                <?php esc_html_e( 'Oxygen setup', 'oxygen' ); ?>
            </a>
            <?php
            return;
        }

        $nonce                     = wp_create_nonce( 'oxygen-' . $order->get_id() . '-nonce' );
        $_oxygen_payment_note_type = sanitize_text_field( $order->get_meta( $order->get_id(), '_oxygen_payment_note_type', true ) );
        $document_type_names       = OxygenHelperFunctions::document_type_names_box();

        $invoice_data = $order->get_meta( '_oxygen_invoice', true );
        $notice_data  = $order->get_meta( '_oxygen_notice', true );

        print_buttons_for_view_download_pdf( $invoice_data, $notice_data ); /* print buttons for download and show document */

        if ( empty( $invoice_data ) ) {
            wp_nonce_field( 'oxygen-' . $order->get_id() . '-nonce', 'oxygen_nonce' );
            /* ONLY RECEIPTS */
            if ( 'yes' === get_option( 'oxygen_only_receipts' ) ) {
                unset( $document_type_names['tpda_intra'] );
                unset( $document_type_names['tpy_intra'] );
                unset( $document_type_names['tpda'] );
                unset( $document_type_names['tpy'] );
            }
            /* INTRA COMMUNITY INVOICES DISABLED */
            if ( 'no' === get_option( 'oxygen_enable_intra_community_invoice' ) ) {
                unset( $document_type_names['tpda_intra'] );
                unset( $document_type_names['tpy_intra'] );
            }
            ?>

            <div>
                <label for="_oxygen_payment_note_type"><?php esc_html_e( 'Document Type', 'oxygen' ); ?></label>
                <p>
                    <select name="_oxygen_payment_note_type" id="_oxygen_payment_note_type" class="wide wide-fat">
                        <?php foreach ( $document_type_names as $key => $type ) { ?>
                            <option value="<?php echo esc_attr( $key ); ?>" <?php selected( $_oxygen_payment_note_type, $key ); ?>><?php echo esc_html( $type ); ?></option>
                        <?php } ?>

                    </select><br />
                </p>
            </div>
        <?php } ?>
        <div>
            <?php if ( empty( $invoice_data ) ) { ?>
                <p>
                    <a href="<?php echo esc_url( get_admin_url() . 'post.php?post=' . intval( $order->get_id() ) . '&action=edit&oxygen=create_invoice&_wpnonce=' . esc_attr( $nonce ) ); ?>" class="oxy_create_document create_invoice disabled"><?php esc_html_e( 'Create Document', 'oxygen' ); ?></a>
                </p>
            <?php } ?>
            <p>
                <a href="<?php echo esc_url( get_admin_url() . 'post.php?post=' . intval( $order->get_id() ) . '&action=edit&oxygen=create_notice&_wpnonce=' . esc_attr( $nonce ) ); ?>" class="oxy_create_notice action create_notice"><?php esc_html_e( 'Create Notice', 'oxygen' ); ?></a>
            </p>
        </div>

        <?php

        if ( ! isset( $_GET['oxygen'] ) || ! isset( $_GET['_wpnonce'] ) ) { // phpcs:ignore

            WC_Admin_Notices::remove_notice( 'oxygen_payment_note_missing' );
            WC_Admin_Notices::remove_notice( 'oxygen_invalid_action' );
            WC_Admin_Notices::remove_notice( 'oxygen_payment_method_missing' );
            WC_Admin_Notices::remove_notice( 'oxygen_invoice_info_missing' );
            WC_Admin_Notices::remove_notice( 'oxygen_contact_error' );
            WC_Admin_Notices::remove_notice( 'oxygen_invoice_error' );
            WC_Admin_Notices::remove_notice( 'oxygen_invoice_success' );
            WC_Admin_Notices::remove_notice( 'oxygen_notice_success' );
            WC_Admin_Notices::remove_notice( 'oxygen_no_api' );
        }
    }

    /**
     *  Trigger Oxygen actions for invoice and notices creation.
     *
     *  @return void
     */
    public function oxygen_actions() {

        if ( ! is_admin() ) {
            return;
        }

        if ( ! isset( $_GET['oxygen'] ) || ! isset( $_GET['_wpnonce'] ) ) {

            return;
        }

        $oxygen_api_key = get_option( 'oxygen_api_key' );

        if ( empty( $oxygen_api_key ) ) {
            /* translators: %s: URL to Oxygen platform */
            WC_Admin_Notices::add_custom_notice( 'oxygen_no_api', sprintf( __( '<p>Oxygen API Κey not found. <a href="%s">Click here to create one.</a>.</p>', 'oxygen' ), get_admin_url() . 'admin.php?page=wc-settings&tab=oxygen' ) );
            WC_Admin_Notices::output_custom_notices();

            WC_Admin_Notices::remove_notice( 'oxygen_no_api' );

            return;
        }

        if ( isset( $_REQUEST['_wpnonce'] ) ) {
            $nonce = sanitize_key( $_REQUEST['_wpnonce'] );
        } else {
            return;
        }

        $post_id = 0;

        if ( isset( $_REQUEST['post'] ) ) {
            $post_id = intval( $_REQUEST['post'] );
        }

        $verify = wp_verify_nonce( $nonce, 'oxygen-' . $post_id . '-nonce' );

        if ( ! $verify ) {

            WC_Admin_Notices::add_custom_notice( 'oxygen', '<p>' . __( 'Could not verify request', 'oxygen' ) . '</p>' );
            WC_Admin_Notices::output_custom_notices();

            WC_Admin_Notices::remove_notice( 'oxygen' );

            return;
        }

        // Disable WP Obj Caching ...
        wp_using_ext_object_cache( false );
        wp_cache_flush();
        wp_cache_init();

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

        $oxygen_action = sanitize_text_field( wp_unslash( $_GET['oxygen'] ) );

        $_GET['notetype'] = false;

        if ( ( isset( $_GET['_oxygen_payment_note_type'] ) && ! empty( $_GET['_oxygen_payment_note_type'] ) ) || ( empty( $_GET['_oxygen_payment_note_type'] ) && 'create_notice' === $oxygen_action ) ) {

            if ( 'create_invoice' === $oxygen_action ) {

                $_GET['notetype'] = 'invoice';

                $this->create_invoice( $order->get_id(), $order );

            } elseif ( 'create_notice' === $oxygen_action ) {

                $_GET['notetype'] = 'notice';

                $this->create_invoice( $order->get_id(), $order );

            } else {

                WC_Admin_Notices::add_custom_notice( 'oxygen_invalid_action', '<p>' . __( 'Invalid Oxygen action', 'oxygen' ) . '</p>' );
            }
        } else {

            WC_Admin_Notices::add_custom_notice( 'oxygen_payment_note_missing', '<p>' . __( 'Document Type has not been defined', 'oxygen' ) . '</p>' );

        }
    }

    /**
     *  Adding 1 new column with their titles (keeping "Total" and "Actions" columns at the end).
     *
     *  @param array $columns the order list admin columns array.
     *  @return array
     */
    public function shop_order_column( $columns ) {

        $reordered_columns = array();

        // Inserting columns to a specific location.
        foreach ( $columns as $key => $column ) {
            $reordered_columns[ $key ] = $column;
            if ( 'order_status' === $key ) {
                // Inserting after "Status" column.
                $reordered_columns['oxygen'] = __( 'Oxygen', 'oxygen' );
            }
        }
        return $reordered_columns;
    }

    /**
     *  Adding custom fields meta data on new column(s)
     *
     *  @param string $column name of the column.
     *  @param int    $post_id post ID.
     *  @return void
     */
    public function orders_list_column_content( $column, $post_id ) {

        $order = wc_get_order( $post_id );

        switch ( $column ) {
            case 'oxygen':
                // Get custom post meta data.
                $invoice_data = $order->get_meta( '_oxygen_invoice', true );
                $notice_data  = $order->get_meta( '_oxygen_notice', true );

                print_buttons_for_view_download_pdf( $invoice_data, $notice_data );

                break;
        }
    }

    /**
     *  Create customer billing address extra fields.
     *
     *  @param array $fields customer billing address data.
     *  @return array
     */
    public function override_checkout_fields( $fields ) {

        $fields['billing']['billing_vat'] = array(
                'type'        => 'text',
                'label'       => __( 'VAT Number', 'oxygen' ),
                'placeholder' => __( 'ex. 1234567890', 'oxygen' ),
                'priority'    => 160,
                'class'       => array( 'form-row-wide', 'custom-vat-field' ),


        );
        $fields['billing']['billing_job']        = array(
                'type'        => 'text',
                'label'       => __( 'Job Description', 'oxygen' ),
                'placeholder' => __( 'ex. Accountant', 'oxygen' ),
                'priority'    => 161,
                'class'       => array( 'form-row-wide', 'custom-job-field' ),

        );
        $fields['billing']['billing_tax_office'] = array(
                'type'        => 'text',
                'label'       => __( 'Tax Office', 'oxygen' ),
                'placeholder' => __( 'ex. Athens', 'oxygen' ),
                'priority'    => 162,
                'class'       => array( 'form-row-wide', 'custom-tax-field' ),

        );
        $fields['billing']['billing_invoice']    = array(
                'type'     => 'checkbox',
                'label'    => __( 'I need an invoice', 'oxygen' ),
                'id'       => 'billing_invoice',
                'priority' => 159,
                'class'       => array( 'form-row-wide', 'custom-invoice-field' ),
        );

        $fields['billing']['billing_company'] = array(
                'type'        => 'text',
                'label'       => __( 'Company Name', 'oxygen' ),
                'placeholder' => __( 'ex. MyCompany', 'oxygen' ),
                'priority'    => 163,
                'class'       => array( 'form-row-wide', 'custom-company-field' ),
        );

        return $fields;
    }

    /**
     *  On order create actions
     *
     *  @param int $order_id the ID of the order.
     *  @return void
     */
    public function on_order_create( $order_id ) {

        $order = wc_get_order( $order_id );

        /* get defaults options for each type of document */
        $defaults_options = OxygenHelperFunctions::get_default_option_documents();

        $oxygen_default_document_type   = OxygenHelperFunctions::get_option( 'oxygen_default_document_type' );
        $oxygen_default_receipt_doctype = $defaults_options ['oxygen_default_receipt_doctype'];
        $oxygen_default_invoice_doctype = $defaults_options ['oxygen_default_invoice_doctype'];
        $oxygen_default_intra_doctype   = $defaults_options ['oxygen_default_intra_doctype'];

        $get_billing_vat_info = OxygenHelperFunctions::get_billing_vat_info( $order_id );

        OxygenHelperFunctions::debug( array( '----- NEW ORDER -----' . json_encode($get_billing_vat_info,true) ) , 'info' );
        OxygenHelperFunctions::debug( array( '----- ORDER DATA -----' . json_encode($order->get_meta_data() ) ), 'info');

        if ( false !== $get_billing_vat_info && 'invoice' === $oxygen_default_document_type ) {

            OxygenHelperFunctions::debug( array( '----- DOC TYPE IS INVOICE  billing_invoice-----' . $get_billing_vat_info['billing_invoice'] ), 'info' );
            OxygenHelperFunctions::debug( array( '----- DOC TYPE IS INVOICE  get_billing_country-----' . $order->get_billing_country() ), 'info' );

            if ( (1 === $get_billing_vat_info['billing_invoice'] || '1' === $get_billing_vat_info['billing_invoice']) && 'GR' === $order->get_billing_country() ) {

                OxygenHelperFunctions::debug( array( '----- COUNTRY HAS TO BE GR BUT IS    -----' . $order->get_billing_country() ), 'info' );

                $order->update_meta_data( '_oxygen_payment_note_type', $oxygen_default_invoice_doctype ); /* kanoniko timologio */

            } elseif ( (1 === $get_billing_vat_info['billing_invoice'] || '1' === $get_billing_vat_info['billing_invoice']) && 'GR' !== $order->get_billing_country() ) {

                OxygenHelperFunctions::debug( array( '----- NOT COUNTRY GR BUT IS    -----' . $order->get_billing_country() ), 'info' );

                $order->update_meta_data( '_oxygen_payment_note_type', $oxygen_default_intra_doctype ); /* endokoinotiko timologio */

            } elseif ( 0 === $get_billing_vat_info['billing_invoice'] || '0' === $get_billing_vat_info['billing_invoice'] ) {
                OxygenHelperFunctions::debug( array( '----- DOC TYPE IS RECEIPT  -----' ), 'info' );

                if ( ! empty( $oxygen_default_receipt_doctype ) ) {
                    $order->update_meta_data( '_oxygen_payment_note_type', $oxygen_default_receipt_doctype );
                }
            }
        } else {
            OxygenHelperFunctions::debug( array( '----- NOTHING MATCH  -----' ), 'warning' );

        }

        remove_action( 'woocommerce_after_order_object_save', array( $this, 'save_order' ), 20 );
        $order->save_meta_data();
        $order->save();
        add_action( 'woocommerce_after_order_object_save', array( $this, 'save_order' ), 20, 1 );
    }

    /**
     *  On order save actions
     *
     *  @param object $order WC_Order.
     *  @return void
     */
    public function save_order( $order ) {

        if ( ! is_admin() ) {
            return;
        }

        if ( defined( 'DOING_AUTOSAVE' ) && DOING_AUTOSAVE ) {
            return;
        }

        if ( ! isset( $_POST['oxygen_nonce'] ) ) {
            return;
        }

        $post_id = $order->get_id();

        if ( ! wp_verify_nonce( sanitize_key( $_POST['oxygen_nonce'] ), 'oxygen-' . $post_id . '-nonce', 'oxygen_nonce' ) ) {
            return;
        }

        // Disable WP Obj Caching ...
        wp_using_ext_object_cache( false );
        wp_cache_flush();
        wp_cache_init();

        if ( isset( $_POST['_oxygen_payment_note_type'] ) ) {

            $order->update_meta_data( '_oxygen_payment_note_type', sanitize_text_field( wp_unslash( $_POST['_oxygen_payment_note_type'] ) ) );

        }

        /* auto ginetai gia na mhn dhmiourgountai diplotypes notices epeidh trexei kai to order_change kai mporei notices  > 1 */
        if ( ! is_edit_order_screen() ) {

            OxygenHelperFunctions::debug( array( '----- execution by edit order page in admin area  -----' ), 'info' );

            $oxygen_order_status = str_replace( 'wc-', '', OxygenHelperFunctions::get_option( 'oxygen_order_status' ) );
            $_oxygen_invoice     = $order->get_meta( '_oxygen_invoice', true );

            if ( empty( $_oxygen_invoice ) && isset( $_POST ) && isset( $_POST['order_status'] ) ) {

                if ( sanitize_text_field( wp_unslash( $_POST['order_status'] ) ) === 'wc-' . $oxygen_order_status ) {

                    $oxygen_default_document_type      = OxygenHelperFunctions::get_option( 'oxygen_default_document_type' );
                    $_GET['notetype']                  = ( ! empty( $oxygen_default_document_type ) ? $oxygen_default_document_type : 'invoice' ); // default to invoice.
                    $_GET['_oxygen_payment_note_type'] = $order->get_meta( '_oxygen_payment_note_type', true );

                    if ( isset( $_GET['notetype'] ) ) {
                        OxygenHelperFunctions::debug(
                                array( '--- in save order notetype is -- ', sanitize_text_field( wp_unslash( $_GET['notetype'] ) ) ),
                                'info'
                        );
                    }

                    add_action( 'woocommerce_order_status_' . $oxygen_order_status, array( $this, 'create_invoice' ), 10, 2 );
                }
            }
        } else {
            OxygenHelperFunctions::debug( array( '----- save order executed elsewhere from admins side -----'), 'info' );
        }
        remove_action( 'woocommerce_after_order_object_save', array( $this, 'save_order' ), 20 );
        $order->save_meta_data();
        $order->save();
        add_action( 'woocommerce_after_order_object_save', array( $this, 'save_order' ), 20, 1 );
    }
    /**
     *  Create order invoice on Oxygen API
     *
     *  @param integer $order_id the WC order ID.
     *  @param object  $order WC_Order.
     *  @return array|false
     */
    public function create_invoice( $order_id, $order ) {

        OxygenHelperFunctions::debug( array( 'Creating invoice for order: ' . $order_id ), 'info' );

        // Prepare concurrency guard variables
        $__oxygen_lock_acquired = false;
        $__oxygen_lock_token    = '';
        $__oxygen_lock_key      = '_oxygen_invoice_creating';

        // Disable WP Obj Caching ...
        wp_using_ext_object_cache( false );
        wp_cache_flush();
        wp_cache_init();

        $_oxygen_invoice = $order->get_meta( '_oxygen_invoice', true );

        // abort duplicate invoice.
        if ( ! empty( $_oxygen_invoice ) && ! empty( $_GET['_oxygen_payment_note_type'] ) && 'notice' !== $_GET['_oxygen_payment_note_type'] ) {

            $order->add_order_note( 'Duplicate oxygen document aborted' );
            return false;
        }

        // If we are NOT on the thankyou page.
        if ( ! ( is_checkout() && is_wc_endpoint_url( 'order-received' ) ) ) {

            if ( array_key_exists( '_wpnonce', $_REQUEST ) ) {
                $nonce = sanitize_key( $_REQUEST['_wpnonce'] );
            } else {
                OxygenHelperFunctions::debug( array( 'Creating invoice .... nonce does not exist in request.' ), 'warning' );
                return false;
            }

            $verify = wp_verify_nonce( $nonce, 'oxygen-' . $order_id . '-nonce' );

            if ( ! $verify && 0 === $order_id ) {

                $log = array( '----------------- Could not verify request ' . gmdate( 'Y-m-d H:i:s' ) . ' -----------------', array( $order_id, __( 'Could not verify request', 'oxygen' ) ) );
                OxygenHelperFunctions::debug( $log );

                WC_Admin_Notices::add_custom_notice( 'oxygen', '<p>' . __( 'Could not verify request', 'oxygen' ) . '</p>' );
                WC_Admin_Notices::output_custom_notices();

                WC_Admin_Notices::remove_notice( 'oxygen' );

                return false;
            }
        }

        // Concurrency guard: prevent duplicate invoice creation for same order
        if ( function_exists( 'wp_generate_uuid4' ) ) {
            $__oxygen_lock_token = wp_generate_uuid4();
        } else {
            $__oxygen_lock_token = uniqid( 'oxy_', true );
        }

        // Try to acquire a unique "creating" flag on the order. This is atomic in WP/DB level.
        $__oxygen_lock_acquired = add_post_meta( $order_id, $__oxygen_lock_key, $__oxygen_lock_token, true );
        OxygenHelperFunctions::debug( array( 'Lock acquire attempt', array(
                'order_id' => $order_id,
                'pid'      => function_exists('getmypid') ? getmypid() : 'n/a',
                'acquired' => $__oxygen_lock_acquired,
                'token'    => $__oxygen_lock_token,
        )), 'info' );

        if ( ! empty( $_oxygen_invoice ) && ( ! $__oxygen_lock_acquired ) ) {
            // Another process is already creating the invoice; abort to avoid duplicates.
            $order->add_order_note( 'Oxygen: another process is already creating the document. Aborting duplicate.' );
            OxygenHelperFunctions::debug( array( 'Duplicate prevention: lock already held for order', $order_id ), 'info' );
            return false;
        }

        // Ensure the lock is released at the end of the request regardless of path
        if ( function_exists( 'register_shutdown_function' ) ) {
            register_shutdown_function( function() use ( $order_id, $__oxygen_lock_key, $__oxygen_lock_token ) {
                delete_post_meta( $order_id, $__oxygen_lock_key, $__oxygen_lock_token );
            } );
        }

        // Re-check invoice meta now that we hold the lock (race-safe double-check)
        $_oxygen_invoice = $order->get_meta( '_oxygen_invoice', true );
        if ( ! empty( $_oxygen_invoice ) && 'invoice' === $_GET['_oxygen_payment_note_type'] ) {
            OxygenHelperFunctions::debug( array( 'Duplicate prevention: invoice already exists after lock for order', $order_id ), 'info' );
            return false;
        }

        $log = array( '----------------- creating_invoice ' . gmdate( 'Y-m-d H:i:s' ) . ' -----------------' );
        OxygenHelperFunctions::debug( $log, 'info' );

        $doc_key = false;
        if ( isset( $_GET['_oxygen_payment_note_type'] ) ) {
            $doc_key = sanitize_text_field( wp_unslash( $_GET['_oxygen_payment_note_type'] ) );
        }

        OxygenHelperFunctions::debug( array( 'doc key in create invoice is ' . $doc_key ) ,'debug' );

        if ( ! isset( $_GET['notetype'] ) ) {

            $log = array( '----------------- Invalid Document Type ' . gmdate( 'Y-m-d H:i:s' ) . ' -----------------', array( $order_id, __( 'Invalid Document Type', 'oxygen' ) ) );
            OxygenHelperFunctions::debug( $log );

            WC_Admin_Notices::add_custom_notice( 'oxygen_payment_note_missing', '<p>' . __( 'Invalid Document Type', 'oxygen' ) . '</p>' );

            return false;

        }

        $notetype = sanitize_text_field( wp_unslash( $_GET['notetype'] ) );

        OxygenHelperFunctions::debug( array( 'note type in create invoice is ' . $notetype ),'debug' );

        if ( 'notice' === $_GET['notetype'] ) {
            $doc_key = 'notice';
        }

        if ( isset( $_GET['oxygen'] ) && 'notice' !== $notetype && empty( $doc_key ) ) {

            $log = array( '----------------- Invalid Document Type ' . gmdate( 'Y-m-d H:i:s' ) . ' -----------------', array( $order_id, __( 'Document Type has not been defined', 'oxygen' ) ) );
            OxygenHelperFunctions::debug( $log );

            WC_Admin_Notices::add_custom_notice( 'oxygen_payment_note_missing', '<p>' . __( 'Document Type has not been defined', 'oxygen' ) . '</p>' );

            return false;

        }

        /* get defaults options for each type of document */
        $defaults_options = OxygenHelperFunctions::get_default_option_documents();

        $oxygen_default_document_type   = OxygenHelperFunctions::get_option( 'oxygen_default_document_type' );
        $oxygen_default_receipt_doctype = $defaults_options ['oxygen_default_receipt_doctype'];
        $oxygen_default_invoice_doctype = $defaults_options ['oxygen_default_invoice_doctype'];
        $oxygen_default_intra_doctype   = $defaults_options ['oxygen_default_intra_doctype'];

        $get_billing_vat_info = OxygenHelperFunctions::get_billing_vat_info( $order_id );

        if ( ! isset( $_GET['oxygen'] ) ) {
            // set the default document type.
            // is it selected to create an invoice.
            $should_create_invoice = false;

            if ( isset( $get_billing_vat_info['billing_invoice'] ) && ! empty( $get_billing_vat_info['billing_invoice'] ) ) {
                if ( false !== $get_billing_vat_info['billing_invoice'] ) {
                    if ( 'y' === strtolower( $get_billing_vat_info['billing_invoice'] ) || 1 === $get_billing_vat_info['billing_invoice'] || '1' === $get_billing_vat_info['billing_invoice'] || 'yes' === strtolower( $get_billing_vat_info['billing_invoice'] ) ) {
                        $should_create_invoice = true;
                    }
                }
            }

            if ( true === $should_create_invoice && 'invoice' === $oxygen_default_document_type ) {
                OxygenHelperFunctions::debug( array( '----- DOC TYPE IS INVOICE  billing_invoice-----' . $get_billing_vat_info['billing_invoice'] ) ,'debug' );
                OxygenHelperFunctions::debug( array( '----- DOC TYPE IS INVOICE  get_billing_country-----' . $order->get_billing_country() ),'debug' );

                if ( 'GR' === $order->get_billing_country() ) {
                    OxygenHelperFunctions::debug( array( '----- COUNTRY HAS TO BE GR BUT IS    -----' . $order->get_billing_country() ),'debug' );

                    $order->update_meta_data( '_oxygen_payment_note_type', $oxygen_default_invoice_doctype ); /* kanoniko timologio */

                    $doc_key = $oxygen_default_invoice_doctype;

                } elseif ( 'GR' !== $order->get_billing_country() ) {
                    OxygenHelperFunctions::debug( array( '----- NOT COUNTRY GR BUT IS    -----' . $order->get_billing_country() ),'debug' );

                    $order->update_meta_data( '_oxygen_payment_note_type', $oxygen_default_intra_doctype ); /* endokoinotiko timologio */

                    $doc_key = $oxygen_default_intra_doctype;

                }
            } elseif ( 0 == $get_billing_vat_info['billing_invoice'] ) {
                OxygenHelperFunctions::debug( array( '----- DOC TYPE IS RECEIPT  -----' ) ,'debug');

                if ( ! empty( $oxygen_default_receipt_doctype ) ) {
                    $order->update_meta_data( '_oxygen_payment_note_type', $oxygen_default_receipt_doctype );
                    $doc_key = $oxygen_default_receipt_doctype;
                }
            } else {
                OxygenHelperFunctions::debug( array( '----- NOTHING MATCH  -----' ),'warning' );
            }
        } else {

            $order->update_meta_data( '_oxygen_payment_note_type', $doc_key );
            OxygenHelperFunctions::debug( array( '---- ELSE create invoice ----', get_option( '_oxygen_payment_note_type', true ) ),'debug' );

        }
        OxygenHelperFunctions::debug( array( 'default document type is ', $oxygen_default_document_type . ' --- ' . $doc_key ),'debug' );

        $class_cat_subfix = OxygenHelperFunctions::find_subfix_mydata_category( $doc_key );
        $document_types   = OxygenHelperFunctions::document_types();
        $mydata_types     = OxygenHelperFunctions::mydata_document_types();
        $payment_methods  = OxygenHelperFunctions::get_option( 'oxygen_payment_methods' );

        if ( ! isset( $payment_methods[ $order->get_payment_method() ] ) ) {

            $log = array( '----------------- Invalid Document Type ' . gmdate( 'Y-m-d H:i:s' ) . ' -----------------', array( $order_id, __( 'Payment Method not found', 'oxygen' ) ) );
            OxygenHelperFunctions::debug( $log );

            WC_Admin_Notices::add_custom_notice( 'oxygen_payment_method_missing', '<p>' . __( 'Payment Method not found', 'oxygen' ) . '</p>' );

            return false;
        }

        /* select contact id or create new */
        $oxygen_customer_id = OxygenHelperFunctions::select_contact_id_per_invoice_type( $notetype, $doc_key, $order, $order_id );

        if ( empty( $oxygen_customer_id ) ) {
            OxygenHelperFunctions::debug( array( '-------------- Contact not created please check contact data and try again. ------------' ) );
            return false;
        }

        if ( 'notice' !== $notetype ) {
            if ( ( 'tpda' === $doc_key || 'tpy' === $doc_key ) && false === $get_billing_vat_info ) {

                $log = array( '----------------- Invalid Document Type ' . gmdate( 'Y-m-d H:i:s' ) . ' -----------------', array( $order_id, __( 'Invoice Details are missing or incomplete', 'oxygen' ) ) );
                OxygenHelperFunctions::debug( $log );

                WC_Admin_Notices::add_custom_notice( 'oxygen_invoice_info_missing', '<p>' . __( 'Invoice Details are missing or incomplete', 'oxygen' ) . '</p>' );

                return false;

            }
        }

        $args = build_invoice_body( $order, $order_id, $notetype, $doc_key, $oxygen_customer_id, $payment_methods, $document_types, $mydata_types, $class_cat_subfix );
        OxygenHelperFunctions::debug( array( '-----------------ARGS-----------------', $args ), 'debug' );

        if ( 'invoice' === $notetype ) {
            if ( ! empty( $args ) && ! OxygenHelperFunctions::check_document_for_missing_fields( $order, $args, $notetype ,$doc_key) ) {
                return false;
            }
        }

        OxygenHelperFunctions::debug( array( '----------------- ' . $notetype . ' args log -----------------', $args, $order_id ), 'debug' );

        if ( 'notice' === $notetype ) {

            $args = apply_filters( 'oxygen/add_notice', $args, $order_id );

            if ( ! is_array( $args ) ) {
                OxygenHelperFunctions::debug(array('invalid_args for notice - oxygen/add_notice filter must return an array'),'debug');
            }
            $result = OxygenApi::add_notice( $args );

        } else {

            $result = OxygenApi::add_invoice( $args );
            OxygenHelperFunctions::debug( array( '----------------- Oxygen invoice creating for order ' . $order_id . ' -----------------', $result, $order_id ), 'info' );

        }

        if ( ! array( $result ) ) {
            OxygenHelperFunctions::debug( array( '----------------- results not array -----------------', $result, $order_id ) );
        }

        if ( is_array( $result ) && isset( $result['body'] ) ) {
            if ( is_wp_error( $result ) ) {
                OxygenHelperFunctions::debug( array( '----------------- results wp error from api -----------------', $result, $order_id ) );
            } else {
                $add_invoice = json_decode( $result['body'], true );
            }
        } elseif ( is_wp_error( $result ) ) {
            OxygenHelperFunctions::debug( array( '----------------- results wp error from api else -----------------', $result, $order_id ) );
        } else {
            $add_invoice = json_decode( $result, true );
        }

        if ( is_array( $add_invoice ) && isset( $add_invoice['id'] ) ) {

            /* remove all error messages on successfully doc creation  */
            if ( class_exists( 'WC_Admin_Notices' ) ) {
                foreach ( WC_Admin_Notices::get_notices() as $notice ) {
                    if ( strpos( $notice, 'oxygen_' ) === 0 ) {
                        WC_Admin_Notices::remove_notice( $notice );
                    }
                }
            }

            if ( 'notice' === $notetype ) {

                $order->update_meta_data( '_oxygen_notice', $add_invoice );
                WC_Admin_Notices::add_custom_notice( 'oxygen_notice_success', '<p class="oxygen_success">' . __( 'Notice created successfully', 'oxygen' ) . '</p>' );
                $this->send_invoice_email( $order, 'notice' );

            } else {

                $order->update_meta_data( '_oxygen_invoice', $add_invoice );

                if ( ! empty( $add_invoice ) ) {
                    WC_Admin_Notices::add_custom_notice( 'oxygen_invoice_success', '<p class="oxygen_success">' . __( 'Document created successfully', 'oxygen' ) . '</p>' );
                    $this->send_invoice_email( $order, 'invoice' );
                } else {
                    WC_Admin_Notices::add_custom_notice( 'oxygen_invoice_error', '<p class="oxygen_error">' . __( 'Could not create invoice', 'oxygen' ) . '</p>' );
                }
            }

            remove_action( 'woocommerce_after_order_object_save', array( $this, 'save_order' ), 20 );
            $order->save_meta_data();
            $order->save();
            add_action( 'woocommerce_after_order_object_save', array( $this, 'save_order' ), 20, 1 );

            if ( ! isset( $_GET['oxygen'] ) ) {
                return;
            }
        } else {

            $errors = array();
            if ( isset( $add_invoice['errors'] ) ) {
                foreach ( $add_invoice['errors'] as $error ) {
                    $errors[] = implode( ',', $error );
                }
            } else {
                $errors = $add_invoice;
            }

            if ( 'notice' === $notetype ) {

                if(is_string($errors)){
                    WC_Admin_Notices::add_custom_notice( 'oxygen_invoice_error',
                            '<p class="oxygen_error">' . __( 'Could not create notice', 'oxygen' ) . ' | ' . $errors . '</p>' );
                }else {
                    WC_Admin_Notices::add_custom_notice( 'oxygen_invoice_error',
                            '<p class="oxygen_error">' . __( 'Could not create notice', 'oxygen' ) . ' | ' . implode( ',',
                                    $errors ) . '</p>' );
                }
            } else {

                if ( is_string( $errors ) ) {
                    $message = $errors;
                } elseif ( is_array( $errors ) ) {
                    $message = implode( ', ', array_map( 'strval', $errors ) );
                } else {
                    $message = maybe_serialize( $errors ); // fallback for unexpected types (object, etc.)
                }

                WC_Admin_Notices::add_custom_notice(
                        'oxygen_invoice_error',
                        '<p class="oxygen_error">' .
                        __( 'Could not create invoice', 'oxygen' ) .
                        ' | ' . esc_html( $message ) .
                        '</p>'
                );
            }

            OxygenHelperFunctions::debug( array( '----------------- ' . $notetype . ' error -----------------', $args, $add_invoice ) );
        }

        remove_action( 'woocommerce_after_order_object_save', array( $this, 'save_order' ), 20 );
        $order->save_meta_data();
        $order->save();
        add_action( 'woocommerce_after_order_object_save', array( $this, 'save_order' ), 20, 1 );

        if ( is_admin() && current_user_can( 'manage_woocommerce' ) ) {

            wp_safe_redirect( get_admin_url() . 'post.php?post=' . $order_id . '&action=edit' );
            die;
        }
    }

    /**
     *  On notice/invoice creation send email attachment
     *
     *  @param object $order WC_Order.
     *  @param string $document_type is document type invoice/notice.
     *  @return void of attachments absolute path.
     */
    public static function send_invoice_email( $order, $document_type ) {

        OxygenHelperFunctions::debug( array( '--- in send_invoice_email -- ' ),'debug' );

        $oxygen_order_attachment = str_replace( 'wc-', '', OxygenHelperFunctions::get_option( 'oxygen_order_attachment' ) );

        if ( $order && 'yes' === $oxygen_order_attachment ) {

            $_oxygen_invoice = $order->get_meta( '_oxygen_invoice', true );

            if ( 'notice' === $document_type ) {
                $_oxygen_invoice = $order->get_meta( '_oxygen_notice', true );
            }

            $attachments = array();

            if ( ! empty( $_oxygen_invoice ) ) {
                $document_id = sanitize_text_field( $_oxygen_invoice['id'] );
                $doc_type    = sanitize_text_field( $_oxygen_invoice['document_type'] );
                $print_type  = 'a4';

                if ( '' === $doc_type && 'invoice' === $document_type ) {
                    WC_Admin_Notices::add_notice( 'error', 'Document type is empty' );
                } else {
                    $doc_types = array( 'p', 's', 'rs', 'rp' );

                    /* print invoices types documents */
                    if ( in_array( $doc_type, $doc_types, true ) ) {
                        $oxygen_pdf = OxygenApi::get_invoice_pdf( $document_id, $print_type );
                        if ( is_wp_error( $oxygen_pdf ) ) {
                            OxygenHelperFunctions::debug( array( 'Failed to retrieve PDF: ' . $oxygen_pdf->get_error_message() ) );
                            return;
                        }

                        $headers       = $oxygen_pdf['headers'];
                        $document_name = get_filename_from_disposition( $headers );
                    } else {
                        /* print notices types documents */
                        $oxygen_pdf = OxygenApi::get_notice_pdf( $document_id );
                        if ( is_wp_error( $oxygen_pdf ) ) {
                            OxygenHelperFunctions::debug( array( 'Failed to retrieve PDF: ' . $oxygen_pdf->get_error_message() ) );
                            return;
                        }

                        $headers       = $oxygen_pdf['headers'];
                        $document_name = get_filename_from_disposition( $headers );
                    }

                    $upload_dir  = wp_upload_dir();
                    $oxygen_path = $upload_dir['basedir'] . '/oxygen';
                    if ( ! is_dir( $oxygen_path ) ) {
                        wp_mkdir_p( $oxygen_path );
                    }

                    $pdf_path = $upload_dir['basedir'] . '/oxygen/' . $document_name;

                    $file_put = false;

                    if ( is_array( $oxygen_pdf ) && isset( $oxygen_pdf['body'] ) ) {
                        $file_put = file_put_contents( $pdf_path, $oxygen_pdf['body'] );
                    }

                    if ( ! empty( $file_put ) ) {

                        $order->update_meta_data( '_oxygen_pdf_attachment', $document_name );
                        $order->save_meta_data();

                        OxygenHelperFunctions::debug( array( '--- oxygen_pdf_document_name  -- ' . $order->get_meta( '_oxygen_pdf_attachment' ) ) , 'info' );
                        $attachments[] = $pdf_path;
                    } else {
                        WC_Admin_Notices::add_notice( 'error', 'Pdf file could not created for this document' );
                        OxygenHelperFunctions::debug(
                                array(
                                        '-------- email doc doesnt exist in folder -----',
                                        $document_name,
                                )
                        );
                    }
                }

                // Send the email with attachments after the delay.
                $mailer = WC()->mailer();
                $email  = $mailer->emails['WC_Email_Invoice_Email'];

                if ( $email->is_enabled() && ! empty( $attachments ) ) {

                    add_filter(
                            'woocommerce_email_attachments',
                            function ( $email_attachments, $email_id, $order ) use ( $attachments ) {
                                $email_attachments = array_merge( $email_attachments, $attachments );
                                OxygenHelperFunctions::debug( array( '--- merged attachments ', $email_attachments ) , 'debug');

                                return $email_attachments;
                            },
                            10,
                            3
                    );

                    $email->trigger( $order->get_id(), $order );
                    OxygenHelperFunctions::debug( array( '--- in custom email sent for order ' . $order->get_id() . ' ' . $document_type . ' has already sent' ) , 'info');

                    remove_filter( 'woocommerce_email_attachments', '__return_empty_array' );

                    self::delete_attachment_pdf_file();

                }
            } else {

                OxygenHelperFunctions::debug( array( '-------- empty pdf in send_invoice_email - empty invoice -----' ) , 'info' );
            }
        }
    }


    /**
     * Deletes all files inside the /uploads/oxygen/ directory.
     *
     * This method is used to clear generated PDF files or temporary attachments
     * from the Oxygen plugin's uploads directory. It ensures that only files within
     * the correct subdirectory are deleted by checking with `realpath()`.
     *
     * Uses `unlink()` to remove each file after verifying it's within the expected path.
     * Logs success or failure messages using `OxygenHelperFunctions::debug()`.
     *
     * @return void
     */
    public static function delete_attachment_pdf_file() {

        /* this unlink does not check is internal */
        $upload_dir  = wp_upload_dir();
        $oxygen_path = realpath( $upload_dir['basedir'] . '/oxygen/' );

        if ( $oxygen_path && is_dir( $oxygen_path ) ) {
            $files = glob( $oxygen_path . '/*' );

            foreach ( $files as $file ) {
                if ( is_file( $file ) && strpos( realpath( $file ), $oxygen_path ) === 0 ) {
                    wp_delete_file( $file );
                }
            }

            OxygenHelperFunctions::debug( array( '------ Documents deleted successfully from oxygen folder ----- ' ) , 'info');
        } else {
            OxygenHelperFunctions::debug( array( '------ Attention! Documents in oxygen files not deleted ----- ' ) );
        }
    }

    /**
     *  Create customer billing address extra fields.
     *
     *  @param array  $address customer billing address fields data.
     *  @param string $load_address address type.
     *  @return array
     */
    public function oxygen_address_to_edit( $address, $load_address ) {
        global $wp_query;

        if ( isset( $wp_query->query_vars['edit-address'] ) && 'billing' !== $wp_query->query_vars['edit-address'] ) {
            return $address;
        }

        if ( ! isset( $address['billing_vat'] ) ) {
            $address['billing_vat'] = array(
                    'label'       => __( 'VAT #', 'oxygen' ),
                    'placeholder' => _x( 'VAT #', 'placeholder', 'oxygen' ),
                    'required'    => false,
                    'class'       => array( 'form-row-first' ),
                    'value'       => sanitize_text_field( get_user_meta( get_current_user_id(), 'billing_vat', true ) ),
            );
        }

        if ( ! isset( $address['billing_job'] ) ) {
            $address['billing_job'] = array(
                    'label'       => __( 'Job Description', 'oxygen' ),
                    'placeholder' => _x( 'Job Description', 'placeholder', 'oxygen' ),
                    'required'    => false,
                    'class'       => array( 'form-row-last' ),
                    'value'       => sanitize_text_field( get_user_meta( get_current_user_id(), 'billing_job', true ) ),
            );
        }
        if ( ! isset( $address['billing_tax_office'] ) ) {
            $address['billing_tax_office'] = array(
                    'label'       => __( 'Tax Office', 'oxygen' ),
                    'placeholder' => _x( 'Tax Office', 'placeholder', 'oxygen' ),
                    'required'    => false,
                    'class'       => array( 'form-row-first' ),
                    'value'       => sanitize_text_field( get_user_meta( get_current_user_id(), 'billing_tax_office', true ) ),
            );
        }

        if ( ! isset( $address['billing_invoice'] ) ) {
            $address['billing_invoice'] = array(
                    'label'       => __( 'Issue invoice', 'oxygen' ),
                    'placeholder' => _x( 'Issue invoice', 'placeholder', 'oxygen' ),
                    'required'    => false,
                    'class'       => array( 'form-row-last' ),
                    'value'       => sanitize_text_field( get_user_meta( get_current_user_id(), 'billing_invoice', true ) ),
                    'type'        => 'checkbox',
            );
        }

        return $address;
    }

    /**
     *  Create customer billing address extra fields.
     *
     *  @param array  $fields customer meta data array.
     *  @param object $order WC_Order.
     *  @return array
     */
    public function oxygen_order_formatted_billing_address( $fields, $order ) {
        $fields['billing_vat']        = sanitize_text_field( $order->get_meta( '_billing_vat', true ) );
        $fields['billing_job']        = sanitize_text_field( $order->get_meta( '_billing_job', true ) );
        $fields['billing_tax_office'] = sanitize_text_field( $order->get_meta( '_billing_tax_office', true ) );
        $fields['billing_invoice']    = sanitize_text_field( $order->get_meta( '_billing_invoice', true ) );

        return $fields;
    }


    /**
     *  Adding new customer billing fields to the order.
     *
     *  @param array  $fields customer meta data array.
     *  @param int    $customer_id order user ID.
     *  @param string $type address type.
     *  @return array
     */
    public function oxygen_my_account_my_address_formatted_address( $fields, $customer_id, $type ) {

        if ( 'billing' === $type ) {
            $fields['vat']        = sanitize_text_field( get_user_meta( $customer_id, 'billing_vat', true ) );
            $fields['job']        = sanitize_text_field( get_user_meta( $customer_id, 'billing_job', true ) );
            $fields['tax_office'] = sanitize_text_field( get_user_meta( $customer_id, 'billing_tax_office', true ) );
            $fields['invoice']    = sanitize_text_field( get_user_meta( $customer_id, 'billing_invoice', true ) );
        }

        return $fields;
    }

    /**
     *  Adding new customer billing fields to the order.
     *
     *  @param array $address customer address data.
     *  @param array $args customer address data.
     *  @return array
     */
    public function oxygen_formatted_address_replacements( $address, $args ) {

        $address['{vat}']        = '';
        $address['{job}']        = '';
        $address['{tax_office}'] = '';
        $address['{invoice}']    = '';

        if ( ! empty( $args['vat'] ) ) {
            $address['{vat}'] = __( 'VAT #', 'oxygen' ) . ' ' . strtoupper( $args['vat'] );
        }
        if ( ! empty( $args['job'] ) ) {
            $address['{job}'] = __( 'Job Description', 'oxygen' ) . ' ' . strtoupper( $args['job'] );
        }
        if ( ! empty( $args['tax_office'] ) ) {
            $address['{tax_office}'] = __( 'Tax Office', 'oxygen' ) . ' ' . strtoupper( $args['tax_office'] );
        }
        if ( ! empty( $args['invoice'] ) ) {
            $address['{invoice}'] = __( 'Issue Invoice', 'oxygen' ) . ' ' . strtoupper( $args['invoice'] );
        }

        return $address;
    }

    /**
     *  Adding new customer billing fields to the order.
     *
     *  @param array $fields customer meta data array.
     *  @return array
     */
    public function oxygen_admin_billing_fields( $fields ) {

        $fields['vat']        = array(
                'label' => __( 'VAT #', 'oxygen' ),
                'show'  => true,
        );
        $fields['job']        = array(
                'label' => __( 'Job Description', 'oxygen' ),
                'show'  => true,
        );
        $fields['tax_office'] = array(
                'label' => __( 'Tax Office', 'oxygen' ),
                'show'  => true,
        );
        $fields['invoice']    = array(
                'label'             => __( 'Issue Invoice', 'oxygen' ),
                'show'              => true,
                'type'              => 'number',
                'description'       => __( '1 is on, 0 is off', 'oxygen' ),
                'custom_attributes' => array(
                        'min' => 0,
                        'max' => 1,
                ),
        );

        return $fields;
    }

    public static function display_custom_order_fields( $order ) {

        $fields = OxygenHelperFunctions::get_custom_admin_order_fields();

        echo '<div class="order_data_column oxygen_admin_order_page form-field-wide" style="padding-top:20px;">';
        echo '<div style="display:flex;align-items:center;justify-content:space-between;margin-top:10px;">
                <h3 style="margin:0!important;">' . __( 'Oxygen - Shipping Data', 'oxygen' ) . '</h3>
                <span id="edit_shipping_data" class="dashicons dashicons-edit" style="font-size:14px;opacity:0.5;cursor:pointer;"></span></div>';

        // 👇 Add your button/link here
        echo '<div style="margin-top:20px;"><a href="#" class="load_shipping_data" id="copy_shipping_details">' . __( 'Load from general settings Oxygen', 'oxygen' ) . '</a></div>';

        echo '<div id="shipping_box_data" style="display:none;">';

        foreach ( $fields as $id => $field ) {

            if ( isset($field['type']) && $field['type'] === 'title' ) {
                echo '<h4 class="oxygen-section-title" style="padding:20px 0;font-weight:600;font-size: 13.5px!important;">' . esc_html($field['title']) . '</h4>';
                continue;
            }

            $value = $order->get_meta($id,true);

            echo '<div class="oxygen-form-row">';
            echo '<div class="oxygen-form-label">';
            echo '<label for="' . esc_attr($id) . '"><strong>' . esc_html($field['label']) . '</strong></label>';
            echo '</div>';
            echo '<div class="oxygen-form-field">';

            if ( $field['type'] === 'select' && !empty($field['options']) ) {
                echo '<select name="' . esc_attr($id) . '" id="' . esc_attr($id) . '">';
                foreach ( $field['options'] as $k => $v ) {
                    echo '<option value="' . esc_attr($k) . '" ' . selected($value, $k, false) . '>' . esc_html($v) . '</option>';
                }
                echo '</select>';
            } elseif ( $field['type'] === 'textarea' ) {
                echo '<textarea name="' . esc_attr($id) . '" id="' . esc_attr($id) . '" rows="2" style="width:100%;">' . esc_textarea($value) . '</textarea>';
            } else {
                echo '<input type="text" class="short" name="' . esc_attr($id) . '" id="' . esc_attr($id) . '" value="' . esc_attr($value) . '">';
            }

            echo '</div></div>';
        }

        echo "<script>
        jQuery(document).ready(function($) {
            $('#copy_shipping_details').on('click', function(e) {
                e.preventDefault();
        
                var order_id = " . intval($order->get_id()) . ";
       
                $.ajax({
                    type: 'POST',
                    url:ajaxurl,
                    data: {
                        action: 'oxygen_copy_shipping_meta',
                        order_id: order_id,
                    },
                    beforeSend: function () {
                        $.blockUI({
                            message: '',
                            css: {
                                border: 'none',
                                padding: '15px',
                                backgroundColor: '#000',
                                color: '#fff',
                                opacity: 0.7
                            }
                        });        
                    },
                    success: function (response) {
                                
                        if(response['data']){
                            
                            const data = response['data'];
                            
                            let values = {
                                oxygen_move_purpose:             data['oxygen_move_purpose'],
                                oxygen_other_move_purpose_title: data['oxygen_other_move_purpose_title'],
                                oxygen_vehicle_number:           data['oxygen_vehicle_number'],
                                oxygen_shipping_comments:        data['oxygen_shipping_comments'],
                                oxygen_pickup_branch_code:       data['oxygen_pickup_branch_code'],
                                oxygen_pickup_street:            data['oxygen_pickup_street'],
                                oxygen_pickup_address_number:    data['oxygen_pickup_address_number'],
                                oxygen_pickup_postal_code:       data['oxygen_pickup_postal_code'],
                                oxygen_pickup_city:              data['oxygen_pickup_city'],
                                oxygen_pickup_country:           data['oxygen_pickup_country']
                            };
                            
                           jQuery.each(values, function(id, value) {
                                if( ''!== value && 0 !== value ){
                                   $('#_' + id).val(value).trigger('change');
                                }
                            });
                            
                            $('#copy_shipping_details').after(
                                 '<div class=\'copied_shipping_details\'>' +
                                    '<p style=\'color:green;\'>Τα πεδία αντιγράφηκαν επιτυχώς</p>' +
                                '</div>' +
                                '<div class=\'copied_shipping_details\'>' +
                                    '<p style=\'color:red;\'><i>Κενά πεδία ή πεδία με τιμή 0 δεν αντιγράφηκαν</i></p>' +
                                '</div>'
                            );
                  
                           setTimeout(function() {
                                $('.copied_shipping_details').fadeOut(400, function() {
                                    $(this).remove();
                                });
                            }, 5000);
                           
                           $.unblockUI();
                           
                        }
                    },
                    error: function () {
                        $.unblockUI();
                    }
                });
                
            });
        });
        </script>";

        echo '</div></div>';

    }


    public static function save_custom_order_fields( $post_id ) {

        $fields = OxygenHelperFunctions::get_custom_admin_order_fields();
        $order = wc_get_order( $post_id );

        if (!$order || empty($fields)) {
            return;
        }
        foreach ($fields as $id => $field) {

            // Skip 'title' types (they are headers, not inputs)
            if ($field['type'] === 'title') {
                continue;
            }
            // Skip if not in POST
            if (!isset($_POST[$id])) {
                continue;
            }

            switch ($field['type']) {
                case 'textarea':
                    $value = sanitize_textarea_field($_POST[$id]);
                    break;
                case 'number':
                    $value = intval($_POST[$id]);
                    break;
                default:
                    $value = sanitize_text_field($_POST[$id]);
                    break;
            }

            $order->update_meta_data($id, $value);

            if ( class_exists( 'WC_Admin_Notices' ) ) {
                foreach ( WC_Admin_Notices::get_notices() as $notice ) {
                    if ( strpos( $notice, 'oxygen_invoice_error' ) === 0 ) {
                        WC_Admin_Notices::remove_notice( $notice );
                    }
                }
            }
        }

        $order->save_meta_data();
        $order->save();
    }

    /**
     *  Fetching customer metadata fields from the order.
     *
     *  @param array  $customer_data customer meta data array.
     *  @param object $customer WC_Customer.
     *  @param int    $user_id the user ID.
     *  @return array
     */
    public function oxygen_found_customer_details( $customer_data, $customer, $user_id ) {

        $customer_data['billing_vat']        = sanitize_text_field( get_user_meta( $user_id, 'billing_vat', true ) );
        $customer_data['billing_job']        = sanitize_text_field( get_user_meta( $user_id, 'billing_job', true ) );
        $customer_data['billing_tax_office'] = sanitize_text_field( get_user_meta( $user_id, 'billing_tax_office', true ) );
        $customer_data['billing_invoice']    = sanitize_text_field( get_user_meta( $user_id, 'billing_invoice', true ) );

        $customer_data['billing']['vat']        = $customer_data['billing_vat'];
        $customer_data['billing']['job']        = $customer_data['billing_job'];
        $customer_data['billing']['tax_office'] = $customer_data['billing_tax_office'];
        $customer_data['billing']['invoice']    = ( empty( $customer_data['billing_invoice'] ) ? 0 : $customer_data['billing_invoice'] );

        return $customer_data;
    }


    /**
     *  Adding new customer metadata fields to the order.
     *
     *  @param array $fields customer meta data array.
     *  @return array
     */
    public function oxygen_customer_meta_fields( $fields ) {
        $fields['billing']['fields']['billing_vat'] = array(
                'label'       => __( 'VAT #', 'oxygen' ),
                'description' => '',
        );

        $fields['billing']['fields']['billing_job'] = array(
                'label'       => __( 'Job Description', 'oxygen' ),
                'description' => '',
        );

        $fields['billing']['fields']['billing_tax_office'] = array(
                'label'       => __( 'Tax Office', 'oxygen' ),
                'description' => '',
        );

        $fields['billing']['fields']['billing_invoice'] = array(
                'label'       => __( 'Issue invoice', 'oxygen' ),
                'description' => '',
                'class'       => '',
                'type'        => 'checkbox',
        );

        return $fields;
    }

    /**
     *  New user actions on orders list table
     *
     *  @param array  $actions Array of user actions.
     *  @param object $order WC_Order.
     *  @return array
     */
    public function my_account_my_orders_actions( $actions, $order ) {

        $invoice_data = $order->get_meta( '_oxygen_invoice', true );
        $notice_data  = $order->get_meta( '_oxygen_notice', true );

        print_buttons_for_view_download_pdf( $invoice_data, $notice_data );

        return $actions;
    }

    /**
     *  Runs on WooCommerce on bulk action "woocommerce_order_status_changed".
     * x
     *
     *  @param integer $id order id.
     *  @param string  $from_status order from status.
     *  @param string  $new_status order to status.
     *  @param object  $order WC_Order.
     *
     *  @return void
     */
    public function run_on_woocommerce_bulk_order_status( $id, $from_status, $new_status, $order ) {

        if ( $order ) {
            $_oxygen_invoice = $order->get_meta( '_oxygen_invoice', true );

            OxygenHelperFunctions::debug( array( '------------ in bulk oxygen invoice is not empty -------------' ) , 'debug' );
            $oxygen_order_status = str_replace( 'wc-', '', OxygenHelperFunctions::get_option( 'oxygen_order_status' ) );
            OxygenHelperFunctions::debug( array( $oxygen_order_status . ' ' . $new_status ) );

            // status mismatch.
            if ( $oxygen_order_status !== $new_status ) {
                return;
            }

            if ( empty( $_oxygen_invoice ) ) {
                $oxygen_default_document_type      = OxygenHelperFunctions::get_option( 'oxygen_default_document_type' );
                $_GET['notetype']                  = ( ! empty( $oxygen_default_document_type ) ? $oxygen_default_document_type : 'invoice' );
                $_GET['_oxygen_payment_note_type'] = $order->get_meta( '_oxygen_payment_note_type', true );

                /* afora ta stoixeia diakinisis */
                $auto_create_shipping_data = OxygenHelperFunctions::get_option( 'oxygen_autocreate_default_shipping_data' );
                $shipping_details_option = get_option('oxygen_enable_shipping_data',true);
                /* an den exei epilex8ei den 8a ekdidei to parastatiko gia alp & tpda*/
                OxygenHelperFunctions::debug( array( 'Data key is  ', $_GET['_oxygen_payment_note_type'] ," oxygen_autocreate_default_shipping_data is " ,!empty($auto_create_shipping_data)) , 'debug');

                if('yes' === $shipping_details_option && ('alp' === $_GET['_oxygen_payment_note_type'] || 'tpda' === $_GET['_oxygen_payment_note_type']) && ('yes' != $auto_create_shipping_data)){

                    $check_fields = OxygenHelperFunctions::check_orders_shipping_data($order);
                    OxygenHelperFunctions::debug( array( "Check fields is " , !empty($check_fields)) , 'debug');

                    if($check_fields) {
                        WC_Admin_Notices::add_custom_notice(
                                'oxygen_invoice_error',
                                sprintf(
                                        __( 'Could not auto create invoice , because of shipping data. Check <a href="%s">here</a> , if last option is enabled and try again.',
                                                'oxygen' ),
                                        admin_url( 'admin.php?page=wc-settings&tab=oxygen_tabs&section=shipping_data_settings' )
                                )
                        );
                    }
                    return;
                }
                /* end - afora ta stoixeia diakinisis */
                $this->create_invoice( $order->get_id(), $order );

            } else {
                OxygenHelperFunctions::debug( array( 'empty oxygen invoice in run bulk options' ) , 'debug');
            }
        } else {

            $log = array( '----------------- Invalid Order on bulk edit ' . gmdate( 'Y-m-d H:i:s' ) . ' -----------------', $order );
            OxygenHelperFunctions::debug( $log );
        }
    }

    /**
     * Validates invoice-related checkout fields during the WooCommerce checkout process.
     *
     * This method is triggered during the checkout process to ensure that required
     * fields for invoice issuance are correctly filled out. It performs different
     * validation rules based on the selected country (GR or other EU) and whether
     * the customer has selected to receive an invoice (`billing_invoice = 1`).
     *
     * If the fields are incomplete or invalid, appropriate error messages are added
     * to the checkout using `wc_add_notice()`.
     *
     * Validated fields:
     * - VAT number
     * - Job title
     * - Tax office
     * - Company name
     *
     * @return void
     */
    public function check_invoice_fields() {

        $posted_data = WC()->checkout()->get_posted_data();

        OxygenHelperFunctions::debug( array( 'Self fields - check_invoice_fields on checkout', wp_json_encode( $posted_data ) ) , 'debug' );

        if ( ! empty( $posted_data ) ) {

            $billing_country    = $posted_data['billing_country'] ?? '';
            $billing_invoice    = $posted_data['billing_invoice'] ?? 0;
            $billing_vat        = $posted_data['billing_vat'] ?? '';
            $billing_job        = $posted_data['billing_job'] ?? '';
            $billing_tax_office = $posted_data['billing_tax_office'] ?? '';
            $billing_company    = $posted_data['billing_company'] ?? '';

            if ( 1 === $billing_invoice ) { /* an exw epilexei ekdosh timologio */
                if ( strcmp( $billing_country, 'GR' ) === 0 ) { /* kai eimai ellada tote ola ta pedia einai ypoxrewtika */

                    if ( empty( $billing_vat ) ) {
                        wc_add_notice( __( 'The vat number field is mandatory for issuing an invoice.', 'oxygen' ), 'error' );
                        wc_add_notice( __( 'Please fill VAT ID', 'oxygen' ), 'error' );

                    } else {
                        $result = check_mod( $billing_vat, $billing_country );

                        if ( 0 === $result ) {
                            wc_add_notice( __( 'The vat number is incorrect.', 'oxygen' ), 'error' );
                        }
                    }

                    if ( empty( $billing_job ) ) {
                        wc_add_notice( __( 'The job field is mandatory for invoicing.', 'oxygen' ), 'error' );
                        wc_add_notice( __( 'Please fill billing job', 'oxygen' ), 'error' );
                    }

                    if ( empty( $billing_tax_office ) ) {
                        wc_add_notice( __( 'The tax office field is mandatory for issuing an invoice.', 'oxygen' ), 'error' );
                        wc_add_notice( __( 'Please fill billing tax office', 'oxygen' ), 'error' );
                    }

                    if ( empty( $billing_company ) ) {
                        wc_add_notice( __( 'The company name field is mandatory for issuing an invoice.', 'oxygen' ), 'error' );
                        wc_add_notice( __( 'Please fill the billing company name', 'oxygen' ), 'error' );
                    }
                } else {

                    OxygenHelperFunctions::debug( array( 'On checkout process not GR , posted data are :  ', wp_json_encode( $posted_data ) ) , 'debug');

                    if ( empty( $billing_vat ) ) {

                        wc_add_notice( __( 'The vat number field is mandatory for issuing an invoice.', 'oxygen' ), 'error' );
                        wc_add_notice( __( 'Please fill VAT ID', 'oxygen' ), 'error' );

                    } else {

                        /* an exei enrgopoihmeno ton elegxo mesw vies */
                        if ( 'yes' === get_option( 'oxygen_fetch_vat_fields' ,false ) ) {
                            $valid_vies = OxygenApi::do_vies_check( $billing_vat, $billing_country );
                            if ( ! empty( $valid_vies['code'] ) && 200 !== $valid_vies['code'] ) {
                                wc_add_notice( __( 'This Tax id does not match selected country.', 'oxygen' ), 'error' );
                            }
                        }
                    }

                    if ( empty( $billing_job ) ) {
                        wc_add_notice( __( 'The job field is mandatory for invoicing.', 'oxygen' ), 'error' );
                        wc_add_notice( __( 'Please fill billing job', 'oxygen' ), 'error' );
                    }

                    if ( empty( $billing_tax_office ) ) {
                        wc_add_notice( __( 'The tax office field is mandatory for issuing an invoice.', 'oxygen' ), 'error' );
                        wc_add_notice( __( 'Please fill billing tax office', 'oxygen' ), 'error' );
                    }

                    if ( empty( $billing_company ) ) {
                        wc_add_notice( __( 'The company name field is mandatory for issuing an invoice.', 'oxygen' ), 'error' );
                        wc_add_notice( __( 'Please fill the billing company name', 'oxygen' ), 'error' );
                    }
                }
            }
        }
    }
}

/**
 * Builds the fee item body structure for MyData API integration.
 *
 * Iterates through WooCommerce order fee items and formats each one into the
 * required structure for transmission to the Greek MyData system. Handles both
 * positive and negative fees (discounts or credits) and maps tax rates, classifications,
 * and monetary values accordingly.
 *
 * @param WC_Order $order             WooCommerce order object.
 * @param array    $oxygen_taxes      Associative array mapping tax rate IDs to MyData tax IDs.
 * @param string   $class_cat_subfix  Suffix string used to identify classification fields (e.g., '_discount', '_fee').
 *
 * @return array An array with formatted MyData item entries under the `items` key.
 */
function build_fees_body( $order, $oxygen_taxes, $class_cat_subfix ) {

    if ( ! $order instanceof WC_Order ) {
        return array();
    }

    $items = $order->get_items( array( 'fee' ) );

    foreach ( $items as $item_id => $item ) {

        $taxes = $item->get_taxes();

        $item_rate_id = false;

        foreach ( $taxes['total'] as $rate_id => $amount ) {

            if ( ! empty( $amount ) ) {

                $item_rate_id = $rate_id;
                break;
            }
        }

        $product_id = '';
        if ( $item instanceof WC_Order_Item_Product ) {
            $product_id = $item->get_product_id();
        }

        $get_product_mydata_info = OxygenHelperFunctions::get_product_mydata_info( $product_id );
        $measurement_unit_id = get_option( 'oxygen_measurement_unit_default', '' );

        if ( $item->get_total() < 0 ) {

            $args['items'][] = array(
                    'code'                           => null,
                    'description'                    => $item->get_name(),
                    'quantity'                       => $item->get_quantity(),
                    'unit_net_value'                 => round( ( $item->get_total() / $item->get_quantity() ), 2 ),
                    'tax_id'                         => $oxygen_taxes[ $rate_id ],
                    'vat_amount'                     => round( $item->get_total_tax(), 2 ),
                    'net_amount'                     => round( $item->get_total(), 2 ),
                    'measurement_unit_id'            => $measurement_unit_id,
                    'mydata_classification_category' => ( is_array( $get_product_mydata_info[ 'oxygen_mydata_category' . $class_cat_subfix ] ) ? $get_product_mydata_info[ 'oxygen_mydata_category' . $class_cat_subfix ][0] : $get_product_mydata_info[ 'oxygen_mydata_category' . $class_cat_subfix ] ),
                    'mydata_classification_type'     => ( is_array( $get_product_mydata_info[ 'oxygen_mydata_classification_type' . $class_cat_subfix ] ) ? $get_product_mydata_info[ 'oxygen_mydata_classification_type' . $class_cat_subfix ][0] : $get_product_mydata_info[ 'oxygen_mydata_classification_type' . $class_cat_subfix ] ),
            );
        } else {

            $shipping_classification_type = get_option( 'oxygen_mydata_classification_type_shipping', '' );

            $args['items'][] = array(
                    'code'                           => null,
                    'description'                    => $item->get_name(),
                    'quantity'                       => $item->get_quantity(),
                    'unit_net_value'                 => round( ( $item->get_total() / $item->get_quantity() ), 2 ),
                    'tax_id'                         => $oxygen_taxes[ $rate_id ],
                    'vat_amount'                     => round( $item->get_total_tax(), 2 ),
                    'net_amount'                     => round( $item->get_total(), 2 ),
                    'measurement_unit_id'            => $measurement_unit_id,
                    'mydata_classification_category' => 'category1_5',
                    'mydata_classification_type'     => !empty($shipping_classification_type) ? $shipping_classification_type : 'E3_562',

            );
        }
    }

    return ! empty( $args ) ? $args : array();
}

/**
 * Builds the shipping item structure for MyData API submission.
 *
 * Formats all shipping-related items in a WooCommerce order into the required
 * MyData schema format. It dynamically sets language labels, applies classification
 * and tax IDs, and calculates net, VAT, and unit values based on shipping data.
 *
 * This function is used to prepare the shipping-related lines in the invoice or receipt
 * sent to the Greek AADE's MyData system.
 *
 * @param WC_Order $order        The WooCommerce order object.
 * @param int      $order_id     The order ID.
 * @param array    $oxygen_taxes Associative array of tax rate IDs to MyData tax IDs.
 * @param string   $tax_id       Tax rate ID applicable to intra-community or domestic shipping.
 * @param int      $is_intra     Flag (1 or 0) to determine if the document is intra-community.
 *
 * @return array Formatted shipping items ready for inclusion in the MyData payload.
 */
function build_shipping_body( $order, $order_id, $oxygen_taxes, $tax_id, $is_intra ) {

    $language_data = set_language_to_document( $order_id );
    $shipping_lang = $language_data['shipping_lang'];

    $items = $order->get_items( array( 'shipping' ) );

    $args = array(); // Initialize $args as an empty array to ensure a consistent return type.

    foreach ( $items as $item_id => $item ) {

        $oxygen_shipping_code = OxygenHelperFunctions::clean_for_shipping(
                str_replace( 'wc-', '', OxygenHelperFunctions::get_option( 'oxygen_shipping_code' ) )
        );

        $vat_amount = round( $item->get_total_tax(), 2 );

        if ( 0.00 === floatval( $item->get_total() ) ) { /* for zero line products as presents and free shipping */
            return array();
        }

        $taxes = $item->get_taxes();

        $item_rate_id = false;

        foreach ( $taxes['total'] as $rate_id => $amount ) {

            if ( ! empty( $amount ) ) {

                $item_rate_id = $rate_id;
                break;
            }
        }

        $measurement_unit_id = get_option( 'oxygen_measurement_unit_default', '' );
        $shipping_classification_type = get_option( 'oxygen_mydata_classification_type_shipping', '' );

        $args['items'][] = array(
                'code'                           => ( ! empty( $oxygen_shipping_code ) ? $oxygen_shipping_code : 'shipping' ),
                'description'                    => $shipping_lang . $item->get_name(),
                'quantity'                       => $item->get_quantity(),
                'unit_net_value'                 => round( ( $item->get_total() / $item->get_quantity() ), 2 ),
                'tax_id'                         => 1 === $is_intra ? $tax_id : $oxygen_taxes[ $rate_id ] ?? null,
                'vat_amount'                     => $vat_amount ,
                'net_amount'                     => round( $item->get_total(), 2 ),
                'measurement_unit_id'            => $measurement_unit_id,
                'mydata_classification_category' => 'category1_5',
                'mydata_classification_type'     => !empty($shipping_classification_type) ? $shipping_classification_type : 'E3_562',

        );
    }

    return ! empty( $args ) ? $args : array();
}


/**
 * Determines the language to use when printing the document (invoice/receipt).
 *
 * Checks the plugin setting for document language. If set to use the order's language,
 * it uses the order's saved language (e.g., 'el' or 'en') to determine the printed
 * text for labels like "Shipping" and "Order No". Defaults to the globally selected language
 * if order-specific language is not enabled.
 *
 * @param int $order_id The WooCommerce order ID.
 *
 * @return array {
 *     Array of localized strings and language code to use in the document.
 *
 *     @type string $language_to_print Language code ('EL', 'EN', or from settings).
 *     @type string $shipping_lang     Translated "Shipping" label.
 *     @type string $infobox_lang      Translated "Order No" label.
 * }
 */
function set_language_to_document( $order_id ) {
    if ( ! $order_id ) {
        return array();
    }

    $order = wc_get_order( $order_id );
    if ( ! $order ) {
        return array();
    }

    $wc_order_language = strtolower( get_checkout_language( $order_id ) );
    $language_setting  = strtoupper( get_option( 'oxygen_language', 'EN' ) );

    $labels = [
            'EN' => [
                    'infobox_lang'  => __( 'Order No ', 'oxygen' ),
                    'shipping_lang' => __( 'Shipping: ', 'oxygen' ),
            ],
            'EL' => [
                    'infobox_lang'  => __( 'Αριθμός παραγγελίας ', 'oxygen' ),
                    'shipping_lang' => __( 'Μεταφορικά: ', 'oxygen' ),
            ],
    ];

    if ( strtoupper('order_lang') === $language_setting ) {
        $language_to_print = $wc_order_language === 'el' ||  $wc_order_language === 'EL' ? 'EL' : 'EN';
    } else {
        $language_to_print = in_array( $language_setting, [ 'EN', 'EL' ] ) ? $language_setting : 'EN';
    }


    return [
            'language_to_print' => $language_to_print,
            'infobox_lang'      => $labels[ $language_to_print ]['infobox_lang'],
            'shipping_lang'     => $labels[ $language_to_print ]['shipping_lang'],
    ];
}

function build_shipping_details_invoice($order_id){

    if ( ! $order_id ) {
        return array();
    }

    $order = wc_get_order($order_id);

    $fields = [
            'move_purpose',
            'other_move_purpose_title',
            'vehicle_number',
            'shipping_comments',
            'pickup_branch_code',
            'pickup_street',
            'pickup_address_number',
            'pickup_postal_code',
            'pickup_city',
            'pickup_country',
    ];

    $data = [];

    $has_default_shipping = false;
    foreach ($fields as $field) {
        $meta_key = '_oxygen_' . $field;
        $option_key = 'oxygen_' . $field;

        $value = $order->get_meta($meta_key,true);

        if(!empty($value)){
            $data[$field] = $value;
        }else{
            $data[$field] = get_option($option_key);
            $has_default_shipping = true;
        }
//		$data[$field] = !empty($value) ? $value : get_option($option_key);
    }

    if ($has_default_shipping) {
        do_action('oxygen_fill_order_shipping_meta_from_options', $order_id);
        OxygenHelperFunctions::debug( array( '------ oxygen_fill_order_shipping_meta_from_options executed ------- '), 'info');

    }

    $athens_time = new DateTime('now', new DateTimeZone('Europe/Athens'));
    $athens_time->modify('+30 seconds');
    $dispatched_at = $athens_time->format('Y-m-d\TH:i:sP');

    $address_1  = OxygenHelperFunctions::get_billing_or_shipping_meta($order, 'address_1');
    $city       = OxygenHelperFunctions::get_billing_or_shipping_meta($order, 'city');
    $postcode   = OxygenHelperFunctions::get_billing_or_shipping_meta($order, 'postcode');
    $country    = OxygenHelperFunctions::get_billing_or_shipping_meta($order, 'country');
    $phone      = OxygenHelperFunctions::get_billing_or_shipping_meta($order, 'phone');
    $first_name = OxygenHelperFunctions::get_billing_or_shipping_meta($order, 'first_name');
    $last_name  = OxygenHelperFunctions::get_billing_or_shipping_meta($order, 'last_name');

    preg_match('/^(.*?)(\d+\S*)$/u', $address_1, $matches);
    $street = isset($matches[1]) ? trim($matches[1]) : $address_1;
    $number = isset($matches[2]) ? trim($matches[2]) : '';

    return [
            "dispatched_at" => $dispatched_at, // Fill with actual date-time if available
            "move_purpose" => (int) $data['move_purpose'],
            "other_move_purpose_title" => $data['other_move_purpose_title'],
            "vehicle_number" => $data['vehicle_number'],
            "pickup_branch_code" => (int) $data['pickup_branch_code'],
            "pickup_address" => [
                    "street" => $data['pickup_street'],
                    "number" => $data['pickup_address_number'],
                    "postal_code" => $data['pickup_postal_code'],
                    "city" => $data['pickup_city'],
                    "country_code" => $data['pickup_country'],
            ],
            "delivery_address" => [
                    'street'       => $street,
                    'number'       => empty($number)? "0" : $number,
                    'postal_code'  => $postcode,
                    'city'         => $city,
                    'country_code' => $country,
            ],
            "delivery_details" => [
                    'name'  => trim($first_name . ' ' . $last_name),
                    'phone' => $phone,
            ]
    ];

}

add_action('oxygen_fill_order_shipping_meta_from_options', 'oxygen_fill_empty_shipping_meta_from_options');

function oxygen_fill_empty_shipping_meta_from_options($order_id) {
    if (! $order_id) {
        return;
    }

    $order = wc_get_order($order_id);

    $fields = [
            'move_purpose',
            'other_move_purpose_title',
            'vehicle_number',
            'shipping_comments',
            'pickup_branch_code',
            'pickup_street',
            'pickup_address_number',
            'pickup_postal_code',
            'pickup_city',
            'pickup_country',
    ];

    foreach ($fields as $field) {
        $meta_key = '_oxygen_' . $field;
        $option_key = 'oxygen_' . $field;

        $current_value = $order->get_meta($meta_key, true);
        if (empty($current_value)) {
            $default_value = get_option($option_key);
            if (!empty($default_value)) {
                $order->update_meta_data($meta_key, $default_value);
            }
        }
    }

    $order->save(); // Save the updated metadata
}


/**
 * Builds the full invoice data array to be sent to the MyData API.
 *
 * This function constructs the main payload for issuing a document (invoice, receipt,
 * notice, intra-community invoice, etc.) to the Greek tax authority through MyData.
 * It includes:
 * - Header information (issue date, document type, numbering, customer, language, etc.)
 * - Line items (products, fees, shipping)
 * - VAT and tax mappings
 * - Payment method
 * - Optional intra-community logic and VIES validation
 *
 * Handles both standard and special documents (e.g., "notice" type), and supports
 * parent or variation SKU handling based on plugin settings.
 *
 * @param WC_Order $order               The WooCommerce order object.
 * @param int      $order_id            The ID of the order.
 * @param string   $notetype            Type of document to issue (e.g. 'invoice', 'receipt', 'notice').
 * @param string   $doc_key             The document key used to fetch plugin document type settings.
 * @param string   $oxygen_customer_id  The Pelatologio contact ID.
 * @param array    $payment_methods     Array mapping WooCommerce payment methods to MyData IDs.
 * @param array    $document_types      Array of document type mappings (p, rp, etc.).
 * @param array    $mydata_types        Array of MyData-specific type codes (e.g. '1.1', '2.2').
 * @param string   $class_cat_subfix    Suffix to use when selecting classification metadata (e.g. '_fee', '_product').
 *
 * @return array The full document body structured for MyData API submission.
 */
function build_invoice_body( $order, $order_id, $notetype, $doc_key, $oxygen_customer_id, $payment_methods, $document_types, $mydata_types, $class_cat_subfix ) {

    $language_data     = set_language_to_document( $order_id );
    $language_to_print = $language_data['language_to_print'];
    $infobox_lang      = $language_data['infobox_lang'];

    $intra_tax_id = '';
    $args = array();

    if ( 'notice' === $notetype ) {

        $doc_key = 'notice';

        $args = array_filter(
                array(
                        'numbering_sequence_id' => OxygenHelperFunctions::get_option( 'oxygen_num_sequence_' . $doc_key ),
                        'issue_date'            => wp_date( 'Y-m-d' ),
                        'expire_date'           => wp_date( 'Y-m-d', strtotime( '+1 month' ) ),
                        'contact_id'            => $oxygen_customer_id,
                        'language'              => $language_to_print,
                        'logo_id'               => ( ! empty( OxygenHelperFunctions::get_option( 'oxygen_logo' ) ) ?  OxygenHelperFunctions::get_logo_by_language($language_to_print) : OxygenHelperFunctions::get_default_logo_id() ),
                        'infobox'               => $infobox_lang . sprintf( ' %s', $order_id ),
                )
        );

    } else {

        $payment_method_option = $payment_methods[ $order->get_payment_method() ];
        if ( empty( $payment_method_option ) ) {
            if ( ! empty( get_option( 'oxygen_payment_default' ) ) ) {
                $payment_method_option = get_option( 'oxygen_payment_default' );
            } else {
                OxygenHelperFunctions::debug( array( '------ Option for default payment method is empty ------- ', $payment_method_option ) , 'debug');
            }
        }

        $document_type = $document_types[ $doc_key ];

        /*
         * Document type i
            $timologio_xwris_stoixea_diakinisis = OxygenHelperFunctions::get_option('oxygen_enable_simple_invoice',true);
            if( 'yes' == $timologio_xwris_stoixea_diakinisis && ($doc_key == 'tpda' || $doc_key == 'tpy')){
                $document_type= 'i'; // i instead of p or s
            }
        */

        $oxygen_enable_intra_community_invoice = OxygenHelperFunctions::get_option( 'oxygen_enable_intra_community_invoice', true );

        if ( 'yes' === $oxygen_enable_intra_community_invoice && ( 'tpda_intra' === $doc_key || 'tpy_intra' === $doc_key ) ) { /* option for endokoinotika */

            $country_code = $order->get_billing_country();
            $vat_number   = $order->get_meta( '_billing_vat' );

            if ( 'GR' === $country_code ) {
                $country_code = 'EL';
            }
            $valid_vies = OxygenApi::do_vies_check( $vat_number, $country_code );

            if ( ! empty( $valid_vies['code'] ) && 200 !== $valid_vies['code'] ) {

                $message = $valid_vies[0]['message'];
                WC_Admin_Notices::add_custom_notice( 'error', $message );
                return array();

            } else {

                $intra_tax_id = OxygenHelperFunctions::get_option( 'oxygen_intra_community_tax_invoices', true );

                if ( '2.2' === $mydata_types[ $doc_key ] ) {
                    $document_type = $document_types['tpy_intra'];
                } elseif ( '1.2' === $mydata_types[ $doc_key ] ) {
                    $document_type = $document_types['tpda_intra'];
                }
            }
        }

        $is_paid = set_payment_status_per_payment_way( $order );

        $receipt_id = get_post_meta( $order->get_id(), '_oxygen_has_receipt_id', true );

        $args = array_filter(
                array(
                        'numbering_sequence_id' => OxygenHelperFunctions::get_option( 'oxygen_num_sequence_' . $doc_key, true ),
                        'issue_date'            => wp_date( 'Y-m-d' ),
                        'document_type'         => $document_type, // Docyment type p or rp if physical product exists.
                        'mydata_document_type'  => $mydata_types[ $doc_key ],
                        'payment_method_id'     => $payment_method_option,
                        'contact_id'            => $oxygen_customer_id,
                        'is_paid'               => $is_paid,
                        'language'              => $language_to_print,
                        'logo_id'               => ( ! empty( OxygenHelperFunctions::get_option( 'oxygen_logo' ) ) ? OxygenHelperFunctions::get_logo_by_language($language_to_print) : OxygenHelperFunctions::get_default_logo_id() ),
                        'infobox'               => $infobox_lang . sprintf( ' %s', $order_id ),
                        'receipt_id'            => $receipt_id ?? ''
                )
        );

    }

    $oxygen_taxes = get_option( 'oxygen_taxes' );

    $items = $order->get_items();

    foreach ( $items as $item_id => $item ) {

        $taxes = $item->get_taxes();

        $item_rate_id = false;

        foreach ( $taxes['total'] as $rate_id => $amount ) {

            if ( ! empty($amount) ) {

                $item_rate_id = $rate_id;
                break;
            }
        }

        $product_variation_id = $item['variation_id'];

        $option_oxygen_products_variations = get_option( 'oxygen_products_variations' );

        /* An 8elw panta na painei to parent product sku */
        if ( 'yes' === $option_oxygen_products_variations ) {

            $item_product = wc_get_product( $item->get_product_id() );
            OxygenHelperFunctions::debug( array( '------Use always parent sku product code ' . !empty($item_product) ? $item_product->get_sku() : 'empty product' ), 'debug');

        } else {
            if ( ! empty( $product_variation_id ) && 0 !== $product_variation_id ) {
                $item_product = wc_get_product( $product_variation_id );
            } else {
                $item_product = wc_get_product( $item->get_product_id() );
            }

            OxygenHelperFunctions::debug( array( '------NOT $option_oxygen_products_variations product code ',!empty($item_product) ? $item_product->get_sku() : 'empty product' ), 'debug');

        }

        // Return ONLY product code
        if ( $item_product instanceof WC_Product ) {
            $product_code = $item_product->get_sku() ?? '';
        }

        /*Discount - DO NOT REMOVE */

        $regular_price = (float) $item_product->get_regular_price() ?? $item_product->get_price();

        $discount_type = 'amount';
        $net_amount_pre_discount = round(  wc_get_price_excluding_tax($item_product, ['price' => $regular_price]) * $item->get_quantity(),2);
        $net_amount              = round( (float) $item->get_total(), 2 );         // net after discounts
        $vat_amount              = round( (float) $item->get_total_tax(), 2 );     // VAT after discounts

        $unit_net_value =  round( (float)$net_amount_pre_discount/ $item->get_quantity(),4);

        if(empty($unit_net_value)){
            $unit_net_value = round( (float) $item->get_total() / $item->get_quantity(), 4 );
        }

        if($net_amount_pre_discount <= 0){

            $qty = max(1, (float) $item->get_quantity());

            $net_amount = (float) $item->get_total(); // after discount (line)

            $net_pre_discount = (float) $item->get_subtotal(); // default from order

            if ( abs($net_pre_discount - $net_amount) < 0.0001 ) {

                $product_id   = (int) $item->get_product_id();
                $variation_id = (int) $item->get_variation_id();

                $p = $variation_id ? wc_get_product($variation_id) : wc_get_product($product_id);

                if ( $p ) {
                    $regular = (float) $p->get_regular_price();

                    if ( $regular > 0 ) {
                        // convert regular to NET
                        $unit_net_regular = (float) wc_get_price_excluding_tax($p, ['price' => $regular]);
                        $unit_net_value = round( $unit_net_regular, 4 );
                        $net_amount_pre_discount = round( (float) $unit_net_regular * $qty, 2 );
                    }
                }
            }
        }

        $total_discount_per_line = $net_amount_pre_discount - $net_amount;
        $discount_value = round( $total_discount_per_line / $item->get_quantity(), 4 );  // net discount on the line

        if($discount_value > 0) {
            OxygenHelperFunctions::debug(array('Discount value is ' . $discount_value .
                                               ' net pre discount '.$net_amount_pre_discount.'
                                               unit net value '.$unit_net_value), 'debug');
        }
        /* agnoei ta proionta me 0 axia kai fpa klp - dwra */
        if( $item->get_total() == 0){
            continue;
        }

        if ( 'invoice' === $notetype ) {

            $get_product_mydata_info = OxygenHelperFunctions::get_product_mydata_info( $item->get_product_id() );

            OxygenHelperFunctions::debug( array( '------doc key before  ', $doc_key ) , 'debug');

            if ( '' !== $intra_tax_id && ( 'tpda_intra' === $doc_key || 'tpy_intra' === $doc_key ) ) {
                $vat_amount     = 0;
                $unit_net_value = wc_format_decimal( $item->get_total(), wc_get_price_decimals() );
                OxygenHelperFunctions::debug( array( '------intra total price  ', $unit_net_value ) , 'debug');
            }

            OxygenHelperFunctions::debug( array( '------in build invoice before category check suffix is  ', $class_cat_subfix, wp_json_encode( $get_product_mydata_info ) ) , 'debug');

            $measurement_unit_id = OxygenHelperFunctions::get_product_measurement_unit( $item->get_product_id() );

            $category = get_option('oxygen_mydata_category' . $class_cat_subfix);

            if(!empty($get_product_mydata_info[ 'oxygen_mydata_category' . $class_cat_subfix ] )){
                if (is_array($get_product_mydata_info['oxygen_mydata_category' . $class_cat_subfix])) {
                    $category = $get_product_mydata_info['oxygen_mydata_category' . $class_cat_subfix][0];
                } else {
                    $category = $get_product_mydata_info['oxygen_mydata_category' . $class_cat_subfix];
                }
            }

            $type = get_option('oxygen_mydata_classification_type' . $class_cat_subfix);

            if(!empty($get_product_mydata_info[ 'oxygen_mydata_classification_type' . $class_cat_subfix ] )){
                if (is_array($get_product_mydata_info['oxygen_mydata_classification_type' . $class_cat_subfix])) {
                    $type = $get_product_mydata_info['oxygen_mydata_classification_type' . $class_cat_subfix][0];
                } else {
                    $type = $get_product_mydata_info['oxygen_mydata_classification_type' . $class_cat_subfix];
                }
            }

            OxygenHelperFunctions::debug( array( '------in build invoice suffix is  ', $class_cat_subfix, $category , $type ) , 'debug');


            $args['items'][] = array_filter(
                    array(
                            'code'                           => $product_code,
                            'description'                    => $item->get_name() ? wp_strip_all_tags( $item->get_name() ) : '',
                            'quantity'                       => $item->get_quantity(),
                            'unit_net_value'                 => $unit_net_value,
                            'tax_id'                         => !empty($intra_tax_id ) ? $intra_tax_id : $oxygen_taxes[ $rate_id ],
                            'vat_amount'                     => $discount_value > 0 || !empty($intra_tax_id ) ? $vat_amount : round( $item->get_total_tax(), 2 ),
                            'net_amount'                     => round( $item->get_total(), 2 ),
                            'discount_type'                  => $discount_type,
                            'discount_value'                 => max($discount_value, 0),
                            'net_amount_pre_discount'        => $net_amount_pre_discount,
                            'measurement_unit_id'            => $measurement_unit_id,
                            'mydata_classification_category' => $category ,
                            'mydata_classification_type'     => $type,
                    ),
                    function ( $value ) {
                        // Remove only null and empty strings, but keep 0.
                        return null !== $value && '' !== $value;
                    }
            );

        }elseif( 'notice' === $notetype){

            $args['items'][] = array_filter(
                    array(
                            'code'                           => $product_code,
                            'description'                    => $item->get_name() ? wp_strip_all_tags( $item->get_name() ) : '',
                            'quantity'                       => $item->get_quantity(),
                            'unit_net_value'                 => $unit_net_value,
                            'tax_id'                         => !empty($intra_tax_id ) ? $intra_tax_id : $oxygen_taxes[ $rate_id ],
                            'vat_amount'                     => $discount_value > 0 || !empty($intra_tax_id ) ? $vat_amount : round( $item->get_total_tax(), 2 ),
                            'net_amount'                     => round( $item->get_total(), 2 ),
                            'discount_type'                  => $discount_type,
                            'discount_value'                 => max($discount_value, 0),
                            'net_amount_pre_discount'        => $net_amount_pre_discount,
                    ),
                    function ( $value ) {
                        // Remove only null and empty strings, but keep 0.
                        return null !== $value && '' !== $value;
                    }
            );
        }

    }

    $item_rate_id = ! empty( $intra_tax_id ) ? $intra_tax_id : $rate_id;

    if ( '' !== $intra_tax_id ) {
        $shipping_data = build_shipping_body( $order, $order_id, $oxygen_taxes, $item_rate_id, 1 );
    } else {
        $shipping_data = build_shipping_body( $order, $order_id, $oxygen_taxes, $item_rate_id, 0 );
    }

    if ( ! empty( $shipping_data['items'] ) ) {
        $args['items'] = array_merge( $args['items'] ?? array(), $shipping_data['items'] );
    }

    $fee_data = build_fees_body( $order, $oxygen_taxes, $class_cat_subfix );

    if ( ! empty( $fee_data['items'] ) ) {
        $args['items'] = array_merge( $args['items'] ?? array(), $fee_data['items'] );
    }

    if( 'yes' === get_option( 'oxygen_enable_shipping_data' ) ) { /* an exei energopoihsei thn epilogh */
        if ( 'rp' === $document_type || 'p' === $document_type ) { /* mono pwlisi */
            $args['shipping_details'] = build_shipping_details_invoice( $order_id );
        }
    }

    return $args;
}

/**
 * Determines whether an order should be marked as paid based on its payment method.
 *
 * Looks up the selected payment method in the plugin option `oxygen_is_paid`
 * and returns `true` if it is configured as "paid" (`yes`), otherwise returns `false`.
 * This is used to inform MyData whether the document should be flagged as paid.
 *
 * @param WC_Order $order WooCommerce order object.
 *
 * @return bool True if the payment method is configured as paid, false otherwise.
 */
function set_payment_status_per_payment_way( $order ): bool {

    $payment_method = $order->get_payment_method();
    if ( ! empty( $payment_method ) ) {
        $options = get_option( 'oxygen_is_paid', array() );
        if( empty($options) ){
            OxygenHelperFunctions::debug( array("Empty payment options , cannot match payment method with paid/unpaid status.") );
        }
        return isset( $options[ $payment_method ] ) && 'no' !== $options[ $payment_method ];
    }
    return false;
}


/**
 * Retrieves the language used during checkout for the given order.
 *
 * This function checks for multilingual plugin metadata (WPML, Polylang, or TranslatePress)
 * to determine the language the customer used when placing the order. It falls back to Greek ('el')
 * if no specific language is found.
 *
 * Priority of detection:
 * 1. WPML via `apply_filters( 'wpml_current_language' )`
 * 2. Polylang via `pll_current_language()`
 * 3. TranslatePress via order meta key `trp_language`
 * 4. Default: `'el'`
 *
 * @param int $order_id The WooCommerce order ID.
 *
 * @return string The detected language code (e.g. 'el', 'en').
 */
function get_checkout_language( $order_id ) {

    $order           = wc_get_order( $order_id );
    $order_meta_data = $order->get_meta_data();

    $trp_language = null;
    $wpml_language=null;
    foreach ( $order_meta_data as $meta ) {
        if ( 'trp_language' === $meta->key ) {
            $trp_language = $meta->value;
            break;
        }
        if ( 'wpml_language' === $meta->key ) {
            $wpml_language = $meta->value;
            break;
        }
    }

    if ( '' !== $wpml_language && null !== $wpml_language ) {
        return $wpml_language;
    } elseif ( function_exists( 'pll_current_language' ) ) {
        return pll_current_language();
    } elseif ( '' !== $trp_language && null !== $trp_language ) {
        return $trp_language;
    }

    return ( 'GR' !== $order->get_billing_country() ) ? 'en' : 'el';
}

/**
 * Outputs HTML buttons for viewing and downloading PDF documents (invoice, receipt, or notice).
 *
 * This function renders download and view buttons for the provided `$invoice_data` and `$notice_data`
 * from the Oxygen e-invoicing system. It supports styling, icons, and uses WooCommerce and WordPress
 * escaping and conditional logic to ensure output is context-aware (e.g., avoiding output on account pages).
 *
 * Button types:
 * - PDF download for invoice or receipt (based on document type)
 * - PDF download for notice (if available)
 * - View link for invoice, receipt, or notice (opens external `iview_url`)
 * - Optional email-sending icon (not on account pages)
 *
 * @param array $invoice_data The invoice or receipt data, including `iview_url`, `document_type`, `number`, etc.
 * @param array $notice_data  The notice document data, including `iview_url`, `number`, etc.
 *
 * @return void Outputs HTML directly (should be used within a template or hooked output).
 */
function print_buttons_for_view_download_pdf( $invoice_data, $notice_data ) {

    $note_type = $invoice_data['document_type'] ?? '';
    if ( ! empty( $invoice_data ) && is_array( $invoice_data ) ) {
        $mydata_type = $invoice_data['mydata_document_type'];

        /*
        This is for simple timologio - xwris stoixeia diakinisis
        $timologio_category = '';
        if ( '1.1' === $mydata_type ) {
            $timologio_category = 'tpda';
        } elseif ( '2.1' === $mydata_type ) {
            $timologio_category = 'tpy';
        }
        */
    }

    $doc_types_array = array(
            's'  => 'tpy',
            'p'  => 'tpda',
            'rs' => 'apy',
            'rp' => 'alp',
        // 'i'  => $timologio_category ?? '',
    );

    if ( isset( $invoice_data['iview_url'] ) && ! empty( $invoice_data['iview_url'] ) ) {
        ?>
        <div>
            <p> <!-- first is the label of document receipt/invoice/notice -->
                <?php
                if ( ! empty( $note_type ) ) {
                    if ( 'rs' === $invoice_data['document_type'] || 'rp' === $invoice_data['document_type'] ) {
                        echo '<span class="oxygen_labels_orders">' . esc_html( __( 'Receipt', 'oxygen' ) ) . ' - #' . esc_attr( $invoice_data['sequence'] . $invoice_data['number'] ) . '</span>';
                    } else {
                        echo '<span class="oxygen_labels_orders">' . esc_html( __( 'Invoice', 'oxygen' ) ) . ' - #' . esc_attr( $invoice_data['sequence'] . $invoice_data['number'] ) . '</span>';
                    }
                }
                ?>
            </p>
            <div style="display:flex; align-items:center;">
				<span class="download_pdf_orders doctype_<?php echo esc_attr( $doc_types_array[ $note_type ] ); ?>" id="<?php echo esc_attr( $invoice_data['id'] ); ?>">
					<span style="margin-right:5px;" class="dashicons dashicons-download"></span>
					<?php esc_html_e( 'PDF Download', 'oxygen' ); ?>
					<div class="loader_pdf"></div>
				</span>
                <div class="print_pdf_orders doctype_<?php echo esc_attr( $doc_types_array[ $note_type ] ); ?>" id="<?php echo esc_attr( $invoice_data['id'] ); ?>">
                    <svg style="vertical-align: middle; margin-right: 5px;" width="22" height="22" fill="grey" viewBox="0 0 24 24">
                        <path d="M6 9V2h12v7h4v9h-4v4H6v-4H2V9h4zm10-5H8v5h8V4zM8 20h8v-5H8v5zm12-7V11H4v2h16z"/>
                    </svg>
                    <div class="loader_pdf"></div>
                </div>
                <?php if ( ! is_account_page() ) { ?>
                    <div class="send_invoice_email">
                        <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 100 91">
                            <path d="M 85,10 84,11 83,11 81,13 79,13 78,14 77,14 75,16 74,16 73,17 71,17 70,18 69,18 67,20 66,20 65,21 64,21 63,22 62,22 60,24 59,24 58,25 56,
						25 55,26 54,26 52,28 51,28 50,29 49,29 47,31 46,31 45,32 42,32 39,35 38,35 37,36 35,36 34,37 33,37 31,39 29,39 28,40 27,40 26,41 26,42 25,43 22,43 21,
						44 20,44 18,46 17,46 17,47 16,48 16,50 17,51 18,51 19,52 21,52 23,54 24,54 25,55 30,55 32,57 33,57 34,58 37,58 40,55 41,55 45,51 46,51 51,46 52,46 52,
						45 53,44 54,44 55,43 57,45 57,46 56,47 56,48 54,50 53,50 53,51 52,52 52,53 51,54 50,54 50,55 46,59 46,61 47,61 48,62 49,62 50,63 52,63 53,64 52,65 43,65 43,66 42,67
						42,79 44,81 47,81 48,80 49,80 49,79 50,78 50,77 53,74 53,73 54,72 54,69 53,68 53,66 54,65 56,65 57,66 62,66 64,68 65,68 66,69 68,69 69,70 74,70 76,72 80,72 82,70 82,64
						83,63 83,56 84,55 84,54 85,53 85,51 86,50 86,42 87,41 87,31 88,30 88,27 89,26 89,22 90,21 90,11 89,10 Z" fill="grey" stroke="grey" stroke-width="1"/>
                        </svg>
                        <div class="loader_pdf"></div>
                    </div>
                <?php } ?>
            </div>
            <p style="padding-top:4px;">
                <a class="oxygen_links_style" href="<?php echo esc_url( $invoice_data['iview_url'] ); ?>" target="_blank"><span class="dashicons dashicons-search"></span>
                    <?php
                    if ( 'rs' === $invoice_data['document_type'] || 'rp' === $invoice_data['document_type'] ) {
                        esc_html_e( 'View Receipt', 'oxygen' );
                    } else {
                        esc_html_e( 'View Invoice', 'oxygen' );
                    }
                    ?>
                </a>
            </p>
        </div>

        <?php
    }
    if ( ! empty( $invoice_data ) && ! empty( $notice_data ) ) {
        ?>
        <p class="oxygen_list_separator"></p>
        <?php
    }
    if ( ! is_account_page() ) {

        if ( isset( $notice_data['iview_url'] ) && ! empty( $notice_data['iview_url'] ) ) {
            ?>
            <div>
                <p>
                    <span class="oxygen_labels_orders"><?php echo esc_html( __( 'Notice', 'oxygen' ) ) . ' - #' . esc_html( $notice_data['sequence'] . $notice_data['number'] ); ?></span>
                </p>
                <div style="display:flex; align-items:center;">
					<span class="download_pdf_orders doctype_notice" id="<?php echo esc_attr( $notice_data['id'] ); ?>">
						<span style="margin-right:5px;" class="dashicons dashicons-download"></span>
						<?php esc_html_e( 'PDF Download', 'oxygen' ); ?>
						<div class="loader_pdf"></div>
					</span>
                    <div class="print_pdf_orders doctype_notice" id="<?php echo esc_attr( $notice_data['id'] ); ?>">
                        <svg style="vertical-align: middle; margin-right: 5px;" width="22" height="22" fill="grey" viewBox="0 0 24 24">
                            <path d="M6 9V2h12v7h4v9h-4v4H6v-4H2V9h4zm10-5H8v5h8V4zM8 20h8v-5H8v5zm12-7V11H4v2h16z"/>
                        </svg>
                        <div class="loader_pdf"></div>
                    </div>
                    <div class="send_invoice_email">
                        <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 100 91">
                            <path d="M 85,10 84,11 83,11 81,13 79,13 78,14 77,14 75,16 74,16 73,17 71,17 70,18 69,18 67,20 66,20 65,21 64,21 63,22 62,22 60,24 59,24 58,25 56,
							25 55,26 54,26 52,28 51,28 50,29 49,29 47,31 46,31 45,32 42,32 39,35 38,35 37,36 35,36 34,37 33,37 31,39 29,39 28,40 27,40 26,41 26,42 25,43 22,43 21,
							44 20,44 18,46 17,46 17,47 16,48 16,50 17,51 18,51 19,52 21,52 23,54 24,54 25,55 30,55 32,57 33,57 34,58 37,58 40,55 41,55 45,51 46,51 51,46 52,46 52,
							45 53,44 54,44 55,43 57,45 57,46 56,47 56,48 54,50 53,50 53,51 52,52 52,53 51,54 50,54 50,55 46,59 46,61 47,61 48,62 49,62 50,63 52,63 53,64 52,65 43,65 43,66 42,67
							42,79 44,81 47,81 48,80 49,80 49,79 50,78 50,77 53,74 53,73 54,72 54,69 53,68 53,66 54,65 56,65 57,66 62,66 64,68 65,68 66,69 68,69 69,70 74,70 76,72 80,72 82,70 82,64
							83,63 83,56 84,55 84,54 85,53 85,51 86,50 86,42 87,41 87,31 88,30 88,27 89,26 89,22 90,21 90,11 89,10 Z" fill="grey" stroke="grey" stroke-width="1"/>
                        </svg>
                        <div class="loader_pdf"></div>
                    </div>
                </div>
                <p style="padding-top:4px;">
                    <a class="oxygen_links_style" href="<?php echo esc_url( $notice_data['iview_url'] ); ?>" target="_blank"><span class="dashicons dashicons-search"></span> <?php esc_html_e( 'View Notice', 'oxygen' ); ?></a><br />
                </p>
            </div>
            <?php
        }
    }
}

/* save check option for invoice or not --- using in oxygen payments */
add_action( 'woocommerce_checkout_update_order_meta', 'save_billing_invoice_meta' ,10 ,2);

/**
 * Saves the billing invoice checkbox value as post meta for the given order.
 *
 * This function checks whether the `billing_invoice` field was submitted during checkout
 * and saves its value (`1` or `0`) to the `_billing_invoice` order meta field.
 * It also logs the update for debugging purposes.
 *
 * Meta key saved:
 * - `_billing_invoice`: '1' if checkbox was checked, '0' otherwise.
 *
 * @param int $order_id The WooCommerce order ID.
 *
 * @return void
 */

function save_billing_invoice_meta( $order_id ) {

    if ( 'yes' === get_option( 'oxygen_self_fields' ) ) {
        if (isset($_POST['billing_invoice']) && '1' === $_POST['billing_invoice']) {
            update_post_meta($order_id, '_billing_invoice', '1'); // Save as 'yes' if checked.
        } else {
            update_post_meta($order_id, '_billing_invoice', '0'); // Save as 'no' if not checked.
        }
    }

}


/**
 * Validates a Greek VAT number using the checksum (modulo) algorithm.
 *
 * The function calculates the checksum based on the first 8 digits of the VAT number,
 * multiplies them by powers of 2 (from 2^8 to 2^1), sums the result, and compares
 * it against the 9th digit. This is the official Greek TIN (ΑΦΜ) validation method.
 *
 * @param string $value The 9-digit VAT number as a string.
 *
 * @return int Returns 1 if valid, 0 if invalid.
 */
function check_mod( $value ) {

    $digits = str_split( substr( $value, 0, -1 ) );
    $sum    = 0;
    foreach ( $digits as $index => $digit ) {
        $sum += $digit * pow( 2, 8 - $index );
    }
    if ( $sum % 11 % 10 == (int) $value[8] ) {
        return 1;
    }
    return 0;
}

/**
 * Handles AJAX request to check a VAT number via Greek or VIES service.
 *
 * This function is triggered by an AJAX call and checks if a VAT number is valid.
 * If only the VAT number is provided, it performs a check for Greek VAT numbers.
 * If both the VAT number and country code are provided, it performs a VIES check.
 *
 * The function logs the request and returns a JSON response with the result.
 *
 * @return void Outputs JSON response and exits.
 */
function handle_check_vat_action() {

    if ( isset( $_POST['vat_number'] ) && ! isset( $_POST['country_code'] ) ) {

        $vat_number = sanitize_text_field( wp_unslash( $_POST['vat_number'] ) );
        $response   = OxygenApi::do_vat_check( $vat_number );

        $log = array( '---------------- handle vat search greek -------------' );
        OxygenHelperFunctions::debug( $log , 'info' );

    } elseif ( isset( $_POST['vat_number'] ) && isset( $_POST['country_code'] ) ) {

        $log = array( '---------------- handle vat search VIES -------------' );
        OxygenHelperFunctions::debug( $log , 'info');

        $vat_number   = sanitize_text_field( wp_unslash( $_POST['vat_number'] ) );
        $country_code = sanitize_text_field( wp_unslash( $_POST['country_code'] ) );
        $response     = OxygenApi::do_vies_check( $vat_number, $country_code );

    } else {
        $response = array( 'message' => 'handle_check_vat_action - Vat number is empty' );
    }

    // Send a response back to the AJAX call.
    wp_send_json_success( $response );
}

// Hook into WordPress' AJAX system for both logged in and non-logged in users.
add_action( 'wp_ajax_check_vat_action', 'handle_check_vat_action' );
add_action( 'wp_ajax_nopriv_check_vat_action', 'handle_check_vat_action' );

/**
 * Enqueues the JavaScript file used to validate VAT numbers on the checkout page.
 *
 * This script is only enqueued during the checkout process to avoid unnecessary loading.
 * It also localizes variables like the AJAX URL and validation messages to be used in the JS.
 *
 * @return void
 */
function enqueue_vat_check_script() {

    wp_enqueue_script( 'check_vat', OXYGEN_PLUGIN_URL . 'js/check_vat.js', array(), null );

    if ( is_checkout() ) {

        wp_localize_script(
                'check_vat',
                'handle_check_vat_action',
                array(
                        'ajax_url'        => admin_url( 'admin-ajax.php' ),
                        'mandatory_field' => __( 'Mandatory field', 'oxygen' ),
                )
        );

    }
}

if ( 'yes' === get_option( 'oxygen_fetch_vat_fields' ) ) {
    add_action( 'wp_enqueue_scripts', 'enqueue_vat_check_script' );
}

/**
 * Handles the AJAX request to generate and download a PDF document (invoice or notice).
 *
 * This function checks the document type and ID, calls the appropriate Oxygen API
 * method to retrieve the PDF, saves it to the /uploads/oxygen/ directory, and returns
 * the public URL for download.
 *
 * @return void Outputs a JSON response with the PDF URL or an error message.
 */
function download_pdf_action() {

    if ( ! empty( $_POST['document_id'] ) && ! empty( $_POST['doctype'] ) ) {

        $document_id = sanitize_text_field( wp_unslash( $_POST['document_id'] ) );
        $doc_type    = sanitize_text_field( wp_unslash( $_POST['doctype'] ) );
        $print_type  = 'a4';

        if ( '' === $doc_type ) {
            wp_send_json_error( 'Document type is empty' );
            wp_die();
        }

        $doc_types = array( 'tpy', 'tpda', 'apy', 'alp' );

        /* print invoices types documents */
        if ( in_array( $doc_type, $doc_types ) ) {
            if ( 'alp' === $doc_type || 'apy' === $doc_type ) {
                $print_type = get_option( 'oxygen_receipt_print_type' );
            }

            $oxygen_pdf = OxygenApi::get_invoice_pdf( $document_id, $print_type );
        } else {
            /* print notices types documents */
            $oxygen_pdf = OxygenApi::get_notice_pdf( $document_id );
        }

        $upload_dir  = wp_upload_dir();
        $oxygen_path = $upload_dir['basedir'] . '/oxygen';
        if ( ! is_dir( $oxygen_path ) ) {
            wp_mkdir_p( $oxygen_path );
        }

        $headers  = $oxygen_pdf['headers'];
        $filename = get_filename_from_disposition( $headers );

        $pdf_path = $upload_dir['basedir'] . '/oxygen/' . $filename;
        $pdf_url  = $upload_dir['baseurl'] . '/oxygen/' . $filename;

        $file_put = false;

        if ( is_array( $oxygen_pdf ) && isset( $oxygen_pdf['body'] ) ) {
            $file_put = file_put_contents( $pdf_path, $oxygen_pdf['body'] );
        }

        if ( $file_put ) {
            wp_send_json_success( $pdf_url );
        } else {
            wp_send_json_error( array( 'message' => 'Failed to generate PDF. Maybe wrong document id.' ) );
        }
    } else {

        wp_send_json_error( array( 'message' => 'Document id or document type is empty. Failed to generate PDF.' ) );
    }
}

// Hook into WordPress' AJAX system for both logged in and non-logged in users.
add_action( 'wp_ajax_download_pdf_action', 'download_pdf_action' );

/**
 * Enqueues the JavaScript file used to handle PDF downloads.
 *
 * Registers the 'download_pdf' script and localizes it with the AJAX URL
 * and a nonce for security to be used when deleting the PDF after download.
 *
 * @return void
 */
function enqueue_download_pdf_script() {

    wp_enqueue_script(
            'download_pdf',
            OXYGEN_PLUGIN_URL . '/js/download_pdf.js',
            array( 'wp-i18n' ),
            null,
            true
    );

    wp_localize_script(
            'download_pdf',
            'download_pdf_action',
            array(
                    'ajax_url' => admin_url( 'admin-ajax.php' ),
                    'nonce'    => wp_create_nonce( 'delete_pdf_nonce' ),
            )
    );
}

add_action( 'admin_enqueue_scripts', 'enqueue_download_pdf_script' );
add_action( 'wp_enqueue_scripts', 'enqueue_download_pdf_script' );

/**
 * AJAX handler to delete a downloaded PDF file from the /uploads/oxygen/ directory.
 *
 * This function verifies a nonce for security, ensures the file exists and is within the expected directory,
 * and then attempts to delete it. It prevents directory traversal by using `basename()` and `realpath()`.
 *
 * @return void Outputs a JSON response indicating success or failure.
 */
function delete_pdf_after_downloading() {

    if ( ! isset( $_POST['security'] ) || ! wp_verify_nonce( wp_unslash( $_POST['security'] ), 'delete_pdf_nonce' ) ) {
        wp_send_json_error( array( 'message' => 'Security check failed.' ) );
        return;
    }

    if ( isset( $_POST['document_name'] ) ) {
        $document_name = basename( sanitize_file_name( wp_unslash( $_POST['document_name'] ) ) );
        $upload_dir    = wp_upload_dir();
        $oxygen_path   = realpath( $upload_dir['basedir'] . '/oxygen/' );
        $file_path     = realpath( $oxygen_path . '/' . $document_name );

        if ( $file_path && strpos( $file_path, $oxygen_path ) === 0 ) {
            if ( file_exists( $file_path ) ) {
                unlink( $file_path );

            } else {
                wp_send_json_error( array( 'message' => 'File not found.' ) );
            }
        } else {
            wp_send_json_error( array( 'message' => 'Invalid file path.' ) );
        }
    } else {
        wp_send_json_error( array( 'message' => 'Document name missing.' ) );
    }
}

add_action( 'wp_ajax_delete_pdf_after_downloading', 'delete_pdf_after_downloading' );

/**
 * Extracts the filename from the Content-Disposition header.
 *
 * This function parses the `Content-Disposition` header to find and return the filename.
 *
 * @param array $headers The response headers array, typically from a wp_remote_request().
 *
 * @return string|null The extracted filename if found, or null if not present.
 */
function get_filename_from_disposition( $headers ) {

    if ( isset( $headers['content-disposition'] ) ) {
        // Match the filename in the Content-Disposition header.
        if ( preg_match( '/filename="?([^"]+)"?/', $headers['content-disposition'], $matches ) ) {
            return $matches[1]; // Return the filename.
        }
    }
    return null; // Return null if filename is not found.
}

/**
 * AJAX callback to send invoice email when triggered from the UI.
 *
 * This function is triggered via an AJAX request and sends an invoice email
 * for the specified order and document type. It logs the attempt and shows
 * an error notice if the order is invalid.
 *
 * @return void
 */
function send_invoice_email_on_click_action() {

    $order_id      = isset( $_POST['order_id'] ) ? absint( wp_unslash( $_POST['order_id'] ) ) : '';
    $document_type = isset( $_POST['document_type'] ) ? sanitize_text_field( wp_unslash( $_POST['document_type'] ) ) : '';

    if ( ! empty( $order_id ) && ! empty( $document_type ) ) {
        $order = wc_get_order( $order_id );

        if ( $order ) {
            OxygenOrder::send_invoice_email( $order, $document_type );
            OxygenHelperFunctions::debug( array( '------------- email sent by icon oxygen column -------------' ), 'info' );
        } else {
            WC_Admin_Notices::add_notice( 'error', 'Something is wrong with order\'s id. Please try again.' );
        }
    }
}

add_action( 'wp_ajax_send_invoice_email_on_click_action', 'send_invoice_email_on_click_action' );
add_action( 'wp_ajax_nopriv_send_invoice_email_on_click_action', 'send_invoice_email_on_click_action' );


/**
 * AJAX callback to change cart prices based on VAT exclusion.
 *
 * This function sets a session flag to remove VAT and recalculates the WooCommerce cart totals.
 * It also performs a security nonce check before proceeding.
 * Useful for scenarios where users need to view prices without tax (e.g., B2B transactions).
 *
 * @return void Sends a JSON success response with updated cart totals, or an error if the nonce fails.
 */
function change_price_per_vat_action() {

    if ( ! isset( $_POST['security'] ) || ! wp_verify_nonce( $_POST['security'], 'change_price_per_vat_nonce' ) ) {
        wp_send_json_error( array( 'message' => 'Security check failed.' ) );
        return;
    }

    WC()->session->set( 'oxygen_remove_tax', true );
    WC()->cart->set_session();

    if ( WC()->cart && ! WC()->cart->is_empty() ) {
        WC()->cart->calculate_totals();
    }

    wp_send_json_success(
            array(
                    'totals' => WC()->cart->get_totals(),
            )
    );
}
if ( 'yes' === get_option( 'oxygen_fetch_vat_fields' ,false ) ) {
    add_action( 'wp_ajax_change_price_per_vat_action', 'change_price_per_vat_action' );

    add_filter(
            'woocommerce_customer_taxable_address',
            function ( $address ) {
                if ( WC()->session && WC()->session->get( 'oxygen_remove_tax' ) ) {
                    return array( '', '', '' );
                }

                return $address;
            }
    );

    add_filter(
            'woocommerce_is_vat_exempt',
            function ( $exempt ) {
                if ( WC()->session && WC()->session->get( 'oxygen_remove_tax' ) ) {
                    return true;
                }

                return $exempt;
            }
    );


    add_action(
            'woocommerce_before_calculate_totals',
            function ( $cart ) {
                if ( is_admin() && ! defined( 'DOING_AJAX' ) ) {
                    return;
                }
                if ( ! is_a( $cart, 'WC_Cart' ) ) {
                    return;
                }

                if ( WC()->session && WC()->session->get( 'oxygen_remove_tax' ) ) {
                    foreach ( $cart->get_cart() as $cart_item ) {
                        $product = $cart_item['data'];
                        $product->set_tax_class( '' );
                    }
                }
            },
            10,
            1
    );

    add_action(
            'woocommerce_thankyou',
            function ( $order_id ) {
                WC()->session->__unset( 'oxygen_remove_tax' );
            }
    );
}

/**
 * AJAX callback to restore cart prices including VAT.
 *
 * This function removes the session flag that disables VAT (`oxygen_remove_tax`),
 * resets the WooCommerce cart session, and recalculates the totals with taxes included.
 * It includes a nonce verification step to ensure security.
 *
 * @return void Sends a JSON success response with the updated cart totals, or an error if the nonce fails.
 */
function restore_price_with_tax_action() {

    if ( ! isset( $_POST['security'] ) || ! wp_verify_nonce( wp_unslash( $_POST['security'] ), 'restore_price_with_tax_nonce' ) ) {
        wp_send_json_error( array( 'message' => 'Security check failed.' ) );
        return;
    }

    WC()->session->__unset( 'oxygen_remove_tax' );
    WC()->cart->set_session();
    WC()->cart->calculate_totals();

    wp_send_json_success(
            array(
                    'totals' => WC()->cart->get_totals(),
            )
    );
}
if ( 'yes' === get_option( 'oxygen_fetch_vat_fields' ,false ) ) {
    add_action( 'wp_ajax_restore_price_with_tax_action', 'restore_price_with_tax_action' );
}

function is_edit_order_screen() {
    return is_admin() &&
           isset( $_GET['post'] ) &&
           isset( $_GET['action'] ) &&
           $_GET['action'] === 'edit' &&
           get_post_type( $_GET['post'] ) === 'shop_order';
}

if ( 'yes' === get_option( 'oxygen_fetch_vat_fields' ,false ) ) {

    add_action( 'wp_ajax_oxygen_copy_shipping_meta', function () {
        if ( ! current_user_can( 'edit_shop_orders' ) ) {
            wp_send_json_error( [ 'message' => 'Unauthorized' ] );
        }

        $order_id = intval( $_POST['order_id'] ?? 0 );

        if ( ! $order_id ) {
            wp_send_json_error( [ 'message' => 'Invalid order ID' ] );
        }

        wp_send_json_success( oxygen_get_shipping_field_ids() );
    } );
}

function oxygen_get_shipping_field_ids() {

    return array(
            'oxygen_move_purpose'              => get_option('oxygen_move_purpose', ''),
            'oxygen_other_move_purpose_title'  => get_option('oxygen_other_move_purpose_title', ''),
            'oxygen_vehicle_number'            => get_option('oxygen_vehicle_number', ''),
            'oxygen_shipping_comments'         => get_option('oxygen_shipping_comments', ''),
            'oxygen_pickup_branch_code'        => get_option('oxygen_pickup_branch_code', ''),
            'oxygen_pickup_street'             => get_option('oxygen_pickup_street', ''),
            'oxygen_pickup_address_number'     => get_option('oxygen_pickup_address_number', ''),
            'oxygen_pickup_postal_code'        => get_option('oxygen_pickup_postal_code', ''),
            'oxygen_pickup_city'               => get_option('oxygen_pickup_city', ''),
            'oxygen_pickup_country'            => get_option('oxygen_pickup_country', '')
    );
}