<?php

namespace Bright_Deposits_For_WooCommerce\Helpers;
use Bright_Deposits_For_WooCommerce\Core\ContainerManager;

/**
 * @package Bright_Deposits_For_WooCommerce\Helpers
 * @since 1.0.0
 * @author Bright Plugins
 * Description: This class is responsible for handling the helper functions for the plugin.
 */
class Helper {
    /**
	 * Singleton instance of the class.
	 */
	private static $instance = null;

	/**
	 * Get the singleton instance of the class.
	 * @since 1.0.0
	 * @return Helper
	 */
	public static function instance() {
		if ( is_null( self::$instance ) ) {
			self::$instance = new self();
		}
		return self::$instance;
	}

	/**
	 * Prevents cloning of the instance.
	 * @since 1.0.0
	 * @return void
	 */
	private function __clone() {
		// Cloning is forbidden.
	}

	/**
	 * Prevents unserializing of the instance.
	 * @since 1.0.0
	 * @return void
	 */
	public function __wakeup() {
		// Unserializing instances of this class is forbidden.
	}

    /**
     * Get the deposit to pay html.
     * @since 1.0.0
     * @return string
     */
    public static function getDepositToPayHtml() {
        $initial_payment_total = WC()->session->get('bdfwbp_cart_deposit_amount');
        return apply_filters('woocommerce_deposit_to_pay_html', wc_price($initial_payment_total));
    }

    /**
     * Get the due to pay html.
     * @since 1.0.0
     * @return string
     */
    public static function getDueToPayHtml() {
        $duePayment = WC()->session->get('bdfwbp_cart_due_amount');

        /**
         * BDFWBP_CUSTOM_FILTER_HOOK: Allows developers to modify the due payment html.
         * @since 1.0.0
         * @param string    $duePayment The due payment.
         * @return string
         */
        return apply_filters('bdfwbp_due_payment_html', wc_price($duePayment));
    }

    /**
     * Displays the deposit and due payment totals on cart and checkout pages.
     * @since 1.0.0
     * @return void
     */
    public static function displayToPayHtml() {
        $container = ContainerManager::get('helper');
        $next_payment_date = $container->getNextPaymentDate();
        ?>

        <!--<tr class="order-topay">
            <th> <span id="deposit-help" data-tipso-color="#fff" data-tipso-background="#555555" data-tipso="<?php //echo esc_attr(self::getTipsoContent()) ?>"><?php //echo esc_html(self::getOptionValue('bdfw_to_pay_label')); ?></span></th>
            <td data-title="<?php //echo esc_html(self::getOptionValue('bdfw_to_pay_label')); ?>"><?php //echo wp_kses_post(self::getDepositToPayHtml()); ?></td>
        </tr>-->
        <tr class="order-duepay">
            <th><?php echo esc_html( self::getOptionValue('bdfw_due_payment_label') ); ?></th>
            <td data-title="<?php echo esc_attr( self::getOptionValue('bdfw_due_payment_label') ); ?>">
                <?php echo wp_kses_post( self::getDueToPayHtml() ); ?>
                <div class="bdfw-next-payment-date">
                    <?php
                        echo esc_html( Helper::getOptionValue( 'bdfw_next_payment_date_label' ) ) . ' <strong>' . esc_html( $next_payment_date ) . '</strong>';
                    ?>
                </div>
            </td>
        </tr>
        <?php
    }

    /**
     * Checks if the cart has deposit items and a total greater than 0, then displays the "To Pay" HTML.
     * This helps avoid code duplication in Cart and Checkout pages.
     *
     * @since 1.0.0
     */
    public static function maybeDisplayToPayHtml() {
        if ( self::cartHaveDepositItem() && WC()->cart->get_total( 'edit' ) > 0 ) {
            self::displayToPayHtml();
        }
    }

