<?php

namespace Unlockafe_Addons\Classes;

if (!defined('ABSPATH')) {
    exit; // Exit if accessed directly.
}

/**
 * Class Store_Credit_Controller
 * @package Unlockafe_Addons\Classes
 */
class Store_Credit_Controller {

    private static $instance = null;

    /**
     * Store_Credit_Controller constructor.
     */
    public function __construct() {
        $this->init_hooks();
    }

    /**
     * Initialize hooks.
     */
    public function init_hooks() {
        // Hooks for admin user profile fields
        add_action('show_user_profile', [$this, 'show_store_credit_field']);
        add_action('edit_user_profile', [$this, 'show_store_credit_field']);
        add_action('personal_options_update', [$this, 'save_store_credit_field']);
        add_action('edit_user_profile_update', [$this, 'save_store_credit_field']);

        // Hooks for frontend display and actions
        add_action('woocommerce_before_cart_totals', [$this, 'display_store_credit_ui']);
        add_action('woocommerce_review_order_before_payment', [$this, 'display_store_credit_ui']);

        // Hooks for AJAX actions
        add_action('wp_ajax_unlockafe_apply_store_credit', [$this, 'handle_apply_store_credit']);
        add_action('wp_ajax_unlockafe_remove_store_credit', [$this, 'handle_remove_store_credit']);

        // Hook to apply credit as a fee
        add_action('woocommerce_cart_calculate_fees', [$this, 'apply_store_credit_fee']);

        // Hooks for order processing
        add_action('woocommerce_checkout_update_order_meta', [$this, 'save_credit_to_order_meta']);
        add_action('woocommerce_order_status_completed', [$this, 'deduct_credit_on_order_completion']);
        add_action('woocommerce_order_status_completed', [$this, 'grant_credit_on_gift_card_purchase']);

        // Hook for scheduled gift card sending
        add_action('unlockafe_send_scheduled_gift_card', [$this, 'send_scheduled_gift_card'], 10, 1);

        // Hook for gift card coupon validation
        add_filter('woocommerce_coupon_is_valid', [$this, 'validate_gift_card_coupon'], 10, 3);

        // Register the custom product type
        add_filter('product_type_selector', [$this, 'add_gift_card_product_type']);
        add_filter('woocommerce_product_class', [$this, 'load_gift_card_product_class'], 10, 2);
        add_action('woocommerce_thankyou', [$this, 'clear_session_credit']);

        // Hooks for product settings
        add_filter('woocommerce_product_data_tabs', [$this, 'add_gift_card_product_data_tab']);
        add_action('woocommerce_product_data_panels', [$this, 'add_gift_card_product_data_panel']);
        add_action('woocommerce_process_product_meta_unlockafe_gift_card', [$this, 'save_gift_card_product_data']);

        // Hooks for frontend gift card custom amount
        add_action('woocommerce_before_add_to_cart_button', [$this, 'display_custom_amount_field']);
        add_filter('woocommerce_add_cart_item_data', [$this, 'add_gift_card_custom_amount_to_cart'], 10, 3);
        add_action('woocommerce_before_calculate_totals', [$this, 'set_gift_card_custom_price']);
    }

    /**
     * Display store credit fields on the user profile page.
     *
     * @param \WP_User $user The user object.
     */
    public function show_store_credit_field($user) {
        if (!current_user_can('manage_woocommerce')) {
            return;
        }

        $balance = $this->get_credit_balance($user->ID);
        ?>
        <h2><?php esc_html_e('Store Credit', 'unlock-addons-for-elementor'); ?></h2>
        <table class="form-table">
            <tr>
                <th><label for="unlockafe_store_credit_balance"><?php esc_html_e('Current Balance', 'unlock-addons-for-elementor'); ?></label></th>
                <td>
                    <input type="text" id="unlockafe_store_credit_balance" value="<?php echo esc_attr(wc_price($balance)); ?>" class="regular-text" readonly />
                </td>
            </tr>
            <tr>
                <th><label for="unlockafe_credit_adjustment"><?php esc_html_e('Adjust Credit', 'unlock-addons-for-elementor'); ?></label></th>
                <td>
                    <input type="number" step="0.01" id="unlockafe_credit_adjustment" name="unlockafe_credit_adjustment" class="regular-text" />
                    <p class="description"><?php esc_html_e('Enter a positive value to add credit or a negative value to deduct credit.', 'unlock-addons-for-elementor'); ?></p>
                </td>
            </tr>
        </table>
        <?php
        wp_nonce_field('unlockafe_save_store_credit', '_unlockafenonce');
    }

