<?php

namespace WeDevs\DokanPro\Coupons;

use WP_Error;
use Exception;

/**
* Hooks Class
*
* Loaded all hooks releated with coupon
*
* @since 3.0.0
*/
class Hooks {

    /**
     * Validated coupon form error
     *
     * @var WP_Error Object
     */
    public static $validated;

    /**
     * Load autometically when class initiate
     *
     * @since 3.0.0
     */
    public function __construct() {
        add_action( 'dokan_load_custom_template', array( $this, 'load_coupon_template' ) );
        add_action( 'dokan_coupon_content_area_header', array( $this, 'render_coupon_header_template' ), 10 );
        add_action( 'dokan_coupon_content', array( $this, 'render_coupon_content_template' ), 10 );
        add_action( 'template_redirect', array( $this, 'handle_coupons' ) );

        add_filter( 'dokan_get_dashboard_nav', array( $this, 'add_coupon_menu' ) );
        add_filter( 'woocommerce_coupon_validate_minimum_amount', array( $this, 'validate_coupon_minimum_amount' ), 10, 2 );
    }

    /**
     * Add Coupon menu
     *
     * @param array $urls
     *
     * @since 2.4
     *
     * @return array $urls
     */
    public function add_coupon_menu( $urls ) {
        $urls['coupons'] = array(
            'title'      => __( 'Coupons', 'dokan' ),
            'icon'       => '<i class="fa fa-gift"></i>',
            'url'        => dokan_get_navigation_url( 'coupons' ),
            'pos'        => 55,
            'permission' => 'dokan_view_coupon_menu',
        );

        return $urls;
    }

    /**
     * Ensure coupon amount is valid or throw exception.
     *
     * @since 2.9.10
     *
     * @param bool $invalid
     * @param WC_Coupon $coupon
     * @param float $total
     *
     * @return bool
     */
    public function validate_coupon_minimum_amount( $valid, $coupon ) {
        if ( ! apply_filters( 'dokan_ensure_vendor_coupon', true ) ) {
            return $valid;
        }

        $line_item_total               = 0;
        $coupon_applicable_product_ids = $coupon->get_product_ids();

        foreach ( WC()->cart->get_cart() as $item ) {
            $product_id = $item['data']->get_id();

            if ( in_array( $product_id, $coupon_applicable_product_ids, true ) || in_array( $item['product_id'], $coupon_applicable_product_ids, true ) ) {
                $line_sub_total  = ! empty( $item['line_subtotal'] ) ? $item['line_subtotal'] : 0;
                $line_item_total += $line_sub_total;
            }
        }

        if ( $coupon->get_minimum_amount() > $line_item_total ) {
            // return validation message when coupon amount greater than total amount
            // translators: %s : showing minimun amount for coupon
            throw new Exception( sprintf( __( 'The minimun spend for this coupon is %s', 'dokan' ), wc_price( $coupon->get_minimum_amount() ) ), 108 );
        }

        return $valid;
    }

    /**
     * Render Coupon Header template
     *
     * @since 2.4
     *
     * @return void
     */
    public function render_coupon_header_template() {
        $is_edit      = ( isset( $_GET['view'] ) && 'add_coupons' === $_GET['view'] ) ? true : false; // phpcs:ignore
        $is_edit_page = ( ! empty( $_GET['post'] ) && $is_edit ) ? true : false; // phpcs:ignore
        dokan_get_template_part(
            'coupon/header', '', array(
                'pro' => true,
                'is_edit_page' => $is_edit_page,
                'is_edit' => $is_edit,
            )
        );
    }