    /**
     * Check if the cart has deposit item.
     * @since 1.0.0
     * @return bool
     */
    public static function cartHaveDepositItem() {
        // Bail early if cart is not available or empty.
        if ( ! is_object( WC()->cart ) || WC()->cart->is_empty() ) {
            return false;
        }

        foreach ( WC()->cart->get_cart() as $cart_item ) {
            // The '_deposit_mode' is only set for items with a deposit.
            // If we find one, we can immediately return true.
            if ( isset( $cart_item['_deposit_mode'] ) && 'check_deposit' === $cart_item['_deposit_mode'] ) {
                return true;
            }
        }

        // If we get here, no deposit items were found.
        return false;
    }

    /**
     * Check if the product type is deposit.
     * @since 1.0.0
     * @param int $product_id
     * @return bool
     */
    public static function isProductTypeDeposit($product_id) {
        $ed = get_post_meta($product_id, '_bdfwbp_enable_deposit', true);

        if ('yes' == $ed || self::getOptionValue('global_deposits_mode') == 1) {
            return true;
        }
        return false;
    }

    /**
     * Get the option value.
     * @since 1.0.0
     * @param string $option
     * @return mixed
     */
    public static function getOptionValue( $option ) {
        $settings = get_option('bdfwbp_deposits_settings');

        // If settings are not found or not an array, use the default value from getDefaultValue
        if ( ! is_array( $settings ) ) {
            return self::getDefaultValue($option);
        }
        // If the option exists in settings and is not empty, return its value; otherwise, return the default value
        return ( isset($settings[$option]) && $settings[$option] !== '' )
            ? $settings[$option]
            : self::getDefaultValue($option);
    }

    /**
     * Get the payment gateway list.
     * @since 1.0.0
     * @return array
     */
    public static function getPaymentGatewayList() {
        $active_gateways = array();
        $gateways = WC()->payment_gateways->payment_gateways();
        foreach ($gateways as $id => $gateway) {
            if ($gateway->enabled == 'yes') {
                $active_gateways[$id] = $gateway->title;
            }
        }
        return $active_gateways;
    }

    /**
     * Get the order status.
     * @since 1.0.0
     * @return array
     */
    public static function getOrderStatus() {
        $allStatus = array();
        $status = wc_get_order_statuses();
        foreach ($status as $id => $s) {
            $allStatus[$id] = $s;
        }
        return $allStatus;
    }

    /**
     * Get the shipping total.
     * @since 1.0.0
     * @return string
     */
    public static function getShippingTotal() {
        if (self::getOptionValue('bdfw_exclude_shipping_fee') == 1) {
            $shipping = self::getOptionValue('bdfw_tooltip_pay_later');
        } else {
            $shipping = WC()->cart->get_cart_shipping_total();
        }
        return $shipping;
    }

    /**
     * Get the tipso content.
     * @since 1.0.0
     * @return string
     */
    public static function getTipsoContent() {
        $labels = array(
            'cart_items' => self::getOptionValue('bdfw_tooltip_items'),
            'shipping' => self::getOptionValue('bdfw_tooltip_shipping'),
        );

        $tip_information = '<ul class="deposit-cart-data">';

        $tip_information .= '<li>' . esc_html( $labels['cart_items'] ) . ' : ' . wp_kses_post( self::getDepositToPayHtml() ) . '</li>';
        $tip_information .= '<li>' . esc_html( $labels['shipping'] ) . ' : ' . wp_kses_post( self::getShippingTotal() ) . '</li>';

        $tip_information .= '</ul>';
        return $tip_information;
    }

    /**
     * Apply tax for deposit order.
     * @since 1.0.0
     * @return bool
     */
    public static function applyTaxforDepositOrder() {
        $value = false;
        return apply_filters('woocommerce_deposit_apply_tax_calculate_totals', $value);
    }

    /**
     * Check if the order is a deposit order.
     * @since 1.0.0
     * @param int $order_id
     * @return bool
     */
    public static function isDepositOrder($order_id) {
        $order = wc_get_order($order_id);
        if (!$order) {
            return false;
        }

        if (!empty($order->get_meta('_deposit_value', true))) {
            return true;
        }

        return false;
    }
    