    /**
     * Save the store credit fields from the user profile page.
     *
     * @param int $user_id The user ID being updated.
     */
    public function save_store_credit_field($user_id) {
        if (!current_user_can('manage_woocommerce') || !isset($_POST['_unlockafenonce']) || !wp_verify_nonce($_POST['_unlockafenonce'], 'unlockafe_save_store_credit')) {
            return;
        }

        if (isset($_POST['unlockafe_credit_adjustment']) && is_numeric($_POST['unlockafe_credit_adjustment'])) {
            $adjustment = (float) $_POST['unlockafe_credit_adjustment'];
            if ($adjustment !== 0.0) {
                $this->update_credit_balance($user_id, $adjustment, 'manual', 0, 'Manual adjustment by admin.');
            }
        }
    }

    /**
     * Get the store credit balance for a specific user.
     *
     * @param int $user_id The ID of the user.
     * @return float The user's credit balance.
     */
    public function get_credit_balance($user_id) {
        if (empty($user_id)) {
            return 0.0;
        }
        return (float) get_user_meta($user_id, '_unlockafe_store_credit', true);
    }

    /**
     * Update the store credit balance for a user and log the transaction.
     *
     * @param int    $user_id The user ID.
     * @param float  $amount  The amount to add (positive) or deduct (negative).
     * @param string $type    The type of transaction (e.g., 'manual', 'refund', 'applied_to_order').
     * @param int    $order_id Optional order ID related to the transaction.
     * @param string $notes    Optional notes for the transaction.
     * @return bool True on success, false on failure.
     */
    public function update_credit_balance($user_id, $amount, $type, $order_id = 0, $notes = '') {
        if (empty($user_id)) {
            return false;
        }

        $current_balance = $this->get_credit_balance($user_id);
        $new_balance = $current_balance + (float) $amount;

        if ($new_balance < 0) {
            // Prevent balance from going negative
            return false;
        }

        update_user_meta($user_id, '_unlockafe_store_credit', $new_balance);
        $this->log_transaction($user_id, $amount, $type, $order_id, $notes);

        return true;
    }

    /**
     * Log a store credit transaction.
     *
     * @param int    $user_id
     * @param float  $amount
     * @param string $type
     * @param int    $order_id
     * @param string $notes
     */
    private function log_transaction($user_id, $amount, $type, $order_id = 0, $notes = '') {
        global $wpdb;
        $table_name = $wpdb->prefix . 'unlockafe_store_credit_log';

        $wpdb->insert(
            $table_name,
            [
                'user_id'    => $user_id,
                'amount'     => $amount,
                'type'       => $type,
                'order_id'   => $order_id,
                'notes'      => $notes,
                'created_at' => current_time('mysql'),
            ],
            ['%d', '%f', '%s', '%d', '%s', '%s']
        );
    }

    /**
     * Get the singleton instance.
     *
     * @return Store_Credit_Controller
     */
    public static function instance() {
        if (is_null(self::$instance)) {
            self::$instance = new self();
        }
        return self::$instance;
    }

    /**
     * Display store credit UI on cart and checkout pages.
     */
    public function display_store_credit_ui() {
        if (!is_user_logged_in()) {
            return;
        }

        $user_id = get_current_user_id();
        $balance = $this->get_credit_balance($user_id);

        if ($balance > 0) {
            wc_get_template('store-credit-ui.php', [
                'balance' => $balance,
                'credit_applied' => WC()->session->get('unlockafe_store_credit_applied', 0),
            ], '', UNLOCKAFE_ADDONS_PATH . 'templates/store-credit/');
        }
    }

    /**
     * Handle the AJAX request to apply store credit.
     */
    public function handle_apply_store_credit() {
        check_ajax_referer('unlockafe-apply-store-credit-nonce', 'nonce');

        if (!is_user_logged_in()) {
            wp_send_json_error(['message' => __('You must be logged in to use store credit.', 'unlock-addons-for-elementor')]);
        }

        $user_id = get_current_user_id();
        $balance = $this->get_credit_balance($user_id);
        $cart_total = WC()->cart->get_totals()['total'];

        $amount_to_apply = min($balance, $cart_total);

        if ($amount_to_apply > 0) {
            WC()->session->set('unlockafe_store_credit_applied', $amount_to_apply);
            wp_send_json_success(['message' => __('Store credit applied successfully.', 'unlock-addons-for-elementor')]);
        } else {
            wp_send_json_error(['message' => __('Could not apply store credit.', 'unlock-addons-for-elementor')]);
        }
    }

