<?php

namespace Unlockafe_Addons\Classes;

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

class Store_Credit_Manager {

    private static $instance = null;

    public static function instance() {
        if (is_null(self::$instance)) {
            self::$instance = new self();
        }
        return self::$instance;
    }

    private function __construct() {
        // Hook into plugin activation
        
        add_action('woocommerce_order_status_completed', [$this, 'generate_and_email_gift_card'], 10, 1);

        // Display available store credit on cart and checkout
        add_action('woocommerce_before_cart', [$this, 'display_available_credit_notice']);
        add_action('woocommerce_before_checkout_form', [$this, 'display_available_credit_notice']);

        // AJAX handlers for applying/removing store credit
        add_action('wp_ajax_unlockafe_apply_store_credit', [$this, 'apply_store_credit_callback']);
        add_action('wp_ajax_unlockafe_remove_store_credit', [$this, 'remove_store_credit_callback']);

        // Apply store credit as a fee
        add_action('woocommerce_cart_calculate_fees', [$this, 'apply_store_credit_as_fee']);
    }

    /**
     * Plugin activation callback.
     */
    public static function on_activation() {
        self::create_database_table();
    }

    /**
     * Create the custom database table for store credit.
     */
    public static function create_database_table() {
        global $wpdb;
        $table_name = $wpdb->prefix . 'unlockafe_store_credit';
        $charset_collate = $wpdb->get_charset_collate();

        $sql = "CREATE TABLE $table_name (
            id BIGINT(20) NOT NULL AUTO_INCREMENT,
            code VARCHAR(255) NOT NULL,
            balance DECIMAL(10, 2) NOT NULL,
            initial_balance DECIMAL(10, 2) NOT NULL,
            currency VARCHAR(10) NOT NULL,
            status VARCHAR(20) NOT NULL DEFAULT 'active',
            order_id BIGINT(20) UNSIGNED NOT NULL,
            recipient_email VARCHAR(255) DEFAULT NULL,
            created_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
            expires_at DATETIME DEFAULT NULL,
            PRIMARY KEY (id),
            UNIQUE KEY code (code)
        ) $charset_collate;";

        require_once(ABSPATH . 'wp-admin/includes/upgrade.php');
        dbDelta($sql);

