<?php

if ( !defined( 'ABSPATH' ) ) {

    exit;
}

if ( !class_exists( 'Pricely_View_Data' ) ) {

    require_once 'views-data-countdown.php';
    require_once 'views-data-tables/tables.php';
    require_once 'views-data-label.php';

    class Pricely_View_Data {

        private static $instance;
        private $promotion_price_at_checkout;
        private $source_prices;
        private $shop_prices_context;
        private $source_prices_key;
        private $currency;

        public static function get_instance(): self {

            if ( !self::$instance ) {

                self::$instance = new self();
            }

            return self::$instance;
        }

        public function __construct() {

            $this->promotion_price_at_checkout = Pricely_Product_Promotion_Price_At_Checkout::get_instance();

            $this->source_prices = array();
            $this->shop_prices_context = 'shop_prices';
            $this->source_prices_key = 'source_prices';
        }

        public function get_regular_price( $product_id, $variation_id ) {

            return $this->get_source_regular_price( $product_id, $variation_id );
        }

        public function get_price_at_checkout( $price_args, $product_id, $variation_id ) {

            $product = array(
                'product_id' => $product_id,
                'variation_id' => $variation_id
            );

            $product[ 'source_prices' ] = $this->get_source_prices( $product_id, $variation_id );

            return $this->promotion_price_at_checkout->calculate( $price_args, false, $this->prepare_product_prices( $product ) );
        }

        public function get_price_to_display( $price, $product_id, $variation_id = 0 ) {

            $product = Pricely_Product::get_instance()->get_product( $product_id );

            $variation = ($variation_id > 0) ? Pricely_Product::get_instance()->get_variation_by_id( $product_id, $variation_id ) : null;

            return Pricely_Util::get_instance()->get_price_to_display( $price, $product, $variation );
        }

        public function get_min_price( $prices ) {

            $min_price = -1;


            foreach ( $prices as $price ) {

                if ( $min_price < 0 ) {

                    $min_price = $price;

                    continue;
                }

                if ( $price < $min_price ) {

                    $min_price = $price;
                }
            }

            if ( $min_price < 0 ) {

                $min_price = 0;
            }

            return $min_price;
        }

        public function get_max_price( $prices ) {

            $max_price = 0;

            foreach ( $prices as $price ) {

                if ( $price > $max_price ) {

                    $max_price = $price;
                }
            }

            return $max_price;
        }

        public function get_min_discount_prices( $regular_prices, $prices ) {

            $discount = 0;

            $min_prices = array();

            foreach ( $regular_prices as $key => $regular_price ) {

                $price = 0;

                if ( isset( $prices[ $key ] ) ) {

                    $price = $prices[ $key ];
                }

                if ( !count( $min_prices ) ) {

                    $discount = $regular_price - $price;
                    $min_prices[ 'price' ] = $regular_price;
                    $min_prices[ 'discount_price' ] = $price;

                    continue;
                }

                $new_discount = $regular_price - $price;

                if ( $discount > $new_discount ) {

                    $discount = $new_discount;
                    $min_prices[ 'price' ] = $regular_price;
                    $min_prices[ 'discount_price' ] = $price;
                }
            }

            return $min_prices;
        }

        public function get_max_discount_prices( $regular_prices, $prices ) {

            $discount = 0;

            $max_prices = array();

            foreach ( $regular_prices as $key => $regular_price ) {

                $price = 0;

                if ( isset( $prices[ $key ] ) ) {

                    $price = $prices[ $key ];
                }

                if ( !count( $max_prices ) ) {

                    $discount = $regular_price - $price;
                    $max_prices[ 'price' ] = $regular_price;
                    $max_prices[ 'discount_price' ] = $price;

                    continue;
                }


                $new_discount = $regular_price - $price;

                if ( $new_discount > $discount ) {

                    $discount = $new_discount;

                    $max_prices[ 'price' ] = $regular_price;
                    $max_prices[ 'discount_price' ] = $price;
                }
            }

            return $max_prices;
        }

        public function same_min_max_discounts( $min_prices, $max_prices ) {

            $min_discount = $min_prices[ 'price' ] - $min_prices[ 'discount_price' ];

            $max_discount = $max_prices[ 'price' ] - $max_prices[ 'discount_price' ];

            return ($min_discount == $max_discount);
        }

        public function get_discount_text( $regular_price, $price, $mode, $show_per = false ) {

            $discount = 0;

            if ( $regular_price > $price ) {
                $discount = $regular_price - $price;
            }

            if ( 'discount' == $mode ) {
                return wc_price( $this->convert_amount( $discount, 'views-data-discount-text' ) );
            }

            $per_format = esc_html__( '{{percent}}%', 'pricely-dynamic-pricing-cart-discounts' );

            if ( $discount == 0 && $show_per ) {

                $args = array( 'percent' => 0 );

                return $this->replace_text( $per_format, $args );
            }

            if ( $discount == 0 ) {

                return '0';
            }

            $per = (($discount / $regular_price) * 100);

            if ( $show_per ) {

                $args = array( 'percent' => Pricely_Totals_Util::get_instance()->round( $per, 2 ) );

                return $this->replace_text( $per_format, $args );
            }

            return Pricely_Totals_Util::get_instance()->round( $per, 2 );
        }

        public function replace_text( $text_format, $args ) {

            $replacements = array();

            if ( isset( $args[ 'percent' ] ) ) {

                $replacements[ '{{percent}}' ] = $args[ 'percent' ];
            }

            if ( isset( $args[ 'from_discount' ] ) ) {

                $replacements[ '{{from_discount}}' ] = $args[ 'from_discount' ];
            }

            if ( isset( $args[ 'to_discount' ] ) ) {

                $replacements[ '{{to_discount}}' ] = $args[ 'to_discount' ];
            }

            if ( isset( $args[ 'from_price' ] ) ) {

                $replacements[ '{{from_price}}' ] = $args[ 'from_price' ];
            }

            if ( isset( $args[ 'to_price' ] ) ) {

                $replacements[ '{{to_price}}' ] = $args[ 'to_price' ];
            }

            if ( isset( $args[ 'from_quantity' ] ) ) {

                $replacements[ '{{from_quantity}}' ] = $args[ 'from_quantity' ];
            }

            if ( isset( $args[ 'to_quantity' ] ) ) {

                $replacements[ '{{to_quantity}}' ] = $args[ 'to_quantity' ];
            }

            return str_replace( array_keys( $replacements ), array_values( $replacements ), $text_format );
        }

        public function get_price_suffix( $product_id, $variation_id = 0, $price = '', $qty = 1 ) {

            $product = Pricely_Product::get_instance()->get_product( $product_id );

            $variation = ($variation_id > 0) ? Pricely_Product::get_instance()->get_variation_by_id( $product_id, $variation_id ) : null;

            return Pricely_Util::get_instance()->get_price_suffix( $product, $variation, $price, $qty );
        }

        public function get_source_prices( $product_id, $variation_id = 0 ) {

            if ( isset( $this->source_prices[ $product_id ][ $variation_id ] ) ) {

                return $this->source_prices[ $product_id ][ $variation_id ];
            }

            $prices = $this->get_pipeline_shop_prices( $this->source_prices_key, $product_id, $variation_id );

            if ( !count( $prices ) ) {

                $prices = $this->get_pipeline_shop_prices( $this->source_prices_key, $product_id, $variation_id, false );
            }

            if ( $prices ) {

                $this->source_prices[ $product_id ][ $variation_id ] = apply_filters( 'pricely_view-data_get-source-prices', $prices, $product_id, $product_id );
            }

            return $prices;
        }

        public function convert_amount( $amount, $amount_id ) {

            if ( is_null( $this->currency ) ) {

                $this->currency = Pricely_Currency::get_instance();
            }

            return $this->currency->convert_amount( $amount, $amount_id );
        }

        private function get_source_regular_price( $product_id, $variation_id ) {

            $prices = $this->get_source_prices( $product_id, $variation_id );

            if ( false === $prices ) {

                return false;
            }

            if ( !isset( $prices[ 'regular_price' ] ) ) {

                return false;
            }

            if ( '' == $prices[ 'regular_price' ] ) {

                return false;
            }

            return $prices[ 'regular_price' ];
        }

        private function get_pipeline_shop_prices( $prices_key, $product_id, $variation_id, $use_cache = true ) {

            $pipeline = Pricely_Pipeline::get_instance();


            $cache_data = $pipeline->get_product_cache( $product_id, $variation_id, $this->shop_prices_context );

            if ( isset( $cache_data[ $prices_key ] ) && $use_cache ) {

                return $cache_data[ $prices_key ];
            }

            $product = Pricely_Product::get_instance()->get_product( $product_id );
            $variation = ($variation_id > 0) ? Pricely_Product::get_instance()->get_variation_by_id( $product_id, $variation_id ) : null;


            $data = $pipeline->get_product_data( $product, $variation, $this->shop_prices_context );

            if ( isset( $data[ $prices_key ] ) ) {

                return $data[ $prices_key ];
            }

            return false;
        }

        private function prepare_product_prices( $product ) {

            if ( !isset( $product[ 'source_prices' ][ 'regular_price' ] ) || empty( $product[ 'source_prices' ][ 'regular_price' ] ) ) {

                $product[ 'source_prices' ][ 'regular_price' ] = 0;
            }


            if ( !isset( $product[ 'source_prices' ][ 'sale_price' ] ) || empty( $product[ 'source_prices' ][ 'sale_price' ] ) ) {

                $product[ 'source_prices' ][ 'sale_price' ] = $product[ 'source_prices' ][ 'regular_price' ];
            }

            return $product;
        }

    }

}