    /**
     * Render Coupon Content
     *
     * @since 2.4
     *
     * @return void
     */
    public function render_coupon_content_template() {
        if ( ! dokan_is_seller_enabled( get_current_user_id() ) ) {
            echo dokan_seller_not_enabled_notice();
        } else {
            $this->list_user_coupons();

            if ( is_wp_error( self::$validated ) ) {
                $messages = self::$validated->get_error_messages();

                foreach ( $messages as $message ) {
                    dokan_get_template_part(
                        'global/dokan-error', '',
                        [
                            'deleted' => true,
                            'message' => $message,
                        ]
                    );
                }
            }

            $this->add_coupons_form( self::$validated );
        }
    }

    /**
     * Load Coupon template
     *
     * @since 2.4
     *
     * @param  array $query_vars
     *
     * @return void [require once template]
     */
    public function load_coupon_template( $query_vars ) {
        if ( isset( $query_vars['coupons'] ) ) {
            dokan_get_template_part( 'coupon/coupons', '', array( 'pro' => true ) );
            return;
        }
    }

    /**
     * Render listing of coupon
     *
     * @since 2.4
     *
     * @return void
     */
    public function list_user_coupons() {
        //click add coupon then hide this function
        if ( isset( $_GET['view'] ) && 'add_coupons' === $_GET['view'] ) { // phpcs:ignore
            return;
        }

        if ( isset( $_GET['post'] ) && 'edit' === $_GET['action'] ) { // phpcs:ignore
            return;
        }

        $pagenum = isset( $_GET['pagenum'] ) ? absint( $_GET['pagenum'] ) : 1; // phpcs:ignore
        $all_coupons  = dokan_pro()->coupon->all( [ 'paged' => $pagenum ] );

        if ( ! empty( $all_coupons->coupons ) ) {
            $this->get_messages();
            dokan_get_template_part(
                'coupon/listing', '',
                [
                    'pro' => true,
                    'coupons' => $all_coupons,
                ]
            );
        } else {
            dokan_get_template_part(
                'coupon/no-coupon', '',
                [
                    'pro' => true,
                    'message' => __( 'No coupons found!', 'dokan' ),
                ]
            );
        }
    }

    /**
     * Render coupon Message
     *
     * @return void
     */
    public function get_messages() {
        if ( isset( $_GET['message'] ) && 'delete_succefully' === $_GET['message'] ) { // phpcs:ignore
            dokan_get_template_part( 'global/dokan-message', '', array( 'message' => __( 'Coupon has been deleted successfully!', 'dokan' ) ) );
        }

        if ( isset( $_GET['message'] ) && 'coupon_saved' === $_GET['message'] ) { // phpcs:ignore
            dokan_get_template_part( 'global/dokan-message', '', array( 'message' => __( 'Coupon has been saved successfully!', 'dokan' ) ) );
        }

        if ( isset( $_GET['message'] ) && 'coupon_update' === $_GET['message'] ) { // phpcs:ignore
            dokan_get_template_part( 'global/dokan-message', '', array( 'message' => __( 'Coupon has been updated successfully!', 'dokan' ) ) );
        }
    }