    /**
     * Check if WooCommerce is installed.
     * @since 1.0.0
     * @return bool
     */
    public static function isWoocommerceInstalled() {
        // Ensure the is_plugin_active function is available, as it's not always loaded on the frontend.
        if ( ! function_exists( 'is_plugin_active' ) ) {
            include_once ABSPATH . 'wp-admin/includes/plugin.php';
        }
        return is_plugin_active('woocommerce/woocommerce.php');
    }

    /**
     * Get all products.
     * @since 1.0.0
     * @return array
     */
    public static function getAllProducts() {
        $products = wc_get_products( array(
            'status' => 'publish',
            'limit'  => -1,
        ) );

        $product_options = array();

        foreach ( $products as $product ) {
            $product_options[ $product->get_id() ] = $product->get_name();
        }

        return $product_options;
    }

    /**
     * Get all categories.
     * @since 1.0.0
     * @return array
     */
    public static function getAllCategories() {
        $categories = get_terms( array(
            'taxonomy'   => 'product_cat',
            'hide_empty' => false, // Change to true if you want to hide empty categories
        ) );

        $category_options = array();

        foreach ( $categories as $category ) {
            $category_options[ $category->term_id ] = $category->name;
        }
        
        return $category_options;
    }

    /**
     * Get the default value.
     * @since 1.0.0
     * @param string $field_id
     * @return mixed
     */
    public static function getDefaultValue($field_id) {
        $default_values = array(
            'select_mode'                          => 'allow_mix',
            'global_deposits_mode'                 => '0',
            'global_deposit_type'                  => 'percentage',
            'global_deposit_percentage'            => 100,
            'global_deposit_fixed_amount'          => 50,
            'global_force_deposit'                 => '0',
            'global_hide_deposit_input'            => '0',
            'predefine_full_payment'               => '0',
            'variable_product_mode'                => 'child',
            'days_to_pay_installment'              => 7,
            'days_before_due'                      => 3,
            'bdfw_pay_deposit_label'               => __( 'Pay deposit', 'bright-deposits-for-woocommerce' ),
            'bdfw_full_payment_label'              => __( 'Full payment', 'bright-deposits-for-woocommerce' ),
            'bdfw_deposit_label'                   => __( 'Deposit', 'bright-deposits-for-woocommerce' ),
            'bdfw_per_item_label'                  => __( 'Per item', 'bright-deposits-for-woocommerce' ),  
            'bdfw_due_payment_label'               => __( 'Balance', 'bright-deposits-for-woocommerce' ),
            'bdfw_to_pay_label'                    => __( 'To Pay', 'bright-deposits-for-woocommerce' ),
            'bdfw_due_payment_for_order_label'     => __( 'Due Payment For Order', 'bright-deposits-for-woocommerce' ),
            'bdfw_paid_label'                      => __( 'Paid', 'bright-deposits-for-woocommerce' ),
            'bdfw_deposit_payment_details_label'   => __( 'Deposit Payment Details', 'bright-deposits-for-woocommerce' ),
            'bdfw_deposit_payments_summary_label'  => __( 'Deposit Payments Summary', 'bright-deposits-for-woocommerce' ),
            'bdfw_payment_label'                   => __( 'Payment', 'bright-deposits-for-woocommerce' ),
            'bdfw_payment_id_label'                => __( 'Payment ID', 'bright-deposits-for-woocommerce' ),
            'bdfw_status_label'                    => __( 'Status', 'bright-deposits-for-woocommerce' ),
            'bdfw_amount_label'                    => __( 'Amount', 'bright-deposits-for-woocommerce' ),
            'bdfw_actions_label'                   => __( 'Actions', 'bright-deposits-for-woocommerce' ),
            'bdfw_make_payment_label'              => __( 'Make Payment', 'bright-deposits-for-woocommerce' ),
            'bdfw_relationship_label'              => __( 'Relationship', 'bright-deposits-for-woocommerce' ),
            'bdfw_date_label'                      => __( 'Date', 'bright-deposits-for-woocommerce' ),
            'bdfw_total_label'                     => __( 'Total', 'bright-deposits-for-woocommerce' ),
            'bdfw_order_number_label'              => __( 'Order Number', 'bright-deposits-for-woocommerce' ),
            'global_deposits_value'                => 0,
            'global_deposits_type'                 => '',
            'deposit_notice'                       => __('You cannot mix deposit products and full payment products in the same order. Please complete your current order first.', 'bright-deposits-for-woocommerce'),
            'regular_notice'                       => __('You cannot mix full payment products and deposit products in the same order. Please complete your current order first.', 'bright-deposits-for-woocommerce'),
            'bdfw_full_payment_not_allowed_label'  => __('Full Payment is Not Allow', 'bright-deposits-for-woocommerce'),
            'bdfw_reminder_sent_note'              => __('Deposit reminder manually sent to customer.', 'bright-deposits-for-woocommerce'),
            'bdfw_send_reminder_notification_label'=> __('Send deposit reminder notification', 'bright-deposits-for-woocommerce'),
            'bdfw_deposit_payments_label'          => __('Deposit Payments', 'bright-deposits-for-woocommerce'),
            'bdfw_deposit_payment_label'           => __('Deposit payment', 'bright-deposits-for-woocommerce'),
            'bdfw_due_label'                       => __('Due', 'bright-deposits-for-woocommerce'),
            'bdfw_due_amount_label'                => __('Due Amount', 'bright-deposits-for-woocommerce'),
            'fully_paid_status'                    => 'processing',
            'bdfw_tax_fee'                         => 'wdp',
            'bdfw_shipping_fee'                    => 'wdp',
            'bdfw_additional_fees'                 => 'wdp',
            'bdfw_deposit_payment_for_order_label' => __('Deposit Payment for order', 'bright-deposits-for-woocommerce'),
            'bdfw_exclude_shipping_fee'            => '0',
            'bdfw_tooltip_pay_later'               => __('Pay with future payment', 'bright-deposits-for-woocommerce'),
            'bdfw_tooltip_items'                   => __('Cart Items', 'bright-deposits-for-woocommerce'),
            'bdfw_tooltip_shipping'                => __('Shipping', 'bright-deposits-for-woocommerce'),
            'bdfw_partial_payment_amount_label'    => __('Partial Payment amount', 'bright-deposits-for-woocommerce'),
            'excluded_products'                    => [],
            'excluded_product_categories'          => [],
            'exclude_on_sale_products'             => false,
            'bdfw_order_label'                     => __('Order', 'bright-deposits-for-woocommerce'),
            'bdfw_payment_installment_label'       => __('Payment of this installment is for the following product(s)', 'bright-deposits-for-woocommerce'),
            'bdfw_next_payment_date_label'         => __('Next payment date', 'bright-deposits-for-woocommerce'),
            'bdfw_deposit_notice_custom_text'      => __('Reserve this product today by paying only {deposit_display_value} of the total amount and make the next payment on {next_payment_date} to complete your purchase.', 'bright-deposits-for-woocommerce'),
        );

        /**
         * BDFWBP_CUSTOM_FILTER_HOOK: Allows developers to add and modify the default values.
         * @since 1.0.0
         * @param array    $default_values The default values.
         * @return array
         */
        $default_values = apply_filters('bdfwbp_default_values', $default_values);

        return isset($default_values[$field_id]) ? $default_values[$field_id] : '';
    }

    /**
     * Get the next payment date.
     * @since 1.0.0
     * @param \WC_Order $order
     * @return string
     */
    public static function getNextPaymentDate( $order = null ) {
        // get the days to pay from the options
        $days_to_pay = intval( self::getOptionValue( 'days_to_pay_installment' ) );

        // determine the base timestamp
        if ( $order instanceof \WC_Order && $order->get_date_created() ) {
            $base_timestamp = $order->get_date_created()->getTimestamp();
        } 
        else {
            $base_timestamp = current_time( 'timestamp' );
        }

        // calculate the next payment timestamp
        $next_payment_timestamp = strtotime( "+$days_to_pay days", $base_timestamp );
        $next_payment_date = date_i18n( get_option( 'date_format' ), $next_payment_timestamp );

        return esc_html( $next_payment_date );
    }

}