    /**
     * Handle the AJAX request to remove store credit.
     */
    public function handle_remove_store_credit() {
        check_ajax_referer('unlockafe-remove-store-credit-nonce', 'nonce');

        if (WC()->session->get('unlockafe_store_credit_applied')) {
            WC()->session->set('unlockafe_store_credit_applied', 0);
            wp_send_json_success(['message' => __('Store credit removed.', 'unlock-addons-for-elementor')]);
        } else {
            wp_send_json_error(['message' => __('No store credit to remove.', 'unlock-addons-for-elementor')]);
        }
    }

    /**
     * Apply the store credit as a negative fee to the cart.
     *
     * @param \WC_Cart $cart
     */
    public function apply_store_credit_fee($cart) {
        if (is_admin() && !defined('DOING_AJAX')) {
            return;
        }

        $credit_applied = WC()->session->get('unlockafe_store_credit_applied', 0);

        if ($credit_applied > 0) {
            $cart->add_fee(__('Store Credit', 'unlock-addons-for-elementor'), -$credit_applied);
        }
    }

    /**
     * Save the amount of store credit applied to the order meta.
     *
     * @param int $order_id The ID of the order being created.
     */
    public function save_credit_to_order_meta($order_id) {
        $credit_applied = WC()->session->get('unlockafe_store_credit_applied', 0);
        if ($credit_applied > 0) {
            $order = wc_get_order($order_id);
            $order->update_meta_data('_unlockafe_store_credit_used', $credit_applied);
            $order->save();
        }
    }

    /**
     * Deduct the used store credit from the user's balance upon order completion.
     *
     * @param int $order_id The ID of the completed order.
     */
    public function deduct_credit_on_order_completion($order_id) {
        $order = wc_get_order($order_id);
        $user_id = $order->get_user_id();
        $credit_used = (float) $order->get_meta('_unlockafe_store_credit_used', true);

        if ($user_id && $credit_used > 0) {
            $this->update_credit_balance($user_id, -$credit_used, 'applied_to_order', $order_id, sprintf(__('Credit applied to order #%s', 'unlock-addons-for-elementor'), $order_id));
        }
    }

    /**
     * Clear the store credit from the session after checkout is complete.
     *
     * @param int $order_id The ID of the order.
     */
    public function clear_session_credit($order_id) {
        if (WC()->session && WC()->session->get('unlockafe_store_credit_applied')) {
            WC()->session->set('unlockafe_store_credit_applied', 0);
        }
    }


    /**
     * Process gift card purchases when an order is completed.
     * This will either send the gift card immediately or schedule it for a future date.
     *
     * @param int $order_id The ID of the completed order.
     */
    public function grant_credit_on_gift_card_purchase($order_id) {
        $order = wc_get_order($order_id);

        foreach ($order->get_items() as $item_id => $item) {
            $product = $item->get_product();
            if ($product && $product->get_type() === 'unlockafe_gift_card') {
                $delivery_date = $item->get_meta('Delivery Date');
                $recipient_email = $item->get_meta('Recipient Email');
                $recipient_name = $item->get_meta('Recipient Name');
                $message = $item->get_meta('Message');
                $amount = $item->get_total();
                $product_id = $item->get_product_id();

                if (empty($recipient_email)) {
                    continue; // Skip if no recipient email
                }

                $event_args = [
                    'recipient_email' => $recipient_email,
                    'recipient_name'  => $recipient_name,
                    'message'         => $message,
                    'amount'          => $amount,
                    'order_id'        => $order_id,
                    'purchaser_name'  => $order->get_billing_first_name(),
                    'product_id'      => $product_id,
                ];

                if (!empty($delivery_date) && strtotime($delivery_date) > time()) {
                    // Schedule the gift card to be sent on the delivery date
                    wp_schedule_single_event(strtotime($delivery_date . ' 09:00:00'), 'unlockafe_send_scheduled_gift_card', ['args' => $event_args]);
                } else {
                    // Send immediately
                    $this->send_gift_card_email($event_args);
                }
            }
        }
    }

    /**
     * Handler for the scheduled cron event to send a gift card.
     *
     * @param array $args
     */
    public function send_scheduled_gift_card($args) {
        $this->send_gift_card_email($args['args']);
    }