        // Create the transaction log table
        $log_table_name = $wpdb->prefix . 'unlockafe_store_credit_log';
        $sql_log = "CREATE TABLE $log_table_name (
            id mediumint(9) NOT NULL AUTO_INCREMENT,
            user_id bigint(20) NOT NULL,
            order_id bigint(20) DEFAULT 0 NOT NULL,
            amount decimal(10, 2) NOT NULL,
            type varchar(50) NOT NULL, /* e.g., 'refund', 'purchase', 'manual', 'applied_to_order' */
            notes text,
            created_at datetime DEFAULT '0000-00-00 00:00:00' NOT NULL,
            PRIMARY KEY  (id),
            KEY user_id (user_id),
            KEY type (type)
        ) $charset_collate;";
        dbDelta($sql_log);
    }



    /**
     * Generate a unique gift card code.
     *
     * @param int $length
     * @return string
     */
    private function generate_unique_code($length = 16) {
        return substr(bin2hex(random_bytes(ceil($length / 2))), 0, $length);
    }

    /**
     * Get all active gift cards for a user by email.
     *
     * @param string $email The user's email address.
     * @return array An array of gift card objects.
     */
    public function get_gift_cards_by_email($email) {
        global $wpdb;
        $table_name = $wpdb->prefix . 'unlockafe_store_credit';

        $query = $wpdb->prepare(
            "SELECT * FROM {$table_name} WHERE recipient_email = %s AND status = 'active' AND balance > 0 AND (expires_at IS NULL OR expires_at >= CURDATE())",
            $email
        );

        return $wpdb->get_results($query, ARRAY_A);
    }

    /**
     * Get a gift card by its code.
     *
     * @param string $code The gift card code.
     * @return object|null The gift card object or null if not found.
     */
    public function get_gift_card_by_code($code) {
        global $wpdb;
        $table_name = $wpdb->prefix . 'unlockafe_store_credit';

        $query = $wpdb->prepare(
            "SELECT * FROM {$table_name} WHERE code = %s AND status = 'active' AND balance > 0 AND (expires_at IS NULL OR expires_at >= CURDATE())",
            $code
        );

        return $wpdb->get_row($query);
    }

    /**
     * Get the total available store credit for the current user.
     *
     * @return float
     */
    public function get_total_credit_for_current_user() {
        if (!is_user_logged_in()) {
            return 0;
        }

        $user = wp_get_current_user();
        $gift_cards = $this->get_gift_cards_by_email($user->user_email);

        if (empty($gift_cards)) {
            return 0;
        }

        $total_balance = 0;
        foreach ($gift_cards as $card) {
            $total_balance += (float) $card['balance'];
        }

        return $total_balance;
    }

    /**
     * Display available store credit and an apply button on cart/checkout.
     */
    public function display_available_credit_notice() {
        if (is_admin() || !is_user_logged_in()) {
            return;
        }

        // Check if credit is already applied
        $is_credit_applied = WC()->session->get('unlockafe_store_credit_applied');

        if ($is_credit_applied) {
            $applied_amount = WC()->session->get('unlockafe_applied_credit_amount', 0);
            $message = sprintf(
                __('You are using %s of your store credit. %s', 'unlock-addons-for-elementor'),
                wc_price($applied_amount),
                sprintf(
                    '<a href="#" class="unlockafe-remove-store-credit" data-nonce="%s">%s</a>',
                    wp_create_nonce('unlockafe-store-credit-nonce'),
                    __('Remove', 'unlock-addons-for-elementor')
                )
            );
            wc_print_notice($message, 'success');
        } else {
            $available_credit = $this->get_total_credit_for_current_user();
            if ($available_credit > 0) {
                $message = sprintf(
                    __('You have %s available in store credit. %s', 'unlock-addons-for-elementor'),
                    wc_price($available_credit),
                    '<a href="#" class="unlockafe-apply-store-credit" data-nonce="%s">' . __('Use for this order', 'unlock-addons-for-elementor') . '</a>',
                    wp_create_nonce('unlockafe-store-credit-nonce')
                );
                wc_print_notice($message, 'notice');
            }
        }
    }

    /**
     * AJAX callback to apply store credit.
     */
    public function apply_store_credit_callback() {
        check_ajax_referer('unlockafe-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')]);
        }

        WC()->session->set('unlockafe_store_credit_applied', true);
        wp_send_json_success(['message' => __('Store credit applied successfully.', 'unlock-addons-for-elementor')]);
    }

    /**
     * AJAX callback to remove store credit.
     */
    public function remove_store_credit_callback() {
        check_ajax_referer('unlockafe-store-credit-nonce', 'nonce');

        WC()->session->set('unlockafe_store_credit_applied', false);
        WC()->session->set('unlockafe_applied_credit_amount', 0);
        wp_send_json_success(['message' => __('Store credit removed.', 'unlock-addons-for-elementor')]);
    }

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

        if (!WC()->session->get('unlockafe_store_credit_applied')) {
            return;
        }

        $available_credit = $this->get_total_credit_for_current_user();
        if ($available_credit <= 0) {
            return;
        }

        $cart_total = $cart->get_subtotal() + $cart->get_shipping_total() + $cart->get_taxes_total(false, false);

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

        if ($amount_to_apply > 0) {
            $cart->add_fee(__('Store Credit', 'unlock-addons-for-elementor'), -$amount_to_apply);
            WC()->session->set('unlockafe_applied_credit_amount', $amount_to_apply);
        }
    }

    /**
     * Generate gift card and email to recipient when order is completed.
     */
    public function generate_and_email_gift_card($order_id) {
        $order = wc_get_order($order_id);
        if (!$order) {
            return;
        }

        foreach ($order->get_items() as $item_id => $item) {
            $product = $item->get_product();

            if ($product && $product->get_type() === 'unlockafe_gift_card') {
                $recipient_email = $item->get_meta('Recipient Email');
                $recipient_name = $item->get_meta('Recipient Name');
                $message = $item->get_meta('Message');
                $amount = $item->get_total();
                $purchaser_name = $order->get_billing_first_name() . ' ' . $order->get_billing_last_name();

                if ($recipient_email) {
                    $coupon_data = [
                        'amount'          => $amount,
                        'recipient_email' => $recipient_email,
                        'order_id'        => $order_id,
                    ];

                    $coupon_code = $this->create_gift_card_coupon($coupon_data);

                    if ($coupon_code) {
                        // We still create a record in our custom table for tracking and admin management.
                        $gift_card_data = [
                            'code'            => $coupon_code, // Use the coupon code here
                            'balance'         => $amount,
                            'recipient_email' => $recipient_email,
                            'order_id'        => $order_id,
                        ];
                        $this->create_gift_card($gift_card_data);

                        // Send the email with the new coupon code.
                        $this->send_gift_card_email($recipient_email, $recipient_name, $coupon_code, $amount, $purchaser_name, $message);
                    }
                }
            }
        }
    }

    /**
     * Send the gift card email to the recipient.
     */
    private function send_gift_card_email($to, $recipient_name, $code, $amount, $from_name, $message) {
        $subject = sprintf(__('You have received a gift card from %s!', 'unlock-addons-for-elementor'), $from_name);
        
        $email_heading = __('Congratulations! You have received a gift card.', 'unlock-addons-for-elementor');

        $email_content = '<p>' . sprintf(__('Hi %s,', 'unlock-addons-for-elementor'), $recipient_name) . '</p>';
        $email_content .= '<p>' . sprintf(__('%s has sent you a gift card worth %s.', 'unlock-addons-for-elementor'), $from_name, wc_price($amount)) . '</p>';
        if ($message) {
            $email_content .= '<p><strong>' . __('Message from sender:', 'unlock-addons-for-elementor') . '</strong></p>';
            $email_content .= '<blockquote>' . wp_kses_post($message) . '</blockquote>';
        }
        $email_content .= '<p>' . __('Your gift card code is:', 'unlock-addons-for-elementor') . '</p>';
        $email_content .= '<h2>' . esc_html($code) . '</h2>';
        $email_content .= '<p>' . __('You can use this code to make purchases on our store.', 'unlock-addons-for-elementor') . '</p>';

        $mailer = WC()->mailer();
        $email = new \WC_Email();
        $content = $email->style_inline($mailer->wrap_message($email_heading, $email_content));
        
        $headers = ['Content-Type: text/html; charset=UTF-8'];
        
        $mailer->send($to, $subject, $content, $headers, []);
    }

    /**
     * Create a WooCommerce coupon to be used as a gift card.
     *
     * @param array $coupon_data Data for creating the coupon.
     * @return string|false The new coupon code on success, false on failure.
     */
    private function create_gift_card_coupon($coupon_data) {
        $coupon_code = $this->generate_unique_code(12);
        $amount = $coupon_data['amount'];
        $recipient_email = $coupon_data['recipient_email'];

        $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_usage_limit_per_user(0);
        $coupon->set_limit_usage_to_x_items(0);
        $coupon->set_free_shipping(false);
        $coupon->set_email_restrictions([$recipient_email]);
        $coupon->set_description(sprintf(__('Gift card for %s from order #%d', 'unlock-addons-for-elementor'), $recipient_email, $coupon_data['order_id']));

        if ($coupon->save()) {
            // Add meta to indicate this is a gift card
            $coupon->update_meta_data('is_unlockafe_gift_card', 'yes');
            $coupon->save_meta_data();
            return $coupon_code;
        }

        return false;
    }

    /**
     * Creates a gift card from the admin panel.
     *
     * This method creates a WooCommerce coupon and a corresponding record
     * in the custom gift card table.
     *
     * @param array $data {
     *     An array of data for the new gift card.
     *
     *     @type float  $amount          The value of the gift card.
     *     @type string $recipient_email Optional. The email to restrict the coupon to.
     *     @type string $expires_at      Optional. The expiration date in Y-m-d format.
     * }
     * @return string|false The new gift card code on success, false on failure.
     */
    public function admin_create_gift_card($data) {
        if (empty($data['amount']) || !is_numeric($data['amount']) || $data['amount'] <= 0) {
            return false;
        }

        // 1. Create the WooCommerce Coupon
        $coupon_code = $this->generate_unique_code(12);
        $coupon = new \WC_Coupon();
        $coupon->set_code($coupon_code);
        $coupon->set_discount_type('fixed_cart'); // Use 'fixed_cart' for a simple discount amount
        $coupon->set_amount($data['amount']);
        $coupon->set_individual_use(true);
        $coupon->set_usage_limit(1); // Can be used once
        $coupon->set_description(sprintf(__('Admin-generated gift card for %s.', 'unlock-addons-for-elementor'), html_entity_decode(strip_tags(wc_price($data['amount'])))));

        if (!empty($data['recipient_email'])) {
            $coupon->set_email_restrictions([sanitize_email($data['recipient_email'])]);
        }

        if (!empty($data['expires_at'])) {
            $coupon->set_date_expires($data['expires_at']);
        }

        // Add meta to identify it as a gift card
        $coupon->update_meta_data('is_unlockafe_gift_card', 'yes');
        
        $coupon_id = $coupon->save();

        if (!$coupon_id) {
            return false;
        }

        // 2. Create a record in our custom table for tracking
        $gift_card_data_to_log = [
            'code'            => $coupon_code,
            'balance'         => $data['amount'],
            'initial_balance' => $data['amount'],
            'recipient_email' => !empty($data['recipient_email']) ? sanitize_email($data['recipient_email']) : '',
            'expires_at'      => !empty($data['expires_at']) ? $data['expires_at'] : null,
            'order_id'        => 0, // 0 indicates it was manually generated
        ];

        $this->create_gift_card($gift_card_data_to_log);

        return $coupon_code;
    }

    /**
     * Get all gift card records from the database.
     *
     * @return array
     */
    public function get_all_gift_cards() {
        global $wpdb;
        $table_name = $wpdb->prefix . 'unlockafe_store_credit';

        $results = $wpdb->get_results("SELECT * FROM {$table_name} ORDER BY created_at DESC", ARRAY_A);

        return $results;
    }

    /**
     * Delete one or more gift cards from the database.
     *
     * @param array $gift_card_ids An array of gift card IDs to delete.
     * @return int The number of gift cards successfully deleted.
     */
    public function delete_gift_cards($gift_card_ids) {
        global $wpdb;
        $table_name = $wpdb->prefix . 'unlockafe_store_credit';

        if (empty($gift_card_ids)) {
            return 0;
        }

        // Sanitize the IDs to ensure they are integers.
        $ids = implode(',', array_map('absint', $gift_card_ids));

        // The query is now safe as all IDs are integers.
        $deleted_count = $wpdb->query("DELETE FROM {$table_name} WHERE id IN ({$ids})");

        return $deleted_count;
    }

    private function create_gift_card($gift_card_data) {
        global $wpdb;
        $table_name = $wpdb->prefix . 'unlockafe_store_credit';

        // Use the provided code if it exists (from a WC Coupon), otherwise generate a new one.
        $code = !empty($gift_card_data['code']) ? $gift_card_data['code'] : $this->generate_unique_code();

        $defaults = [
            'balance'         => 0,
            'initial_balance' => 0,
            'currency'        => get_woocommerce_currency(),
            'order_id'        => 0,
            'recipient_email' => '',
        ];

        $gift_card_data = wp_parse_args($gift_card_data, $defaults);

        $result = $wpdb->insert(
            $table_name,
            [
                'code'            => $code,
                'balance'         => $gift_card_data['balance'],
                'initial_balance' => $gift_card_data['balance'],
                'currency'        => $gift_card_data['currency'],
                'order_id'        => $gift_card_data['order_id'],
                'recipient_email' => $gift_card_data['recipient_email'],
            ],
            ['%s', '%f', '%f', '%s', '%d', '%s']
        );

        if ($result !== false) {
            return $code;
        }

        return false;
    }
}
