<?php

defined( 'ABSPATH' ) or exit;

final class PWLPAR_Hooks {

    function __construct() {
        add_action( 'woocommerce_init', array( $this, 'woocommerce_init' ) );
    }

    function woocommerce_init() {
        if ( !pwlpar_is_active_or_admin() ) {
            return;
        }

        add_action( 'woocommerce_login_form_end', array( $this, 'redirect_to_field' ) );
        add_action( 'woocommerce_register_form_end', array( $this, 'redirect_to_field' ) );

        add_filter( 'woocommerce_get_shop_coupon_data', array( $this, 'woocommerce_get_shop_coupon_data' ), 10, 2 );
        add_filter( 'woocommerce_cart_totals_coupon_label', array( $this, 'woocommerce_cart_totals_coupon_label' ), 10, 2 );

        if ( get_option( 'pwlpar_show_points_on_product_page', 'yes' ) == 'yes' ) {
            add_action( 'woocommerce_single_product_summary', array( $this, 'show_points_on_product' ), 35 );
        }

        add_action( 'woocommerce_proceed_to_checkout', array( $this, 'woocommerce_proceed_to_checkout' ), apply_filters( 'pwlpar_proceed_to_checkout_priority', 15 ) );
        add_action( 'woocommerce_review_order_after_order_total', array( $this, 'woocommerce_review_order_after_order_total' ) );
        add_action( 'woocommerce_after_checkout_billing_form', array( $this, 'woocommerce_after_checkout_billing_form' ), apply_filters( 'pwlpar_checkout_signup_priority', 15 ) );
        add_filter( 'woocommerce_create_account_default_checked', '__return_true' );
        add_action( 'woocommerce_after_order_details', array( $this, 'woocommerce_after_order_details' ) );

        add_action( 'woocommerce_checkout_posted_data', array( $this, 'woocommerce_checkout_posted_data' ) );
        add_action( 'woocommerce_checkout_update_user_meta', array( $this, 'woocommerce_checkout_update_user_meta' ), 10, 2 );

        add_action( 'woocommerce_new_order', array( $this, 'woocommerce_new_order' ), 10, 2 );
        add_action( 'woocommerce_order_status_pending', array( $this, 'handle_order_status_change' ), 10, 3 );
        add_action( 'woocommerce_order_status_processing', array( $this, 'handle_order_status_change' ), 10, 3 );
        add_action( 'woocommerce_order_status_on-hold', array( $this, 'handle_order_status_change' ), 10, 3 );
        add_action( 'woocommerce_order_status_completed', array( $this, 'handle_order_status_change' ), 10, 3 );
        add_action( 'woocommerce_order_status_cancelled', array( $this, 'handle_order_status_change' ), 10, 3 );
        add_action( 'woocommerce_order_status_refunded', array( $this, 'handle_order_status_change' ), 10, 3 );
        add_action( 'woocommerce_order_status_failed', array( $this, 'handle_order_status_change' ), 10, 3 );
        add_action( 'woocommerce_order_status_preordered', array( $this, 'handle_order_status_change' ), 10, 3 );

        add_action( 'delete_post', array( $this, 'order_deleted' ) );
        add_action( 'untrash_post', array( $this, 'order_restored' ) );

        add_action( 'deleted_user', array( $this, 'deleted_user' ), 10, 2 );

        add_action( 'wp_ajax_pwlpar-claim_offer', array( $this, 'ajax_claim_offer' ) );
        add_action( 'wp_ajax_nopriv_pwlpar-claim_offer', array( $this, 'ajax_claim_offer' ) );
    }

    /**
     * Adds a redirect field to the login form so we can redirect users after login or new account registration.
     */
    function redirect_to_field() {
        // Nonce is not required here because the 'pwlpar_redirect' value is not used to perform any actions.
        // phpcs:disable WordPress.Security.NonceVerification.Recommended
        if ( isset( $_GET['pwlpar_redirect'] ) && !empty( $_GET['pwlpar_redirect'] ) ) {
            echo '<input type="hidden" name="redirect" value="' . esc_attr( esc_url_raw( wp_unslash( $_GET['pwlpar_redirect'] ) ) ) . '" />';
        }
        // phpcs:enable
    }

    function woocommerce_get_shop_coupon_data( $data, $coupon_code ) {

        if ( ( is_admin() && !wp_doing_ajax() ) || empty( $coupon_code ) || empty( WC()->cart ) ) {
            return $data;
        }

        $reward = pwlpar_get_reward_by_coupon_code( $coupon_code );
        if ( $reward ) {
            return $reward->shop_coupon_data();
        }

        return $data;
    }

    function woocommerce_cart_totals_coupon_label( $label, $coupon ) {
        $reward = pwlpar_get_reward_by_coupon_code( $coupon->get_code() );
        if ( $reward ) {
            $label = $reward->get_offer_title();
        }

        return $label;
    }

    function show_points_on_product() {
        global $product;

        if ( !is_a( $product, 'WC_Product' ) ) {
            return;
        }

        $potential_points = pwlpar_calculate_max_potential_product_points( $product->get_id() );
        if ( absint( $potential_points ) > 0 ) {
            pwlpar_get_template( 'woocommerce/single-product/product-reward-points.php', array(
                'program_name' => pwlpar_program_name(),
                'potential_points' => $potential_points,
                'is_rewards_member' => pwlpar_current_user_is_rewards_member(),
            ) );
        }
    }

    function woocommerce_proceed_to_checkout() {
        pwlpar_get_template( 'woocommerce/cart/cart-rewards.php', array(
            'program_name' => pwlpar_program_name(),
            'points_earned' => pwlpar_calculate_earned_cart_points(),
            'is_rewards_member' => pwlpar_current_user_is_rewards_member(),
        ) );
    }

