<?php

if ( !defined( 'ABSPATH' ) ) {

    exit;
}

if ( !class_exists( 'Pricely_Pipeline_Prices' ) ) {

    class Pricely_Pipeline_Prices {

        private static $instance;
        private $adjusted_prices_key;
        private $context;
        private $currency;

        public static function get_instance(): self {

            if ( !self::$instance ) {

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

            return self::$instance;
        }

        public function __construct() {

            $this->adjusted_prices_key = 'adjusted_prices';
            $this->context = 'shop_prices';

            add_filter( 'woocommerce_product_get_sale_price', array( $this, 'get_sale_price' ), 99999, 2 );
            add_filter( 'woocommerce_product_variation_get_sale_price', array( $this, 'get_sale_price' ), 99999, 2 );

            add_filter( 'woocommerce_product_get_price', array( $this, 'get_price' ), 99999, 2 );
            add_filter( 'woocommerce_product_variation_get_price', array( $this, 'get_price' ), 99999, 2 );
        }

        public function get_sale_price( $price, $product ) {

            if ( $this->is_pre_processing_items() ) {

                return $price;
            }

            $adjusted_sale_price = $this->get_adjusted_sale_price( $product );

            if ( false !== $adjusted_sale_price ) {

                return apply_filters( 'pricely_get-pipeline-sale-price', $this->convert_amount( $adjusted_sale_price, 'pipeline-sale-price' ), $product );
            }

            return $price;
        }

        public function get_price( $price, $product ) {

            if ( $this->is_pre_processing_items() ) {

                return $price;
            }

            $adjusted_sale_price = $this->get_adjusted_sale_price( $product );

            if ( false === $adjusted_sale_price ) {

                $calculated_price = $this->get_calculated_price( $price, $product );
            } else {

                $adjusted_price = apply_filters( 'pricely_get-pipeline-price', $this->convert_amount( $adjusted_sale_price, 'pipeline-price' ), $product );

                $calculated_price = $this->get_calculated_price( $adjusted_price, $product );
            }

            if ( false !== $calculated_price ) {

                return apply_filters( 'pricely_get-pipeline-price', $this->convert_amount( $calculated_price, 'pipeline-price' ), $product );
            }

            if ( false !== $adjusted_sale_price ) {

                return apply_filters( 'pricely_get-pipeline-price', $this->convert_amount( $adjusted_sale_price, 'pipeline-price' ), $product );
            }

            return $price;
        }

        private function get_calculated_price( $price, $product ) {

            return Pricely_Pipeline_Cart_Prices::get_instance()->get_price( $price, $product );
        }

        private function get_adjusted_sale_price( $product ) {

            $adjusted_prices = $this->get_adjusted_prices( $product );

            if ( $adjusted_prices && isset( $adjusted_prices[ 'sale_price' ] ) ) {

                return $adjusted_prices[ 'sale_price' ];
            }

            return false;
        }

        private function get_adjusted_prices( $product ) {

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

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

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

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

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

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

            return false;
        }

        private function get_product_cache( $product ) {

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

            $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 ) {

            $pipeline = Pricely_Pipeline::get_instance();

            $this->init_pipeline_data( $pipeline );

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

        private function init_pipeline_data( $pipeline ) {

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

        private function is_pre_processing_items() {

            return Pricely_Pipeline_Cart::get_instance()->is_pre_processing_items();
        }

        private 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 );
        }

    }

    Pricely_Pipeline_Prices::get_instance();
}

