<?php

if ( !defined( 'ABSPATH' ) ) {

    exit;
}

if ( !class_exists( 'Pricely_Pipeline_Cart_Prices' ) ) {

    class Pricely_Pipeline_Cart_Prices {

        private static $instance;
        private static $shop_prices;
        private static $any_prices;
        private $is_checkout;
        private $is_cart;
        private $product_util;
        private $calculated_prices_key;
        private $context;

        public static function get_instance(): self {

            if ( !self::$instance ) {

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

            return self::$instance;
        }

        public function __construct() {

            $this->calculated_prices_key = 'calculated_prices';
            $this->context = 'cart_prices';
        }

        public function get_shop_prices() {

            return self::$shop_prices;
        }

        public function get_any_prices() {

            return self::$any_prices;
        }

        public function get_price( $price, $product, $variation = null ) {

            $this->set_any_price( $price, $product, $variation );

            if ( !$this->can_use_cart_prices() ) {

                return false;
            }

            $calculated_prices = $this->get_calculated_prices( $product, $variation );

            if ( !$calculated_prices ) {

                return false;
            }

            $this->set_shop_price( $price, $product, $variation );

            $final_price = $this->get_final_price( $price, $calculated_prices );

            if ( false === $final_price ) {

                return false;
            }

            return $final_price;
        }

        public function get_items_data() {

            $data = $this->get_data();

            if ( !$data ) {

                return false;
            }

            if ( !isset( $data[ 'items' ] ) || false === $data[ 'items' ] ) {

                return false;
            }

            return array(
                'items' => $data[ 'items' ],
                'tooltips' => isset( $data[ 'tooltips' ] ) ? $data[ 'tooltips' ] : array(),
            );
        }

        private function get_final_price( $price, $calculated_prices ) {

            $item_qty = $calculated_prices[ 'item_qty' ];
            $qty = $calculated_prices[ 'qty' ];

            $original_total = 0;

            if ( $item_qty > $qty ) {

                $original_total = ($item_qty - $qty) * $price;
            }

            $total = array_sum( $calculated_prices[ 'prices' ] );

            return ($total + $original_total) / $item_qty;
        }

        private function get_calculated_prices( $product, $variation ) {

            $cache_data = $this->get_product_cache( $product, $variation );

            if ( isset( $cache_data[ $this->calculated_prices_key ] ) ) {

                return $cache_data[ $this->calculated_prices_key ];
            }

            if ( $this->is_cache_valid() ) {

                return false;
            }

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

            if ( isset( $data[ $this->calculated_prices_key ] ) ) {

                return $data[ $this->calculated_prices_key ];
            }


            return false;
        }

        private function get_product_cache( $product, $variation ) {

            $product_id = $product->get_id();
            $variation_id = 0;

            if ( $variation ) {

                $variation_id = $variation->get_id();
            }

            $parent_id = $product->get_parent_id();

            if ( $parent_id > 0 && 'variation' == $product->get_type() ) {

                $product_id = $parent_id;
                $variation_id = $product->get_id();
            }

            $pipeline = Pricely_Pipeline::get_instance();

            return $pipeline->get_product_cache( $product_id, $variation_id, $this->context );
        }

        private function get_product_data( $product, $variation ) {

            $pipeline = Pricely_Pipeline::get_instance();

            $this->init_pipeline_data( $pipeline );

            return $pipeline->get_product_data( $product, $variation, $this->context );
        }

        private function get_data() {

            $pipeline = Pricely_Pipeline::get_instance();

            $cache_data = $pipeline->get_cache( $this->context );

            if ( isset( $cache_data[ $this->calculated_prices_key ] ) ) {

                return $cache_data[ $this->calculated_prices_key ];
            }

            if ( $this->is_cache_valid() ) {

                return false;
            }

            $data = $this->init_pipeline_data( $pipeline );

            if ( isset( $data[ $this->calculated_prices_key ] ) ) {

                return $data[ $this->calculated_prices_key ];
            }

            return false;
        }

        private function init_pipeline_data( $pipeline ) {

            return $pipeline->get_data( $this->context );
        }

        private function is_cache_valid() {

            return Pricely_Cache::get_instance()->is_valid_data();
        }

        private function can_use_cart_prices() {

            if ( Pricely_Pipeline_Cart::get_instance()->is_calculating() ) {

                return true;
            }

            $use_cart_prices = false;

            if ( $this->is_cart_or_checkout() ) {

                $use_cart_prices = true;
            }

            return apply_filters( 'pricely_get-pipeline-use-cart-prices', $use_cart_prices );
        }

        private function is_cart_or_checkout() {

            if ( $this->get_is_cart() ) {

                return true;
            }

            if ( $this->get_is_mini_cart() ) {

                return true;
            }

            if ( $this->get_is_checkout() ) {

                return true;
            }

            return false;
        }

        private function get_is_cart() {

            if ( defined( 'WOOCOMMERCE_CART' ) ) {

                return true;
            }

            if ( !is_null( $this->is_cart ) ) {

                return $this->is_cart;
            }

            $this->is_cart = is_cart();

            return $this->is_cart;
        }

        private function get_is_mini_cart() {

            return Pricely_Pipeline_View_Mini_Cart::get_instance()->is_mini_cart();
        }

        private function get_is_checkout() {

            if ( defined( 'WOOCOMMERCE_CHECKOUT' ) ) {

                return true;
            }

            if ( !is_null( $this->is_checkout ) ) {

                return $this->is_checkout;
            }

            $this->is_checkout = is_checkout();

            return $this->is_checkout;
        }

        private function set_shop_price( $price, $product, $variation ) {

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

                $this->product_util = Pricely_Product::get_instance();
            }

            $product_id = $product->get_id();
            $variation_id = 0;

            $parent_id = $product->get_parent_id();

            if ( $parent_id > 0 ) {

                $product_id = $parent_id;
                $variation_id = $product->get_id();
            }

            if ( !is_null( $variation ) ) {

                $variation_id = $variation->get_id();
            }

            $item_key = $this->product_util->get_product_key( $product_id, $variation_id );

            self::$shop_prices[ $item_key ] = $price;
        }

        private function set_any_price( $price, $product, $variation ) {

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

                $this->product_util = Pricely_Product::get_instance();
            }

            $product_id = $product->get_id();
            $variation_id = 0;

            $parent_id = $product->get_parent_id();

            if ( $parent_id > 0 ) {

                $product_id = $parent_id;
                $variation_id = $product->get_id();
            }

            if ( !is_null( $variation ) ) {

                $variation_id = $variation->get_id();
            }

            $item_key = $this->product_util->get_product_key( $product_id, $variation_id );

            self::$any_prices[ $item_key ] = $price;
        }

    }

    Pricely_Pipeline_Cart_Prices::get_instance();
}
