<?php

namespace Pay4AllForMypos\Support;

use Pay4AllForMypos\Engine\Adapter\DirectLogger;

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

class WooBridge
{
    /**
     * Checks if WooCommerce higher or equal $version is installed.
     *
     * @param $version
     * @return mixed
     */
    public static function is_woocommerce_version_up( $version )
    {
        return version_compare( WOOCOMMERCE_VERSION, $version, '>=' );
    }

    /**
     * @param $property
     * @param $order
     * @return mixed
     */
    public static function get( $property, $order )
    {
        if ( is_numeric( $order ) || is_string( $order ) ) {
            $order = wc_get_order( $order );
        }

        if ( 'id' == strtolower( $property ) ) {
            $func = 'get_id';
        } else {
            $func = 'get_' . $property;
        }
        return $order->$func();
    }

    /**
     * @param $order
     * @return mixed
     */
    public static function get_order_status( $order )
    {
        if ( version_compare( WOOCOMMERCE_VERSION, '3.0.0', '>=' ) ) {
            return $order->get_status();
        } else {
            return $order->status;
        }
    }

    /**
     * @param $order
     * @return bool
     */
    public static function is_order_complete( $order )
    {
        $wc_order_status = static::get_order_status( $order );
        if ( $wc_order_status == 'processing' || $wc_order_status == 'completed' ) {
            return true;
        }

        return false;
    }

    /**
     * Checks if the WC order only contains virtual products.
     *
     * @param $order
     * @return bool
     */
    public static function is_virtual_order( $order )
    {
        $items = $order->get_items();

        if ( 0 >= count( $items ) ) {
            return false;
        }

        foreach ( $items as $item ) {

            $product = wc_get_product( '0' != $item[ 'variation_id' ] ? $item[ 'variation_id' ] : $item[ 'product_id' ] );

            if ( !$product ) {
                continue;
            }

            if ( !$product->is_virtual() ) {
                return false;
            }
        }

        return true;
    }

    /**
     * Updates the order status after a successful payment.
     *
     * @param \WC_Order $order
     * @param bool $is_deferred
     */
    public static function update_order_successful( $order, $is_deferred = false )
    {
        if ( $is_deferred ) {
            $deferred_status = get_option( 'pay4all_for_mypos_settings_deferred_order_status' );
            $order_status    = !empty( $deferred_status ) ? $deferred_status : PAY4ALL_FOR_MYPOS_DEFAULT_STATUS_DEFERRED;
        } elseif ( static::is_virtual_order( $order ) ) {
            $virtual_status = get_option( 'pay4all_for_mypos_settings_order_status_virtual' );
            $order_status   = !empty( $virtual_status ) ? $virtual_status : PAY4ALL_FOR_MYPOS_DEFAULT_STATUS_VIRTUAL;
        } else {
            $non_virtual_status = get_option( 'pay4all_for_mypos_settings_order_status_non_virtual' );
            $order_status       = !empty( $non_virtual_status ) ? $non_virtual_status : PAY4ALL_FOR_MYPOS_DEFAULT_STATUS_ORDER;
        }

        switch ( $order_status ) {

            case 'processing':
                $order->payment_complete();
                break;

            case 'completed':
                $order->payment_complete();
                $order->update_status( 'completed' );
                break;

            case 'on-hold':
            default:
                $order->update_status( 'on-hold' );
                break;
        }

        DirectLogger::log_event( 'update_order_successful', sprintf( 'Updated order to status %1$s', $order_status ), $order->get_id() );

        global $woocommerce;
        $cart = $woocommerce->cart;
        if ( $cart ) {
            $cart->empty_cart();
        }
    }

    /**
     * @param \WC_Order|string|int $order
     * @param string $key
     * @param mixed $single
     * @return mixed
     * @since 6.0.0
     */
    public static function get_order_meta( $order, $key, $single = true )
    {
        if ( !is_object( $order ) ) {
            $order = wc_get_order( $order );
        }

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

        return $order->get_meta( $key, $single );
    }