    function woocommerce_review_order_after_order_total() {
        if ( pwlpar_current_user_is_rewards_member() ) {
            pwlpar_get_template( 'woocommerce/checkout/checkout-rewards-member.php' );
        }
    }

    function woocommerce_after_checkout_billing_form() {
        if ( !pwlpar_current_user_is_rewards_member() ) {
            add_filter( 'woocommerce_create_account_default_checked', '__return_true' );
            pwlpar_get_template( 'woocommerce/checkout/checkout-rewards-join.php' );
        }
    }

    function woocommerce_after_order_details( $order ) {
        if ( !empty( $order->get_user_id( 'edit' ) ) && pwlpar_user_is_rewards_member( $order->get_user_id( 'edit' ) ) ) {

            $points_by_status = array();
            $transactions = pwlpar_get_transactions( array( 'earned_order_id' => $order->get_id() ) );
            foreach ( $transactions as $transaction ) {
                if ( !isset( $points_by_status[ $transaction->get_status( 'edit' ) ] ) ) {
                    $points_by_status[ $transaction->get_status( 'edit' ) ] = 0;
                }

                $points_by_status[ $transaction->get_status( 'edit' ) ] += $transaction->get_points( 'edit' );
            }
            if ( empty( $points_by_status ) ) {
                $points_by_status['active'] = 0;
            }

            pwlpar_get_template( 'woocommerce/order/reward-order-details.php', array(
                'order' => $order,
                'points_by_status' => $points_by_status
            ) );
        }
    }

    function woocommerce_checkout_posted_data( $data ) {
        // WooCommerce verified the nonce before calling this action hook, there is no need to re-verify the nonce.
        // phpcs:ignore WordPress.Security.NonceVerification
        $data['pwlpar_join'] = isset( $_POST['pwlpar_join'] );

        return $data;
    }

    function woocommerce_checkout_update_user_meta( $user_id, $data ) {
        if ( isset( $data['pwlpar_join'] ) && $data['pwlpar_join'] ) {
            pwlpar_enroll_user( $user_id );
        }
    }

    function woocommerce_new_order( $order_id, $order ) {
        pwlpar_mark_order_rewards_redeemed( $order );

        $points = pwlpar_calculate_earned_cart_points();
        if ( $points > 0 ) {
            pwlpar_add_earned_order_points( $order, $points );
        }
    }

    function handle_order_status_change( $order_id, $order, $status_transition ) {
        $status = $status_transition['to'];

        switch ( $status ) {
            case 'pending':
            case 'on-hold':
                pwlpar_update_earned_order_points_status( $order, 'pending' );
            break;

            case 'processing':
            case 'preordered':
            case 'completed':
                pwlpar_mark_order_rewards_redeemed( $order );
                pwlpar_update_earned_order_points_status( $order, 'active' );
            break;

            case 'cancelled':
            case 'refunded':
            case 'failed':
                pwlpar_mark_order_rewards_pending( $order );
                pwlpar_update_earned_order_points_status( $order, $status );
            break;
        }
    }

    function order_deleted( $id ) {
        global $post_type;

        if ( $post_type !== 'shop_order' && $post_type !== 'shop_order_placehold' ) {
            return;
        }

        $order = wc_get_order( $id );
        if ( is_a( $order, 'WC_Order' ) ) {
            pwlpar_mark_order_rewards_pending( $order );
            pwlpar_update_earned_order_points_status( $order, 'trash' );
        }
    }

    function order_restored( $id ) {
        global $post_type;

        if ( $post_type !== 'shop_order' && $post_type !== 'shop_order_placehold' ) {
            return;
        }

        $order = wc_get_order( $id );
        if ( is_a( $order, 'WC_Order' ) ) {
            $failed_statuses = array( 'wc-cancelled', 'wc-refunded', 'wc-failed' );

            $completed = true;
            if ( $order->has_status( $failed_statuses ) ) {
                $completed = false;
            } else {
                $original_status = get_post_field( 'post_status', $order->get_id() );
                if ( in_array( $original_status, $failed_statuses ) ) {
                    $completed = false;
                }
            }

            if ( $completed ) {
                pwlpar_mark_order_rewards_redeemed( $order );
                pwlpar_update_earned_order_points_status( $order, 'active' );
            }
        }
    }

    function deleted_user( $user_id, $reassign ) {
        $member = pwlpar_get_member( $user_id );
        if ( $member ) {
            pwlpar_delete_member( $member, $reassign );
        }
    }

    function ajax_claim_offer() {
        check_ajax_referer( 'pwlpar-claim-offer', 'security' );

        $offer_id = isset( $_REQUEST['offer_id'] ) ? absint( $_REQUEST['offer_id'] ) : wp_die( esc_html__( 'Invalid offer_id', 'pw-loyalty-points-and-rewards-for-woocommerce' ) );
        $offer = pwlpar_get_offer( $offer_id );
        $result = pwlpar_claim_offer( $offer_id );

        if ( $result !== true ) {
            pwlpar_log( 'ajax_claim_offer() Offer could not be claimed: [$offer_id: ' . $offer_id . '], [$result: ' . $result . ']' );
            /* translators: %s is the error message. */
            wp_send_json_error( array( 'message' => sprintf( __( 'Offer could not be claimed. %s', 'pw-loyalty-points-and-rewards-for-woocommerce' ), $result ) ) );
            return;
        }

        wp_send_json_success( array( 'url' => pwlpar_get_home_url() ) );
    }
}

return new PWLPAR_Hooks();
