<?php

if ( !defined( 'ABSPATH' ) ) {

    exit;
}

if ( !class_exists( 'Pricely_Pipeline_Coupons_Discounts' ) ) {

    class Pricely_Pipeline_Coupons_Discounts {

        private static $instance;
        private $cart_discounts_coupons_util;
        private $currency;

        public static function get_instance(): self {

            if ( !self::$instance ) {

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

            return self::$instance;
        }

        public function get_item_data( $cart_item ) {

            if ( is_array( $cart_item ) ) {

                return array(
                    'key' => $this->get_item_key( $cart_item[ 'product_id' ], $cart_item[ 'variation_id' ] ),
                    'cart_key' => $cart_item[ 'key' ],
                    'product_id' => $cart_item[ 'product_id' ],
                    'variation_id' => $cart_item[ 'variation_id' ],
                    'quantity' => $cart_item[ 'quantity' ]
                );
            }

            if ( !is_null( $cart_item ) && is_array( $cart_item->object ) ) {

                return array(
                    'key' => $this->get_item_key( $cart_item->object[ 'product_id' ], $cart_item->object[ 'variation_id' ] ),
                    'cart_key' => $cart_item->object[ 'key' ],
                    'product_id' => $cart_item->object[ 'product_id' ],
                    'variation_id' => $cart_item->object[ 'variation_id' ],
                    'quantity' => $cart_item->object[ 'quantity' ]
                );
            }

            if ( !is_null( $cart_item ) ) {

                return array(
                    'key' => $this->get_item_key( $cart_item->product_id, $cart_item->variation_id ),
                    'cart_key' => $cart_item->key,
                    'product_id' => $cart_item->product_id,
                    'variation_id' => $cart_item->variation_id,
                    'quantity' => $cart_item->quantity
                );
            }

            return false;
        }

        public function get_discount_data( $coupon_code, $has_external_id, $prev_totals ) {

            $discount_data = $this->get_cart_discount_data( $coupon_code, $prev_totals, $has_external_id );

            if ( false == $discount_data ) {

                return $discount_data;
            }

            $discount_data[ 'product_ids' ] = $this->process_coupon_product_ids( $discount_data );

            return $discount_data;
        }

        private function get_cart_discount_data( $coupon_code, $prev_totals, $has_external_id ) {

            //get cart discount data
            $data = Pricely_Pipeline_Cart_Discounts::get_instance()->get_data();

            if ( !$data ) {

                return false;
            }

            $coupon = false;

            foreach ( $data[ 'coupons' ] as $data_coupon ) {

                if ( $coupon_code == $data_coupon[ 'coupon_code' ] ) {

                    $coupon = $data_coupon;

                    break;
                }
            }

            if ( !$coupon ) {

                return false;
            }

            if ( !isset( $data[ 'discounts' ] ) ) {

                return false;
            }
            
            //convert cart discounts current currency
            $data[ 'discounts' ] = $this->convert_cart_discounts( $data[ 'discounts' ] );

            //get calculated coupon discounts
            $discount_data = $this->get_cart_dicounts_coupon_discounts( $this->get_default_discount_data(), $coupon[ 'id' ], $coupon_code, $data[ 'discounts' ], $prev_totals );

            //set other coupon data
            $discount_data[ 'coupon_code' ] = $coupon_code;
            $discount_data[ 'individual_use' ] = $coupon[ 'individual_use' ];

            //set coupon id
            if ( !$has_external_id && false === $discount_data[ 'coupon_id' ] ) {

                $discount_data[ 'coupon_id' ] = $coupon[ 'id' ];
            }

            return $discount_data;
        }

        private function process_coupon_product_ids( $discount_data ) {

            $product_ids = array();

            if ( !isset( $discount_data[ 'totals' ] ) ) {

                return $product_ids;
            }

            $item_keys = array_keys( $discount_data[ 'totals' ] );

            foreach ( $item_keys as $item_key ) {

                $item_id_data = $this->get_item_id_data( $item_key );

                if ( !$item_id_data ) {

                    continue;
                }

                $item_id = $item_id_data[ 'product_id' ];

                if ( $item_id_data[ 'variation_id' ] > 0 ) {

                    $item_id = $item_id_data[ 'variation_id' ];
                }

                if ( !is_numeric( $item_id ) ) {

                    continue;
                }

                if ( in_array( $item_id, $product_ids ) ) {

                    continue;
                }

                $product_ids[] = ( int ) $item_id;
            }

            return $product_ids;
        }

        private function get_cart_dicounts_coupon_discounts( $discount_data, $coupon_id, $coupon_code, $discounts, $prev_totals ) {

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

                $this->cart_discounts_coupons_util = new Pricely_Cart_Discounts_Coupons_Util();
            }

            return $this->cart_discounts_coupons_util->get_coupon_discounts( $discount_data, $coupon_id, $coupon_code, $discounts, $prev_totals );
        }

        private function get_item_key( $product_id, $variation_id ) {

            return Pricely_Product::get_instance()->get_product_key( $product_id, $variation_id );
        }

        private function get_item_id_data( $item_key ) {

            return Pricely_Product::get_instance()->get_product_id_data_by_key( $item_key );
        }
        
        private function convert_cart_discounts( $discounts ) {

            if ( !$discounts ) {

                return $discounts;
            }

            foreach ( $discounts as $key => $discount ) {

                if ( !isset( $discount[ 'discount_id' ] ) ) {

                    continue;
                }

                if ( !isset( $discount[ 'totals' ] ) ) {

                    continue;
                }

                $convert_id = 'pipeline-coupon-cart-discount-';
                $discount_id = $discount[ 'discount_id' ];

                $discounts[ $key ][ 'totals' ] = $this->convert_amounts( $discount[ 'totals' ], $convert_id . 'totals-' . $discount_id );
                $discounts[ $key ][ 'total' ] = $this->convert_amount( $discount[ 'total' ], $convert_id . 'total-' . $discount_id );
                $discounts[ $key ][ 'taxes' ] = $this->convert_amounts( $discount[ 'taxes' ], $convert_id . 'taxes-' . $discount_id );
                $discounts[ $key ][ 'total_tax' ] = $this->convert_amount( $discount[ 'total_tax' ], $convert_id . 'total_tax-' . $discount_id );
            }

            return $discounts;
        }
        
        private function convert_amounts( $amounts, $amount_id ) {

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

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

            return $this->currency->convert_amounts( $amounts, $amount_id );
        }

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

        private function get_default_discount_data() {

            return array(
                'coupon_id' => false,
                'coupon_code' => '',
                'cart_prices' => array(),
                'cart_discounts' => array(),
                'totals' => array(),
                'total' => 0,
                'product_ids' => array(),
                'date_expires' => null,
                'individual_use' => false
            );
        }

    }

}

