<?php

if ( !defined( 'ABSPATH' ) ) {

    exit;
}

if ( !class_exists( 'Pricely_Pipeline_Coupons_Auto_Add' ) ) {

    class Pricely_Pipeline_Coupons_Auto_Add {

        private static $instance;
        private $cart;
        private $is_internal_process;
        private $cart_discount_coupon_prefix;

        public static function get_instance(): self {

            if ( !self::$instance ) {

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

            return self::$instance;
        }

        public function __construct() {

            $this->is_internal_process = false;
            $this->cart_discount_coupon_prefix = 'pricely-d';

            add_filter( 'woocommerce_coupon_message', array( $this, 'get_coupon_error_message' ), 10, 3 );
            add_filter( 'woocommerce_coupon_error', array( $this, 'get_coupon_error' ), 10, 3 );
        }

        public function process_coupons_auto_add( $cart ) {

            $this->cart = $cart;

            $this->is_internal_process = false;

            $this->apply_coupons();

            $this->remove_coupons();
        }

        public function get_coupon_error_message( $msg, $msg_code, $coupon ) {

            if ( !$this->is_internal_process ) {

                return $msg;
            }

            $error_codes = array( 200, 201 );

            if ( in_array( $msg_code, $error_codes ) ) {

                // prevent defualt coupon message 
                return '';
            }

            return $msg;
        }

        public function get_coupon_error( $msg, $msg_code, $coupon ) {

            if ( $this->is_internal_process ) {

                return $msg;
            }

            if ( !method_exists( $coupon, 'get_code' ) ) {

                return $msg;
            }

            $coupon_code = $coupon->get_code();

            $error_codes = array( 105, 101 );

            if ( in_array( $msg_code, $error_codes ) && $this->is_dynamic_coupon_code( $coupon_code ) ) {

                // prevent defualt coupon message 
                return '';
            }

            $coupon_codes = $this->get_internal_coupon_codes();

            if ( !in_array( $coupon_code, $coupon_codes ) ) {

                return $msg;
            }

            if ( in_array( $msg_code, $error_codes ) ) {

                // prevent defualt coupon message 
                return '';
            }

            return $msg;
        }

        private function apply_coupons() {

            $applied_coupon_codes = $this->get_applied_coupon_codes();

            $coupon_codes_to_apply = array();

            foreach ( $this->get_coupon_codes() as $coupon_code ) {

                if ( in_array( $coupon_code, $applied_coupon_codes ) ) {

                    continue;
                }

                if ( in_array( $coupon_code, $coupon_codes_to_apply ) ) {

                    continue;
                }

                $coupon_codes_to_apply[] = $coupon_code;
            }

            if ( !count( $coupon_codes_to_apply ) ) {

                return;
            }

            foreach ( $coupon_codes_to_apply as $coupon_code ) {

                $this->apply_coupon_code( $coupon_code );
            }
        }

        private function remove_coupons() {

            $coupon_codes = $this->get_coupon_codes();

            $unknown_coupon_codes = array();

            foreach ( $this->get_applied_coupon_codes() as $applied_coupon_code ) {

                if ( in_array( $applied_coupon_code, $coupon_codes ) ) {

                    continue;
                }

                $unknown_coupon_codes[] = $applied_coupon_code;
            }

            if ( !count( $unknown_coupon_codes ) ) {

                return;
            }

            $internal_coupon_codes = $this->get_internal_coupon_codes();

            $coupon_codes_to_rempve = array();

            foreach ( $unknown_coupon_codes as $unknown_coupon_code ) {

                if ( !in_array( $unknown_coupon_code, $internal_coupon_codes ) ) {

                    continue;
                }

                $coupon_codes_to_rempve[] = $unknown_coupon_code;
            }

            if ( !count( $coupon_codes_to_rempve ) ) {

                return;
            }

            foreach ( $coupon_codes_to_rempve as $coupon_code ) {

                $this->remove_coupon_code( $coupon_code );
            }
        }

        private function apply_coupon_code( $coupon_code ) {

            $this->is_internal_process = true;

            $this->cart->apply_coupon( $coupon_code );
        }

        private function remove_coupon_code( $coupon_code ) {

            $this->is_internal_process = true;

            $this->cart->remove_coupon( $coupon_code );
        }

        private function get_coupon_codes() {

            $coupons = Pricely_Pipeline_Coupons::get_instance()->get_coupons();

            if ( !$coupons ) {

                return array();
            }

            $coupon_codes = array();

            foreach ( $coupons as $coupon_code => $coupons ) {

                $coupon_codes[] = $coupon_code;
            }

            if ( !count( $coupon_codes ) ) {

                return false;
            }

            return $coupon_codes;
        }

        private function get_applied_coupon_codes() {

            $coupons = $this->cart->get_applied_coupons();

            if ( !is_array( $coupons ) ) {

                return array();
            }

            return $coupons;
        }

        private function get_internal_coupon_codes() {

            return Pricely_Pipeline_Coupons_Internal::get_instance()->get_coupon_codes();
        }

        private function is_dynamic_coupon_code( $coupon_code ) {

            if ( (strpos( strtolower( $coupon_code ), strtolower( $this->cart_discount_coupon_prefix ) ) === 0 ) ) {

                return true;
            }

            return false;
        }

    }

}