        /**
     * Render Add Coupon Form
     *
     * @param object $validated
     *
     * @return void
     */
    public function add_coupons_form( $validated ) {
        $get_data  = wp_unslash( $_GET ); // phpcs:ignore
        $post_data = wp_unslash( $_POST ); // phpcs:ignore

        //intial time hide this function
        if ( ! isset( $get_data['view'] ) ) {
            return;
        } elseif ( 'add_coupons' !== $get_data['view'] ) {
            return;
        }

        $button_name = __( 'Create Coupon', 'dokan' );

        if ( isset( $get_data['post'] ) && 'edit' === $get_data['action'] ) {
            $post                       = get_post( $get_data['post'] );
            $button_name                = __( 'Update Coupon', 'dokan' );
            $discount_type              = get_post_meta( $post->ID, 'discount_type', true );
            $amount                     = get_post_meta( $post->ID, 'coupon_amount', true );
            $products                   = get_post_meta( $post->ID, 'product_ids', true );
            $exclude_products           = get_post_meta( $post->ID, 'exclude_product_ids', true );
            $product_categories         = get_post_meta( $post->ID, 'product_categories', true );
            $exclude_product_categories = get_post_meta( $post->ID, 'exclude_product_categories', true );
            $usage_limit                = get_post_meta( $post->ID, 'usage_limit', true );
            $expire                     = get_post_meta( $post->ID, 'date_expires', true );
            $apply_before_tax           = get_post_meta( $post->ID, 'apply_before_tax', true );
            $exclide_sale_item          = get_post_meta( $post->ID, 'exclude_sale_items', true );
            $minimum_amount             = get_post_meta( $post->ID, 'minimum_amount', true );
            $customer_email             = get_post_meta( $post->ID, 'customer_email', true );
            $show_on_store              = get_post_meta( $post->ID, 'show_on_store', true );
        }

        $post_id     = isset( $post->ID ) ? $post->ID : '';
        $post_title  = isset( $post->post_title ) ? $post->post_title : '';
        $description = isset( $post->post_content ) ? $post->post_content : '';

        if ( ! empty( $post_id ) && ! dokan_is_valid_owner( $post_id, dokan_get_current_user_id() ) ) {
            wp_safe_redirect( dokan_get_navigation_url( 'coupons' ) );
            exit();
        }

        $discount_type              = isset( $discount_type ) ? $discount_type : '';
        $amount                     = isset( $amount ) ? $amount : '';
        $products                   = isset( $products ) ? $products : '';
        $exclude_products           = isset( $exclude_products ) ? $exclude_products : '';
        $product_categories         = ! empty( $product_categories ) ? $product_categories : array();
        $exclude_product_categories = ! empty( $exclude_product_categories ) ? $exclude_product_categories : array();

        $usage_limit = isset( $usage_limit ) ? $usage_limit : '';

        if ( isset( $expire ) && ( (string) (int) $expire === $expire )
            && ( $expire <= PHP_INT_MAX )
            && ( $expire >= ~PHP_INT_MAX ) ) {
            $expire = date( 'Y-m-d', $expire ); // phpcs:ignore
        } else {
            $expire = ! empty( $expire ) ? date( 'Y-m-d', strtotime( $expire ) ) : ''; // phpcs:ignore
        }

        $products_id = str_replace( ' ', '', $products );
        $products_id = explode( ',', $products_id );

        if ( isset( $apply_before_tax ) && 'yes' === $apply_before_tax ) {
            $apply_before_tax = 'checked';
        } else {
            $apply_before_tax = '';
        }

        if ( isset( $exclide_sale_item ) && 'yes' === $exclide_sale_item ) {
            $exclide_sale_item = 'checked';
        } else {
            $exclide_sale_item = '';
        }

        if ( isset( $show_on_store ) && 'yes' === $show_on_store ) {
            $show_on_store = 'checked';
        } else {
            $show_on_store = '';
        }

        $minimum_amount = isset( $minimum_amount ) ? $minimum_amount : '';
        $customer_email = isset( $customer_email ) ? implode( ',', $customer_email ) : '';

        if ( is_wp_error( self::$validated ) ) {
            $post_id       = $post_data['post_id'];
            $post_title    = $post_data['title'];
            $description   = $post_data['description'];
            $discount_type = $post_data['discount_type'];
            $amount        = $post_data['amount'];

            if ( isset( $post_data['product_drop_down'] ) ) {
                $products = implode( ',', array_filter( array_map( 'intval', (array) $post_data['product_drop_down'] ) ) );
            } else {
                $products = '';
            }

            if ( isset( $post_data['exclude_product_ids'] ) ) {
                $exclude_products = implode( ',', array_filter( array_map( 'intval', (array) $post_data['exclude_product_ids'] ) ) );
            } else {
                $exclude_products = '';
            }

            if ( isset( $post_data['product_categories'] ) ) {
                $product_categories = implode( ',', array_filter( array_map( 'intval', (array) $post_data['product_categories'] ) ) );
            } else {
                $product_categories = '';
            }

            if ( isset( $post_data['exclude_product_categories'] ) ) {
                $exclude_product_categories = implode( ',', array_filter( array_map( 'intval', (array) $post_data['exclude_product_categories'] ) ) );
            } else {
                $exclude_product_categories = '';
            }

            $usage_limit = $post_data['usage_limit'];
            $expire      = $post_data['expire'];

            if ( isset( $post_data['apply_before_tax'] ) && 'yes' === $post_data['apply_before_tax'] ) {
                $apply_before_tax = 'checked';
            } else {
                $apply_before_tax = '';
            }

            if ( isset( $post_data['exclude_sale_items'] ) && 'yes' === $post_data['exclude_sale_items'] ) {
                $exclide_sale_item = 'checked';
            } else {
                $exclide_sale_item = '';
            }

            if ( isset( $post_data['show_on_store'] ) && 'yes' === $post_data['show_on_store'] ) {
                $show_on_store = 'checked';
            } else {
                $show_on_store = '';
            }

            $minimum_amount = $post_data['minium_ammount'];
            $customer_email = $post_data['email_restrictions'];
        }

        $exclude_products = str_replace( ' ', '', $exclude_products );
        $exclude_products = explode( ',', $exclude_products );

        if ( empty( $post_id ) && ! current_user_can( 'dokan_add_coupon' ) ) {
            dokan_get_template_part(
                'global/dokan-error', '',
                [
                    'deleted' => false,
                    'message' => __( 'You have no permission to add coupon', 'dokan' ),
                ]
            );
        } elseif ( ! empty( $post_id ) && ! current_user_can( 'dokan_edit_coupon' ) ) {
            dokan_get_template_part(
                'global/dokan-error', '',
                [
                    'deleted' => false,
                    'message' => __( 'You have no permission to edit this coupon', 'dokan' ),
                ]
            );
        } else {
            dokan_get_template_part(
                'coupon/form', '', array(
                    'pro'                        => true,
                    'post_id'                    => $post_id,
                    'post_title'                 => $post_title,
                    'discount_type'              => $discount_type,
                    'description'                => $description,
                    'amount'                     => strpos( $discount_type, 'percent' ) !== false ? wc_format_localized_decimal( $amount ) : wc_format_localized_price( $amount ),
                    'products'                   => $products,
                    'exclude_products'           => $exclude_products,
                    'product_categories'         => $product_categories,
                    'exclude_product_categories' => $exclude_product_categories,
                    'usage_limit'                => $usage_limit,
                    'expire'                     => $expire,
                    'minimum_amount'             => $minimum_amount,
                    'customer_email'             => $customer_email,
                    'button_name'                => $button_name,
                    'exclide_sale_item'          => $exclide_sale_item,
                    'show_on_store'              => $show_on_store,
                    'all_products'               => dokan_get_coupon_products_list(),
                    'products_id'                => $products_id,
                )
            );
        }
    }