    /**
     * Generate a coupon and send the gift card email.
     *
     * @param array $args
     */
    public function send_gift_card_email($args) {
        $recipient_email = $args['recipient_email'];
        $recipient_name = $args['recipient_name'];
        $message = $args['message'];
        $amount = $args['amount'];
        $order_id = $args['order_id'];
        $purchaser_name = $args['purchaser_name'];
        $product_id = $args['product_id'];

        // Get selected email template
        $template_name = get_post_meta($product_id, '_unlockafe_gift_card_template', true);
        if (empty($template_name)) {
            $template_name = 'default';
        }
        $template_path = "emails/customer-gift-card-{$template_name}.php";

        // Generate a unique coupon code
        $coupon_code = 'GIFT-' . strtoupper(wp_generate_password(8, false));

        $coupon = new \WC_Coupon();
        $coupon->set_code($coupon_code);
        $coupon->set_discount_type('fixed_cart');
        $coupon->set_amount($amount);
        $coupon->set_individual_use(true);
        $coupon->set_usage_limit(1);
        $coupon->set_date_expires(''); // No expiry date
        $coupon->set_email_restrictions([$recipient_email]);
        $coupon->save();

        // Prepare the email
        $mailer = WC()->mailer();
        $subject = sprintf(__('You have received a gift card from %s!', 'unlock-addons-for-elementor'), $purchaser_name);
        $email_heading = __('Your Gift Card Has Arrived!', 'unlock-addons-for-elementor');

        ob_start();
        // Fallback to default if template is not found
        if (!file_exists(UNLOCKAFE_ADDONS_PATH . 'templates/' . $template_path)) {
            $template_path = 'emails/customer-gift-card.php';
        }

        wc_get_template($template_path, [
            'recipient_name' => $recipient_name,
            'purchaser_name' => $purchaser_name,
            'message'        => $message,
            'coupon_code'    => $coupon_code,
            'amount'         => wc_price($amount),
            'email_heading'  => $email_heading,
        ], '', UNLOCKAFE_ADDONS_PATH . 'templates/');
        $email_body = ob_get_clean();

        $headers = ['Content-Type: text/html; charset=UTF-8'];
        $mailer->send($recipient_email, $subject, $mailer->wrap_message($email_heading, $email_body), $headers, []);

        // Add order note
        $order = wc_get_order($order_id);
        if ($order) {
            $note = sprintf(__('Gift card worth %s sent to %s. Coupon code: %s', 'unlock-addons-for-elementor'), wc_price($amount), $recipient_email, $coupon_code);
            $order->add_order_note($note);
        }
    }

    /**
     * Add 'Gift Card' to the product type selector.
     *
     * @param array $types
     * @return array
     */
    public function add_gift_card_product_type($types) {
        $types['unlockafe_gift_card'] = __('Gift Card', 'unlock-addons-for-elementor');
        return $types;
    }

    /**
     * Load the custom product class for the 'Gift Card' type.
     *
     * @param string $classname
     * @param string $product_type
     * @return string
     */
    public function load_gift_card_product_class($classname, $product_type) {
        if ($product_type === 'unlockafe_gift_card') {
            return 'Unlockafe_addons\\Classes\\Product_Gift_Card';
        }
        return $classname;
    }

    /**
     * Add the 'Gift Card' product data tab.
     *
     * @param array $tabs
     * @return array
     */
    public function add_gift_card_product_data_tab($tabs) {
        $tabs['unlockafe_gift_card'] = [
            'label'    => __('Gift Card', 'unlock-addons-for-elementor'),
            'target'   => 'unlockafe_gift_card_product_data',
            'class'    => ['show_if_unlockafe_gift_card'],
            'priority' => 21,
        ];
        return $tabs;
    }