    /**
     * @param \WC_Order|string|int $order
     * @param string $key
     * @param mixed $value
     * @return mixed
     * @since 6.0.0
     */
    public static function update_order_meta( $order, $key, $value, $save = true )
    {
        if ( !is_object( $order ) ) {
            $order = wc_get_order( $order );
        }

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

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

        if ( $save ) {
            return $order->save();
        }

        return true;
    }

    public static function delete_order_meta( $order, $key, $value = '', $save = true )
    {
        if ( !is_object( $order ) ) {
            $order = wc_get_order( $order );
        }

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

        if ( !empty( $value ) && $value != $order->get_meta( $key, true ) ) {
            return false;
        }

        Journal::event( 'Deleting meta ' . $key );
        $order->delete_meta_data( $key, $value );

        if ( $save ) {
            return $order->save();
        }

        return true;
    }

    /**
     * Returns the correct screen id for WC pages. HPOS-ready and backward-compatible.
     *
     * @param $screen
     * @return mixed|string
     */
    public static function get_wc_screen( $screen = 'shop-order' )
    {
        if ( !class_exists( '\Automattic\WooCommerce\Internal\DataStores\Orders\CustomOrdersTableController' ) ) {
            return $screen;
        }

        return wc_get_container()->get( \Automattic\WooCommerce\Internal\DataStores\Orders\CustomOrdersTableController::class )->custom_orders_table_usage_is_enabled()
            ? wc_get_page_screen_id( $screen )
            : str_replace( '-', '_', $screen );
    }

    /**
     * Returns the language of an order.
     * e.g. de
     *
     * @param $order_id
     * @return bool|string
     */
    public static function get_order_language( $order_id, $two_chars = true )
    {
        // Get WPML order language.
        $lang = WooBridge::get_order_meta( $order_id, 'wpml_language', true );

        // WPML
        if ( empty( $lang ) && function_exists( 'icl_object_id' ) ) {
            // phpcs:ignore WordPress.NamingConventions.PrefixAllGlobals.NonPrefixedHooknameFound -- WPML public API filter ; must be invoked verbatim.
            $lang = apply_filters( 'wpml_current_language', null );
        }

        if ( empty( $lang ) ) {
            $lang = get_locale();
        }

        if ( empty( $lang ) ) {
            return 'en';
        }

        $parts = explode( '_', $lang );
        if ( !empty( $parts ) ) {
            $lang = $parts[ 0 ];
        }

        if ( $two_chars ) {
            return substr( $lang, 0, 2 );
        }

        return $lang;
    }

    /**
     * @param \WC_Order $wc_order
     * @return string
     */
    public static function get_order_currency( $wc_order )
    {
        $currency = $wc_order->get_currency();
        if ( !$currency ) {
            $currency = get_woocommerce_currency();
        }
        return strtoupper( $currency );
    }

    /**
     * Safely process a WooCommerce order with a custom condition and transient-based lock.
     *
     * @param int $order_id WooCommerce order ID.
     * @param callable $condition A function that receives a WC_Order and returns true if the critical section should run.
     * @param callable $callback A function to run on the order if the condition is met.
     * @param int $lock_expiry Duration of the lock in seconds. Default is 30.
     * @return bool True if the critical section was run, false otherwise.
     */
    public static function process_order_with_lock_condition( $order_id, $condition, $callback, $lock_expiry = 30 )
    {
        $lock_key = PAY4ALL_FOR_MYPOS_PREFIX . "_order_lock_{$order_id}";

        if ( get_transient( $lock_key ) ) {
            return false;
        }

        set_transient( $lock_key, true, $lock_expiry );

        try {
            $order = wc_get_order( $order_id );
            if ( !$order ) {
                throw new Exception( "Order $order_id not found." );
            }

            if ( call_user_func( $condition, $order ) ) {
                call_user_func( $callback, $order );
                Journal::info( 'Process lock ' . $lock_key );
                return true;
            }
        } catch ( \Exception $e ) {
            Journal::error( "Error processing order $order_id: " . $e->getMessage() );
        } finally {
            delete_transient( $lock_key );
        }

        return false;
    }
}