    /**
     * Handle the coupons submission
     *
     * @return void
     */
    public function handle_coupons() {
        if ( ! is_user_logged_in() ) {
            return;
        }

        if ( ! dokan_is_user_seller( get_current_user_id() ) ) {
            return;
        }

        // Coupon functionality
        self::$validated = $this->validate();

        if ( ! is_wp_error( self::$validated ) ) {
            $this->coupons_create();
        }

        $this->coupun_delete();
    }

    /**
     * Validate Coupon handler form
     *
     * @since 2.4
     *
     * @return object WP_Error|error
     */
    public function validate() {
        $post_data = wp_unslash( $_POST ); // phpcs:ignore

        if ( ! isset( $post_data['coupon_creation'] ) ) {
            return;
        }

        if ( ! wp_verify_nonce( $post_data['coupon_nonce_field'], 'coupon_nonce' ) ) {
            wp_die( __( 'Are you cheating?', 'dokan' ) );
        }

        $errors = new WP_Error();

        // Checking permissions for adding and editing
        if ( empty( $post_data['post_id'] ) ) {
            if ( ! current_user_can( 'dokan_add_coupon' ) ) {
                $errors->add( 'title', __( 'You have no permission to add this coupon', 'dokan' ) );
            }
        } else {
            if ( ! current_user_can( 'dokan_edit_coupon' ) ) {
                $errors->add( 'title', __( 'You have no permission to edit this coupon', 'dokan' ) );
            }
        }

        if ( empty( $post_data['title'] ) ) {
            $errors->add( 'title', __( 'Please enter the coupon title', 'dokan' ) );
        }

        if ( empty( $post_data['amount'] ) ) {
            $errors->add( 'amount', __( 'Please enter the amount', 'dokan' ) );
        }

        if ( ! isset( $post_data['product_drop_down'] ) || ! count( $post_data['product_drop_down'] ) ) {
            $errors->add( 'products', __( 'Please specify any products', 'dokan' ) );
        }

        $this->is_coupon_exist( $post_data['title'], $errors );

        if ( $errors->get_error_codes() ) {
            return $errors;
        }

        return true;
    }