    /**
     * Add the 'Gift Card' product data panel.
     */
    public function add_gift_card_product_data_panel() {
        global $post;

        echo '<div id="unlockafe_gift_card_product_data" class="panel woocommerce_options_panel">';

        woocommerce_wp_checkbox([
            'id'            => '_unlockafe_allow_custom_amount',
            'label'         => __('Allow Custom Amount', 'unlock-addons-for-elementor'),
            'description'   => __('Allow customers to enter a custom gift card value.', 'unlock-addons-for-elementor'),
            'desc_tip'      => true,
            'value'         => get_post_meta($post->ID, '_unlockafe_allow_custom_amount', true),
        ]);

        woocommerce_wp_select([
            'id'      => '_unlockafe_gift_card_template',
            'label'   => __('Email Template', 'unlock-addons-for-elementor'),
            'options' => [
                'default' => __('Default', 'unlock-addons-for-elementor'),
                'birthday' => __('Birthday', 'unlock-addons-for-elementor'),
                'holiday' => __('Holiday', 'unlock-addons-for-elementor'),
            ],
            'desc_tip' => true,
            'description' => __('Select the email template for this gift card.', 'unlock-addons-for-elementor'),
            'value' => get_post_meta($post->ID, '_unlockafe_gift_card_template', true),
        ]);

        echo '</div>';
    }

    /**
     * Save the gift card product data.
     *
     * @param int $post_id
     */
    public function save_gift_card_product_data($post_id) {
        $allow_custom_amount = isset($_POST['_unlockafe_allow_custom_amount']) ? 'yes' : 'no';
        update_post_meta($post_id, '_unlockafe_allow_custom_amount', $allow_custom_amount);

        if (isset($_POST['_unlockafe_gift_card_template'])) {
            update_post_meta($post_id, '_unlockafe_gift_card_template', sanitize_text_field($_POST['_unlockafe_gift_card_template']));
        }
    }

    /**
     * Display the custom amount field on the gift card product page.
     */
    public function display_custom_amount_field() {
        global $product;

        if ($product->get_type() === 'unlockafe_gift_card' && $product->get_meta('_unlockafe_allow_custom_amount') === 'yes') {
            echo '<div class="unlockafe-gift-card-custom-amount">';
            woocommerce_form_field('unlockafe_gift_card_amount', [
                'type' => 'number',
                'class' => ['input-text'],
                'label' => __('Gift Card Amount', 'unlock-addons-for-elementor'),
                'placeholder' => __('Enter amount', 'unlock-addons-for-elementor'),
                'required' => true,
                'custom_attributes' => [
                    'min' => 1,
                    'step' => 'any',
                ],
            ]);
            echo '</div>';
        }
    }

    /**
     * Add the custom amount to the cart item data.
     *
     * @param array $cart_item_data
     * @param int $product_id
     * @param int $variation_id
     * @return array
     */
    public function add_gift_card_custom_amount_to_cart($cart_item_data, $product_id, $variation_id) {
        if (isset($_POST['unlockafe_gift_card_amount'])) {
            $product = wc_get_product($product_id);
            if ($product && $product->get_type() === 'unlockafe_gift_card' && $product->get_meta('_unlockafe_allow_custom_amount') === 'yes') {
                $custom_amount = floatval(sanitize_text_field($_POST['unlockafe_gift_card_amount']));
                if ($custom_amount > 0) {
                    $cart_item_data['unlockafe_gift_card_amount'] = $custom_amount;
                }
            }
        }
        return $cart_item_data;
    }

    /**
     * Set the custom price for the gift card in the cart.
     *
     * @param \WC_Cart $cart
     */
    public function set_gift_card_custom_price($cart) {
        if (is_admin() && !defined('DOING_AJAX')) {
            return;
        }

        foreach ($cart->get_cart() as $cart_item) {
            if (isset($cart_item['unlockafe_gift_card_amount'])) {
                $cart_item['data']->set_price($cart_item['unlockafe_gift_card_amount']);
            }
        }
    }

    /**
     * Validate gift card coupons to ensure they are used by the correct recipient.
     *
     * @param bool $is_valid
     * @param \WC_Coupon $coupon
     * @param \WC_Discounts $discount
     * @return bool|\WP_Error
     */
    public function validate_gift_card_coupon($is_valid, $coupon, $discount) {
        if (!$is_valid) {
            return $is_valid;
        }

        if (strpos($coupon->get_code(), 'GIFT-') === 0) {
            $user = wp_get_current_user();
            if (!$user || !$user->ID) {
                return new \WP_Error('invalid_coupon', __('Please log in to use this gift card.', 'unlock-addons-for-elementor'));
            }

            $user_email = $user->user_email;
            $restricted_emails = $coupon->get_email_restrictions();

            if (!empty($restricted_emails) && !in_array($user_email, $restricted_emails)) {
                return new \WP_Error('invalid_coupon', __('This gift card is not valid for your email address.', 'unlock-addons-for-elementor'));
            }
        }

        return $is_valid;
    }
}