    /**
     * Coupon Delete Functionality
     *
     * @since 2.4
     *
     * @return void
     */
    public function coupun_delete() {
        $get_data = wp_unslash( $_GET ); // phpcs:ignore

        if ( ! isset( $get_data['post'] ) || ! isset( $get_data['action'] ) ) { // phpcs:ignore
            return;
        } elseif ( 'delete' !== $get_data['action'] ) { // phpcs:ignore
            return;
        }

        if ( ! current_user_can( 'dokan_delete_coupon' ) ) {
            wp_die( __( 'You have not permission to delete this coupon', 'dokan' ) );
        }

        if ( ! wp_verify_nonce( $get_data['coupon_del_nonce'], '_coupon_del_nonce' ) ) { // phpcs:ignore
            wp_die( __( 'Are you cheating?', 'dokan' ) );
        }

        dokan_pro()->coupon->delete( $get_data['post'], true ); // phpcs:ignore
        wp_safe_redirect( add_query_arg( array( 'message' => 'delete_succefully' ), dokan_get_navigation_url( 'coupons' ) ) );
    }

    /**
     * Create Coupon hanlder function
     *
     * @since 2.4
     *
     * @return void
     */
    public function coupons_create() {
        $post_data = wp_unslash( $_POST ); // phpcs:ignore

        if ( ! isset( $post_data['coupon_creation'] ) ) {
            return;
        }

        if ( ! wp_verify_nonce( $post_data['coupon_nonce_field'], 'coupon_nonce' ) ) {
            wp_die( __( 'Are you cheating?', 'dokan' ) );
        }

        if ( empty( $post_data['post_id'] ) ) {
            $post = array(
                'post_title'   => $post_data['title'],
                'post_content' => $post_data['description'],
                'post_status'  => 'publish',
                'post_type'    => 'shop_coupon',
                'post_author'  => dokan_get_current_user_id(),
            );

            $post_id = wp_insert_post( $post );
            $message = 'coupon_saved';
        } else {
            $post = array(
                'ID'           => $post_data['post_id'],
                'post_title'   => $post_data['title'],
                'post_content' => $post_data['description'],
                'post_status'  => 'publish',
                'post_type'    => 'shop_coupon',
                'post_author'  => dokan_get_current_user_id(),
            );
            $post_id = wp_update_post( $post );
            $message = 'coupon_update';
        }

        if ( ! $post_id ) {
            return;
        }

        $customer_email     = array_filter( array_map( 'trim', explode( ',', sanitize_text_field( $post_data['email_restrictions'] ) ) ) );
        $type               = sanitize_text_field( $post_data['discount_type'] );
        $amount             = wc_format_decimal( sanitize_text_field( $post_data['amount'] ) );
        $usage_limit        = empty( $post_data['usage_limit'] ) ? '' : absint( $post_data['usage_limit'] );
        $expiry_date        = strtotime( sanitize_text_field( $post_data['expire'] ) );
        $apply_before_tax   = isset( $post_data['apply_before_tax'] ) ? 'yes' : 'no';
        $exclude_sale_items = isset( $post_data['exclude_sale_items'] ) ? 'yes' : 'no';
        $show_on_store      = isset( $post_data['show_on_store'] ) ? 'yes' : 'no';
        $minimum_amount     = wc_format_decimal( sanitize_text_field( $post_data['minium_ammount'] ) );

        if ( isset( $post_data['product_drop_down'][0] ) && 'select_all' === $post_data['product_drop_down'][0] ) {
            $product_ids = array_map(
                function( $product ) {
                    return intval( $product->ID );
                }, dokan_get_coupon_products_list()
            );

            $product_ids = implode( ',', $product_ids );
        } elseif ( isset( $post_data['product_drop_down'] ) ) {
            $product_ids = implode( ',', array_filter( array_map( 'intval', (array) $post_data['product_drop_down'] ) ) );
        } else {
            $product_ids = '';
        }

        if ( isset( $post_data['exclude_product_ids'] ) ) {
            $exclude_product_ids = implode( ',', array_filter( array_map( 'intval', (array) $post_data['exclude_product_ids'] ) ) );
        } else {
            $exclude_product_ids = '';
        }

        if ( isset( $post_data['product_categories'] ) ) {
            $product_categories = array_filter( array_map( 'intval', (array) $post_data['product_categories'] ) );
        } else {
            $product_categories = array();
        }

        if ( isset( $post_data['exclude_product_categories'] ) ) {
            $exclude_product_categories = array_filter( array_map( 'intval', (array) $post_data['exclude_product_categories'] ) );
        } else {
            $exclude_product_categories = array();
        }

        update_post_meta( $post_id, 'discount_type', $type );
        update_post_meta( $post_id, 'coupon_amount', $amount );
        update_post_meta( $post_id, 'product_ids', $product_ids );
        update_post_meta( $post_id, 'exclude_product_ids', $exclude_product_ids );
        update_post_meta( $post_id, 'product_categories', $product_categories );
        update_post_meta( $post_id, 'exclude_product_categories', $exclude_product_categories );
        update_post_meta( $post_id, 'usage_limit', $usage_limit );
        update_post_meta( $post_id, 'date_expires', $expiry_date );
        update_post_meta( $post_id, 'apply_before_tax', $apply_before_tax );
        update_post_meta( $post_id, 'free_shipping', 'no' );
        update_post_meta( $post_id, 'exclude_sale_items', $exclude_sale_items );
        update_post_meta( $post_id, 'show_on_store', $show_on_store );
        update_post_meta( $post_id, 'minimum_amount', $minimum_amount );
        update_post_meta( $post_id, 'customer_email', $customer_email );

        do_action( 'dokan_after_coupon_create', $post_id );

        if ( ! defined( 'DOING_AJAX' ) ) {
            wp_safe_redirect( add_query_arg( array( 'message' => $message ), dokan_get_navigation_url( 'coupons' ) ) );
        }
    }

    /**
    * Get the orders total from a specific seller
    *
    * @since version 3
    *
    * @param string $title
    * @param object $error
    *
    * @return object $error
    */
    public function is_coupon_exist( $title, $errors ) {
        $post_data = wp_unslash( $_POST ); // phpcs:ignore

        $args = array(
            'post_type' => 'shop_coupon',
            'name' => $title,
		);
        $query = get_posts( $args );

        if ( $title ) {
            if ( ! empty( $query ) ) {
                if ( empty( $post_data['post_id'] ) || (int) $post_data['post_id'] !== $query[0]->ID ) {
                    return $errors->add( 'duplicate', __( 'Coupon title already exists', 'dokan' ) );
                }
            }
        }
    }

}
