HEX
Server: Apache/2.4.52 (Ubuntu)
System: Linux spn-python 5.15.0-89-generic #99-Ubuntu SMP Mon Oct 30 20:42:41 UTC 2023 x86_64
User: arjun (1000)
PHP: 8.1.2-1ubuntu2.20
Disabled: NONE
Upload Files
File: /var/www/html/video-rental/wp-content/themes/video-rental-old/functions.php
<?php
require_once get_template_directory() . '/templates/country-codes.php';
function theme_enqueue_styles()
{
    $template_dir = get_template_directory_uri();

    // Always-loaded common styles
    wp_enqueue_style('common-style', $template_dir . '/css/common.css');
    wp_enqueue_style('header-style', $template_dir . '/css/header.css');
    wp_enqueue_style('footer-style', $template_dir . '/css/footer.css');
    wp_enqueue_style('home-style', $template_dir . '/css/home.css');
    wp_enqueue_style('modal-style', $template_dir . '/css/modal.css');

    if (is_page('login')) {
        wp_enqueue_style('login-style', $template_dir . '/css/login.css');
    }

    if (is_page('contact-us')) {
        wp_enqueue_style('contact-style', $template_dir . '/css/contact.css');
    }

    if (is_page('profile')) {
        wp_enqueue_style('my-rentals-style', $template_dir . '/css/my-rentals.css');
    }
    // Toastr CSS
    wp_enqueue_style(
        'toastr-css',
        'https://cdnjs.cloudflare.com/ajax/libs/toastr.js/latest/toastr.min.css',
        [],
        null
    );
}
add_action('wp_enqueue_scripts', 'theme_enqueue_styles');
function cw_enqueue_parsley_validation()
{
    // Load Parsley CSS (optional but good for styling)
    wp_enqueue_style(
        'parsley-css',
        'https://cdn.jsdelivr.net/npm/parsleyjs/src/parsley.css',
        [],
        null
    );

    // Load Parsley JS
    wp_enqueue_script(
        'parsley-js',
        'https://cdn.jsdelivr.net/npm/parsleyjs',
        ['jquery'], // depends on jQuery
        null,
        true
    );
    // Toastr JS
    wp_enqueue_script(
        'toastr-js',
        'https://cdnjs.cloudflare.com/ajax/libs/toastr.js/latest/toastr.min.js',
        ['jquery'],
        null,
        true
    );
    // html2pdf external library
    wp_enqueue_script(
        'html2pdf-js',
        'https://cdnjs.cloudflare.com/ajax/libs/html2pdf.js/0.10.1/html2pdf.bundle.min.js',
        [],
        null,
        true
    );
}
add_action('wp_enqueue_scripts', 'cw_enqueue_parsley_validation');
// Enqueue custom JS and localize ajax data
function enqueue_custom_login_script()
{
    wp_enqueue_script(
        'custom-ajax-script',
        get_template_directory_uri() . '/js/custom_js.js',
        ['jquery'],
        null,
        true
    );

    wp_localize_script('custom-ajax-script', 'ajax_obj', [
        'ajaxurl' => admin_url('admin-ajax.php'),
        'is_logged_in' => is_user_logged_in(),
        'site_url' => get_site_url(),
        'redirect_url' => home_url()
    ]);
}
add_action('wp_enqueue_scripts', 'enqueue_custom_login_script');
add_filter('show_admin_bar', '__return_false');

function enqueue_password_toggle_script()
{
    wp_enqueue_script(
        'password-toggle-js',
        get_stylesheet_directory_uri() . '/js/password-toggle.js',
        array('jquery'),
        null,
        true
    );

    // Pass PHP variables to JS
    wp_localize_script(
        'password-toggle-js',
        'passwordToggleVars',
        array(
            'eyeOpen' => get_stylesheet_directory_uri() . '/img/eye-ico.svg',
            'eyeClose' => get_stylesheet_directory_uri() . '/img/eye_ico_close.svg',
        )
    );
}
add_action('wp_enqueue_scripts', 'enqueue_password_toggle_script');
//User Registration

add_action('wp_ajax_nopriv_register_user', 'handle_user_registration');
add_action('wp_ajax_register_user', 'handle_user_registration');
function handle_user_registration()
{

    // Sanitize and validate input
    $first_name = sanitize_text_field($_POST['first_name']);
    $last_name = sanitize_text_field($_POST['last_name']);
    $email = sanitize_email($_POST['email']);
    $country_code = sanitize_text_field($_POST['country_code']);
    $phone = sanitize_text_field($_POST['phone']);
    $password = sanitize_text_field($_POST['password']);
    $confirm_password = sanitize_text_field($_POST['confirm_password']);
    $terms = isset($_POST['terms']) ? true : false;

    // Validate email
    if (!is_email($email)) {
        wp_send_json_error(['message' => 'Invalid email address.']);
    }

    // Check if email already exists
    if (email_exists($email)) {
        wp_send_json_error(['message' => 'Email already exists']);
        // wp_send_json_success(['message' => 'If the provided email was not already registered, you have been successfully registered, and a verification email has been sent.']);
    }
    // Check password match
    if ($password !== $confirm_password) {
        wp_send_json_error(['message' => 'Passwords do not match.']);
    }

    // Generate username
    $user_login = strstr($email, '@', true); // Part before @ in email
    $user_nicename = sanitize_title($first_name . '-' . $last_name);
    $display_name = trim($first_name . ' ' . $last_name);
    $phone_no = trim($country_code . ' ' . $phone);

    // Prepare user data
    $user_data = [
        'user_login' => $user_login,
        'user_pass' => $password,
        'user_email' => $email,
        'first_name' => $first_name,
        'last_name' => $last_name,
        'user_nicename' => $user_nicename,
        'display_name' => $display_name,
        // 'email_verified' => 0,
    ];

    // Insert user into database
    $user_id = wp_insert_user($user_data);

    // Handle errors during user creation
    if (is_wp_error($user_id)) {
        wp_send_json_error(['message' => $user_id->get_error_message()]);
    }
    update_user_meta($user_id, 'phone', $phone);
    // update_user_meta($user_id, 'email_verified', 0);
    update_user_meta($user_id, 'phone_country_code', $country_code);
    // Email Verification Logic
    // $verification_code = wp_generate_password(20, false); // Generate a secure random code
    // update_user_meta($user_id, 'email_verification_code', $verification_code);

    // $token = base64_encode(json_encode([
    //     'user_id' => $user_id,
    //     'code' => $verification_code,
    //     'timestamp' => time(),
    // ]));

    // // Generate verification link
    // $verification_link = add_query_arg('token', $token, site_url('/email-verification/'));
    // $base_url = get_template_directory_uri();

    // // Load the email template
    // $template_path = __DIR__ . '/emails/email-verification.php';
    // if (!file_exists($template_path)) {
    //     wp_send_json_error(['message' => 'Email template not found.']);
    // }

    // $email_body = file_get_contents($template_path);

    // // Replace placeholders with dynamic data
    // $email_body = str_replace('{{verification_link}}', esc_url($verification_link), $email_body);
    // $email_body = str_replace('{{display_name}}', esc_html($display_name), $email_body);
    // $email_body = str_replace('{{base_url}}', $base_url, $email_body);

    // // Send email
    // $subject = "Verify Your Email Address";
    // $headers = ['Content-Type: text/html; charset=UTF-8'];

    // if (!wp_mail($email, $subject, $email_body, $headers)) {
    //     wp_send_json_error(['message' => 'Failed to send verification email.']);
    // }
    $admin_email = get_option('admin_email');
    $admin_subject = "New User Registration: " . $display_name;
    $admin_panel_url = admin_url('user-edit.php?user_id=' . $user_id);
    $user_info = get_userdata($user_id);
    $registered_date = $user_info->user_registered;
    $registered_date_formatted = date('F j, Y \a\t g:i A', strtotime($registered_date));

    // Load the email template
    $template_path = __DIR__ . '/emails/admin-new-user.php';
    if (!file_exists($template_path)) {
        wp_send_json_error(['message' => 'Admin email template not found.']);
    }

    $admin_message = file_get_contents($template_path);

    // Replace placeholders with dynamic data
    $admin_message = str_replace('{{display_name}}', esc_html($display_name), $admin_message);
    $admin_message = str_replace('{{email}}', esc_html($email), $admin_message);
    $admin_message = str_replace('{{user_login}}', esc_html($user_login), $admin_message);
    $admin_message = str_replace('{{phone_no}}', esc_html($phone_no), $admin_message);
    $admin_message = str_replace('{{admin_panel_url}}', esc_url($admin_panel_url), $admin_message);
    $admin_message = str_replace('{{base_url}}', $base_url, $admin_message);
    $admin_message = str_replace('{{registered_date}}', esc_html($registered_date_formatted), $admin_message);


    // Send the email
    wp_mail($admin_email, $admin_subject, $admin_message, $headers);

    wp_send_json_success(['message' => 'You have been successfully registered.']);
}

//email verification

// add_action('init', 'verify_user_email');

// function verify_user_email()
// {
//     // Check if the verification parameters are present
//     if (isset($_GET['token']) && !empty($_GET['token'])) {
//         $token = sanitize_text_field($_GET['token']);
//         $data = json_decode(base64_decode($token), true);
//         // Validate the token structure and verify the code
//         if (isset($data['user_id'], $data['code']) && valid_code($data['user_id'], $data['code'])) {
//             $user_id = intval($data['user_id']);
//             $code = sanitize_text_field($data['code']);

//             // Retrieve user using meta key and value
//             $user_query = new WP_User_Query([
//                 'meta_key' => 'email_verification_code',
//                 'meta_value' => $code,
//             ]);
//             update_user_meta($user_id, 'email_verified', 1);
//             if (!empty($user_query->results)) {
//                 $user = $user_query->results[0];

//                 // Clean up meta data and mark email as verified
//                 delete_user_meta($user->ID, 'email_verification_code');
//                 update_user_meta($user->ID, 'email_verified', true);

//                 // Redirect to login page with success message
//                 wp_redirect(site_url('/login?verified=success'));
//                 exit;
//             }
//         }

//         // Invalid or expired token
//         wp_die("Invalid or expired verification link.");
//     }
// }

// Helper function to validate the code against the user ID
// function valid_code($user_id, $code)
// {
//     $stored_code = get_user_meta($user_id, 'email_verification_code', true);
//     return !empty($stored_code) && hash_equals($stored_code, $code);
// }


// Register the AJAX handler for guests and logged-in users
add_action('wp_ajax_nopriv_login_user', 'login_user');
add_action('wp_ajax_login_user', 'login_user');

// Login handler function
function login_user()
{
    // Sanitize input
    $email = isset($_POST['email']) ? sanitize_email($_POST['email']) : '';
    $password = isset($_POST['password']) ? sanitize_text_field($_POST['password']) : '';
    $remember = isset($_POST['remember']) && $_POST['remember'] === 'true';

    // Validate input
    if (empty($email) || empty($password)) {
        wp_send_json_error(['message' => 'Email and password are required.']);
    }

    // Get user by email
    $user = get_user_by('email', $email);
    // if (!$user || !wp_check_password($password, $user->user_pass, $user->ID)) {
    //     wp_send_json_error(['message' => 'Invalid email or password.']);
    // }

    // Optional: Check if email is verified (remove if not using this feature)
    // $email_verified = get_user_meta($user->ID, 'email_verified', true);
    // if ($email_verified !== '1') {
    //     wp_send_json_error(['message' => 'Please verify your email before logging in.']);
    // }

    // Set login credentials
    $creds = [
        'user_login' => $user->user_login,
        'user_password' => $password,
        'remember' => $remember,
    ];

    // Attempt login
    $user_signon = wp_signon($creds, false);

    if (is_wp_error($user_signon)) {
        $error = $user_signon->get_error_message();
        wp_send_json_error(['message' => strip_tags($error)]);
    }

    // Optional: Custom login logic
    if (function_exists('main_site_login')) {
        main_site_login($user->ID);
    }

    // Send success response
    wp_send_json_success([
        'message' => 'Login successful.',
        'redirect' => site_url('/profile') // Change to your desired URL
    ]);
}
add_action('wp_ajax_update_user_profile', function () {

    parse_str($_POST['form_data'], $form_data);
    $user_id = get_current_user_id();

    if (!$user_id) {
        wp_send_json_error('User not logged in');
    }

    $first_name = sanitize_text_field($form_data['first_name']);
    $last_name = sanitize_text_field($form_data['last_name']);
    $phone = sanitize_text_field($form_data['phone']);
    $email = sanitize_email($form_data['email']);
    $country_code = sanitize_text_field($form_data['country_code']);

    if (!is_email($email)) {
        wp_send_json_error('Invalid email');
    }

    $current_email = wp_get_current_user()->user_email;
    if ($email != $current_email && email_exists($email)) {
        wp_send_json_error('Email already exists');
    }

    // Update user fields
    wp_update_user([
        'ID' => $user_id,
        'user_email' => $email,
        'first_name' => $first_name,
        'last_name' => $last_name
    ]);

    // update_user_meta($user_id, 'phone', $country_code . ' ' . $phone);
    update_user_meta($user_id, 'phone', sanitize_text_field($phone));
    update_user_meta($user_id, 'phone_country_code', sanitize_text_field($country_code));

    wp_send_json_success();
});
add_action('wp_ajax_upload_profile_image', 'upload_profile_image_callback');

function upload_profile_image_callback()
{
    // check_ajax_referer('profile_image_nonce');

    if (!is_user_logged_in()) {
        wp_send_json_error(['message' => 'User not logged in']);
    }

    if (!isset($_FILES['profile_image'])) {
        wp_send_json_error(['message' => 'No file uploaded']);
    }

    $file = $_FILES['profile_image'];

    require_once(ABSPATH . 'wp-admin/includes/file.php');
    $upload = wp_handle_upload($file, ['test_form' => false]);

    if (isset($upload['error'])) {
        wp_send_json_error(['message' => $upload['error']]);
    }

    // Save URL to user meta
    $user_id = get_current_user_id();
    update_user_meta($user_id, 'profile_picture', $upload['url']);

    wp_send_json_success(['image_url' => $upload['url']]);
}
add_action('wp_ajax_change_user_password', 'handle_password_change');
function handle_password_change()
{
    if (!is_user_logged_in()) {
        wp_send_json_error(['message' => 'Unauthorized.']);
    }

    $current_password = $_POST['current_password'];
    $new_password = $_POST['new_password'];

    if (empty($current_password) || empty($new_password)) {
        wp_send_json_error(['message' => 'Both current and new passwords are required.']);
    }

    $user_id = get_current_user_id();
    $user = get_userdata($user_id);

    if (!wp_check_password($current_password, $user->user_pass, $user_id)) {
        wp_send_json_error(['message' => 'Current password is incorrect.']);
    }

    if ($current_password === $new_password) {
        wp_send_json_error(['message' => 'New password cannot be the same as the current password.']);
    }

    wp_set_password($new_password, $user_id);
    wp_logout();

    wp_send_json_success([
        'message' => 'Password updated successfully.',
        'logout_url' => site_url('/login/')
    ]);
}
function handle_forgot_password()
{
    if (!isset($_POST['user_email']) || empty($_POST['user_email'])) {
        wp_send_json_error(['message' => 'Please enter a valid email address']);
        return;
    }

    $email = sanitize_email($_POST['user_email']);
    $user = get_user_by('email', $email);

    if (!$user) {
        wp_send_json_success(['message' => 'If this email is registered, you will receive a password reset link.']);
        return;
    }

    // 1. Delete any previous password reset meta
    delete_user_meta($user->ID, 'rp_key');
    delete_user_meta($user->ID, 'password_reset_status');
    delete_user_meta($user->ID, 'rp_expiration');

    // 2. Generate a new reset key and store it
    $reset_key = get_password_reset_key($user);
    if (is_wp_error($reset_key)) {
        wp_send_json_error(['message' => 'Unable to generate reset link. Please try again later.']);
        return;
    }

    // 3. Force update the password reset key and expiration manually
    update_user_meta($user->ID, 'password_reset_status', 0); // Mark as unused
    update_user_meta($user->ID, 'rp_key', $reset_key);
    update_user_meta($user->ID, 'rp_expiration', time() + HOUR_IN_SECONDS * 24); // 24-hour expiry

    // 4. Create the reset URL
    // $reset_url = site_url("/password-reset?action=rp&key=" . urlencode($reset_key) . "&login=" . urlencode($user->user_login));
    $reset_url = site_url("/login?action=rp&key=" . urlencode($reset_key) . "&login=" . urlencode($user->user_login));


    // 5. Load and replace the email template
    $template_path = __DIR__ . '/emails/change_pwd.php';
    if (!file_exists($template_path)) {
        wp_send_json_error(['message' => 'Email template not found.']);
        return;
    }
    $email_body = file_get_contents($template_path);
    $email_body = str_replace('{{reset_link}}', esc_url($reset_url), $email_body);
    $base_url = get_template_directory_uri();
    $email_body = str_replace('{{base_url}}', $base_url, $email_body);

    // 6. Send the email
    $subject = "Password Reset Request";
    $headers = ['Content-Type: text/html; charset=UTF-8'];

    if (wp_mail($email, $subject, $email_body, $headers)) {
        wp_send_json_success(['message' => 'If this email is registered, you will receive a password reset link.']);
    } else {
        wp_send_json_error(['message' => 'Failed to send email. Please try again.']);
    }
}

add_action('wp_ajax_handle_forgot_password', 'handle_forgot_password');
add_action('wp_ajax_nopriv_handle_forgot_password', 'handle_forgot_password');
function handle_password_reset()
{
    if (!isset($_POST['new_password'], $_POST['reset_key'], $_POST['user_login'])) {
        wp_send_json_error(array('message' => 'Invalid request.'));
        return;
    }

    $user_login = sanitize_text_field($_POST['user_login']);
    $new_password = $_POST['new_password'];
    $reset_key = sanitize_text_field($_POST['reset_key']);

    // Get user by login
    $user = get_user_by('login', $user_login);
    if (!$user) {
        wp_send_json_error(array('message' => 'User not found.'));
        return;
    }

    // Validate reset key
    $check_key = check_password_reset_key($reset_key, $user->user_login);
    if (is_wp_error($check_key)) {
        wp_send_json_error(array('message' => 'The reset link is invalid or has expired'));
        return;
    }

    // Prevent using the same password
    if (wp_check_password($new_password, $user->user_pass, $user->ID)) {
        wp_send_json_error(array('message' => 'New password cannot be the same as the old password.'));
        return;
    }

    // Reset password
    reset_password($user, $new_password);

    // Delete reset key to prevent reuse
    delete_user_meta($user->ID, 'rp_key');
    delete_user_meta($user->ID, 'password_reset_status');
    delete_user_meta($user->ID, 'rp_expiration');

    wp_send_json_success(array('message' => 'Password reset successfully. You can now log in.'));
}

add_action('wp_ajax_handle_password_reset', 'handle_password_reset');
add_action('wp_ajax_nopriv_handle_password_reset', 'handle_password_reset');
function create_video_rentals_table()
{
    global $wpdb;

    $table = $wpdb->prefix . 'video_rentals';
    $charset_collate = $wpdb->get_charset_collate();

    $sql = "CREATE TABLE $table (
        id BIGINT UNSIGNED NOT NULL AUTO_INCREMENT,
        user_id BIGINT NOT NULL,
        name VARCHAR(255),
        address TEXT,
        state VARCHAR(100),
        city VARCHAR(100),
        zip VARCHAR(20),
        phone VARCHAR(50),
        card_number VARCHAR(30),
        expiry VARCHAR(10),
        cvv VARCHAR(10),
        country VARCHAR(100),
        created_at DATETIME DEFAULT CURRENT_TIMESTAMP,
        PRIMARY KEY (id)
    ) $charset_collate;";

    require_once ABSPATH . 'wp-admin/includes/upgrade.php';
    dbDelta($sql);
}
register_activation_hook(__FILE__, 'create_video_rentals_table');


//----------------------------------Rent Now---------------------------------------------------------
add_action('wp_ajax_rent_video', 'handle_rent_video');
add_action('wp_ajax_nopriv_rent_video', 'handle_rent_video');
add_action('wp_ajax_handle_rent_video', 'handle_rent_video');
add_action('wp_ajax_nopriv_handle_rent_video', 'handle_rent_video');

function handle_rent_video()
{
    if (!is_user_logged_in()) {
        wp_send_json_error(['message' => 'You must be logged in.']);
    }

    $user_id = get_current_user_id();
    $video_id = intval($_POST['video_id']);

    $vm_rental = get_post_meta($video_id, 'vm_rental', true);
    $amount = floatval($_POST['amount']);
    $affiliate_code = sanitize_text_field($_POST['affiliate_code']);

    $name = sanitize_text_field($_POST['name']);
    $address = sanitize_text_field($_POST['address']);
    $state = sanitize_text_field($_POST['state']);
    $city = sanitize_text_field($_POST['city']);
    $country = sanitize_text_field($_POST['country']);
    $zip = sanitize_text_field($_POST['zip']);
    $phone = sanitize_text_field($_POST['phone']);
    $package_type = isset($_POST['package_types']) ? sanitize_text_field($_POST['package_types']) : '';


    $card_number = sanitize_text_field($_POST['card_number']);
    $expiry = sanitize_text_field($_POST['expiry']); // MM/YY
    $cvv = sanitize_text_field($_POST['cvv']);

    // ✅ Validate and format expiry
    if (strpos($expiry, '/') === false) {
        wp_send_json_error(['message' => 'Invalid expiry format']);
    }

    list($exp_month, $exp_year) = array_map('trim', explode('/', $expiry));
    $exp_month = str_pad($exp_month, 2, '0', STR_PAD_LEFT);
    $exp_year = (strlen($exp_year) === 2) ? ('20' . $exp_year) : $exp_year;
    $xExp = $exp_month . substr($exp_year, -2); // MMYY format

    // ✅ Cardknox API call
    $cardknox_key = 'spericorndev272f621906bc45d4871c84f57f7b99b2'; // Replace with your test/sandbox key $xExp $amount

    $payload = [
        'xKey' => $cardknox_key,
        'xVersion' => '4.5.0',
        'xCommand' => 'cc:Sale',
        'xAmount' => 10,
        'xCardNum' => $card_number,
        'xExp' => '1026',
        'xCVV' => $cvv,
        'xEmail' => wp_get_current_user()->user_email,
        'xBillFirstName' => $name,
        'xBillZip' => $zip,
    ];


    $response = wp_remote_post('https://x1.cardknox.com/gateway', [
        'body' => $payload
    ]);

    if (is_wp_error($response)) {
        wp_send_json_error(['message' => 'Cardknox error: ' . $response->get_error_message()]);
    }

    $body = wp_remote_retrieve_body($response);

    // Log raw response
    error_log('Raw Response from Cardknox: ' . $body);

    // Parse response
    parse_str($body, $parsed);

    // Log parsed response
    if (!empty($parsed)) {
        foreach ($parsed as $key => $value) {
            error_log($key . ': ' . $value);
        }
    } else {
        error_log('Cardknox response parsing failed or returned empty data.');
    }

    // Validate transaction result
    if (!isset($parsed['xResult']) || $parsed['xResult'] !== 'A') {
        wp_send_json_error(['message' => $parsed['xError'] ?? 'Transaction failed']);
    }

    // ✅ Save successful transaction
    global $wpdb;
    $table = $wpdb->prefix . 'video_rentals';

    // Fetch all published videos
    $args = [
        'post_type' => 'vm_video',
        'posts_per_page' => -1,
        'post_status' => 'publish'
    ];

    $video_query = new WP_Query($args);

    if ($video_query->have_posts()) {
        while ($video_query->have_posts()) {
            $video_query->the_post();
            $video_id = get_the_ID();
            $vm_rental = get_post_meta($video_id, 'vm_rental', true);

            $wpdb->insert($table, [
                'user_id' => $user_id,
                'video_id' => $video_id,
                'cardknox_transaction_id' => $parsed['xRefNum'] ?? '',
                'amount' => $amount,
                'rental_duration' => $vm_rental,
                'name' => $name,
                'address' => $address,
                'state' => $state,
                'city' => $city,
                'country' => $country,
                'zip' => $zip,
                'phone' => $phone,
                'license_type' => $package_type,
                'affiliate_code' => $affiliate_code,
                'rented_at' => current_time('mysql'),
            ]);
        }
        wp_reset_postdata();
    }


    $rental_id = $wpdb->insert_id;

    // Insert into transactions table
    $transactions_table = $wpdb->prefix . 'video_transactions';
    $wpdb->insert($transactions_table, [
        'rental_id' => $rental_id,
        'transaction_id' => $parsed['xRefNum'] ?? '',
        'amount' => $amount,
        'license' => 'standard',
        'created_at' => current_time('mysql'),
    ]);
    // Update user meta only if affiliate_code is not empty
    update_user_meta($user_id, 'referred_by_affiliate', null);

    // Load the email template
    $template_path = __DIR__ . '/emails/purchase_confirmation.php';
    if (!file_exists($template_path)) {
        wp_send_json_error(['message' => 'Email template not found.']);
    }
    $verification_link = site_url('/profile/');
    $email_body = file_get_contents($template_path);
    $base_url = get_template_directory_uri();
    $email = wp_get_current_user()->user_email;
    $display_name = wp_get_current_user()->display_name;

    // Replace placeholders with dynamic data
    $email_body = str_replace('{{verification_link}}', esc_url($verification_link), $email_body);
    $email_body = str_replace('{{display_name}}', esc_html($display_name), $email_body);
    $email_body = str_replace('{{base_url}}', $base_url, $email_body);

    // Send email
    $subject = "Thank You for Your Purchase";
    $headers = ['Content-Type: text/html; charset=UTF-8'];

    if (!wp_mail($email, $subject, $email_body, $headers)) {
        wp_send_json_error(['message' => 'Failed to send verification email.']);
    }

    // 🎉 Success
    wp_send_json_success(['message' => 'Payment successful! Video added to your rentals.']);

}



// function handle_rent_video()
// {
//     if (!is_user_logged_in()) {
//         wp_send_json_error(['message' => 'You must be logged in.']);
//     }

//     $user_id = get_current_user_id();
//     $video_id = intval($_POST['video_id']);
//     $amount = floatval($_POST['amount']);

//     $name = sanitize_text_field($_POST['name']);
//     $address = sanitize_text_field($_POST['address']);
//     $state = sanitize_text_field($_POST['state']);
//     $city = sanitize_text_field($_POST['city']);
//     $country = sanitize_text_field($_POST['country']);
//     $zip = sanitize_text_field($_POST['zip']);
//     $phone = sanitize_text_field($_POST['phone']);
//     $card_number = sanitize_text_field($_POST['card_number']);
//     $expiry = sanitize_text_field($_POST['expiry']);
//     $cvv = sanitize_text_field($_POST['cvv']);

//     if (strpos($expiry, '/') === false) {
//         wp_send_json_error(['message' => 'Invalid expiry format']);
//     }
//     list($exp_month, $exp_year) = array_map('trim', explode('/', $expiry));
//     $exp_month = str_pad($exp_month, 2, '0', STR_PAD_LEFT);
//     $exp_year = (strlen($exp_year) === 2) ? ('20' . $exp_year) : $exp_year;

//     $cardknox_key = 'PKZ8xxREPLACE_WITH_YOUR_KEY';

//     $payload = [
//         'xKey' => $cardknox_key,
//         'xVersion' => '4.5.0',
//         'xCommand' => 'cc:sale',
//         'xAmount' => $amount,
//         'xCardNum' => $card_number,
//         'xExp' => $exp_month . $exp_year,
//         'xCVV' => $cvv,
//         'xEmail' => wp_get_current_user()->user_email,
//         'xBillFirstName' => $name,
//         'xBillZip' => $zip,
//     ];

//     $response = wp_remote_post('https://x1.cardknox.com/gateway', [
//         'body' => $payload
//     ]);

//     if (is_wp_error($response)) {
//         wp_send_json_error(['message' => 'Payment failed.']);
//     }

//     $body = wp_remote_retrieve_body($response);
//     parse_str($body, $parsed);

//     if (!isset($parsed['xResult']) || $parsed['xResult'] !== 'Approved') {
//         wp_send_json_error(['message' => $parsed['xMessage'] ?? 'Transaction failed']);
//     }

//     // Insert into rentals
//     global $wpdb;
//     $rentals_table = $wpdb->prefix . 'video_rentals';
//     $rented_at = current_time('mysql');
//     $rental_days = get_option('rental_period_days', 7);

//     $wpdb->insert($rentals_table, [
//         'user_id' => $user_id,
//         'video_id' => $video_id,
//         'cardknox_transaction_id' => $parsed['xRefNum'],
//         'amount' => $amount,
//         'rental_duration' => $rental_days,
//         'name' => $name,
//         'address' => $address,
//         'state' => $state,
//         'city' => $city,
//         'country' => $country,
//         'zip' => $zip,
//         'phone' => $phone,
//         'rented_at' => $rented_at,
//     ]);

//     $rental_id = $wpdb->insert_id;

//     // Insert into transaction table
//     $transactions_table = $wpdb->prefix . 'video_transactions';
//     $wpdb->insert($transactions_table, [
//         'rental_id' => $rental_id,
//         'transaction_id' => $parsed['xRefNum'],
//         'amount' => $amount,
//         'license' => 'standard',
//         'created_at' => current_time('mysql'),
//     ]);

//     wp_send_json_success([
//         'message' => 'Payment successful!',
//         'transaction_id' => $parsed['xRefNum']
//     ]);
// }


//----------------------Common Rental Settings--------------------------------------------
// 1. Add Admin Menu Page
add_action('admin_menu', function () {
    add_menu_page(
        'Rental Settings',        // Page title
        'Rental Settings',        // Menu title
        'manage_options',         // Capability
        'rental-settings',        // Menu slug
        'rental_settings_page',   // Callback function
        'dashicons-controls-repeat', // Icon
        100
    );
});

// 2. Admin Page Callback
function rental_settings_page()
{
    ?>
    <div class="wrap">
        <h1>Rental Settings</h1>
        <form method="post" action="options.php">
            <?php
            settings_fields('rental_settings_group');
            do_settings_sections('rental-settings');
            submit_button();
            ?>
        </form>
    </div>
    <?php
}

// 3. Register Settings and Fields
add_action('admin_init', function () {
    // Register options
    register_setting('rental_settings_group', 'individual_price');
    register_setting('rental_settings_group', 'family_price');
    register_setting('rental_settings_group', 'rental_period_days'); // ✅ new setting

    // Add section
    add_settings_section(
        'rental_main_section',
        'Rental Options',
        null,
        'rental-settings'
    );

    // Individual price field
    add_settings_field(
        'individual_price',
        'Individual Price ($)',
        function () {
            $value = esc_attr(get_option('individual_price', '18'));
            echo "<input type='number' name='individual_price' value='{$value}' min='0' step='0.01'>";
        },
        'rental-settings',
        'rental_main_section'
    );

    // Family price field
    add_settings_field(
        'family_price',
        'Family Price ($)',
        function () {
            $value = esc_attr(get_option('family_price', '36'));
            echo "<input type='number' name='family_price' value='{$value}' min='0' step='0.01'>";
        },
        'rental-settings',
        'rental_main_section'
    );

    // ✅ Rental period field
    add_settings_field(
        'rental_period_days',
        'Rental Period (in days)',
        function () {
            $value = esc_attr(get_option('rental_period_days', '7'));
            echo "<input type='number' name='rental_period_days' value='{$value}' min='1' step='1'>";
        },
        'rental-settings',
        'rental_main_section'
    );
});


add_action('wp_ajax_get_package_price', 'get_package_price_ajax');
add_action('wp_ajax_nopriv_get_package_price', 'get_package_price_ajax');


function get_package_price_ajax()
{
    $type = sanitize_text_field($_GET['type']);

    if ($type === 'single') {
        $amount = get_option('individual_price', 18);
    } elseif ($type === 'family') {
        $amount = get_option('family_price', 36);
    } else {
        wp_send_json_error(['message' => 'Invalid package type']);
    }

    wp_send_json_success(['amount' => $amount]);
}


add_action('wp_ajax_submit_contact_form', 'handle_ajax_contact_form');
add_action('wp_ajax_nopriv_submit_contact_form', 'handle_ajax_contact_form');

function handle_ajax_contact_form()
{
    // Sanitize input values based on new field names
    $first_name = sanitize_text_field($_POST['first_name'] ?? '');
    $email = sanitize_email($_POST['email'] ?? '');
    $phone = sanitize_text_field($_POST['phone'] ?? '');
    $subject = sanitize_text_field($_POST['subject'] ?? '');
    $description = sanitize_textarea_field($_POST['description'] ?? '');

    // Validate required fields (optional fallback if JS validation fails)
    if (empty($first_name) || empty($email) || empty($phone) || empty($description)) {
        wp_send_json_error(['success' => false, 'message' => 'All fields are required.']);
    }

    // Admin email
    $admin_email = get_option('admin_email');
    $headers = ['Content-Type: text/html; charset=UTF-8'];

    // Load the email template
    $template_path = __DIR__ . '/emails/contact-email.php';
    if (!file_exists($template_path)) {
        wp_send_json_error(['success' => false, 'message' => 'Contact email template not found.']);
    }

    $admin_message = file_get_contents($template_path);
    $base_url = get_template_directory_uri();
    // Set default subject if empty
    if (empty($subject)) {
        $email_subject = "New contact form submission from $first_name";
    } else {
        $email_subject = sanitize_text_field($_POST['subject'] ?? '');
    }


    // Replace template placeholders
    $admin_message = str_replace('{{display_name}}', esc_html($first_name), $admin_message);
    $admin_message = str_replace('{{email}}', esc_html($email), $admin_message);
    $admin_message = str_replace('{{phone_no}}', esc_html($phone), $admin_message);
    $admin_message = str_replace('{{subject}}', esc_html($subject), $admin_message);
    $admin_message = str_replace('{{message}}', esc_html($description), $admin_message);
    $admin_message = str_replace('{{base_url}}', esc_url($base_url), $admin_message);

    // Send the email
    $sent = wp_mail($admin_email, $email_subject, $admin_message, $headers);

    if ($sent) {
        wp_send_json_success(['success' => true, 'message' => 'Thank you for contacting us. We will be in touch shortly!']);
    } else {
        wp_send_json_error(['success' => false, 'message' => 'Failed to send the message. Please try again later.']);
    }

    wp_die();
}

function create_video_transactions_table()
{
    global $wpdb;
    $table = $wpdb->prefix . 'video_transactions';

    $charset_collate = $wpdb->get_charset_collate();

    $sql = "CREATE TABLE $table (
        id BIGINT(20) UNSIGNED NOT NULL AUTO_INCREMENT,
        rental_id BIGINT(20) UNSIGNED NOT NULL,
        transaction_id VARCHAR(100),
        amount DECIMAL(10,2),
        license VARCHAR(50) DEFAULT 'standard',
        created_at DATETIME DEFAULT CURRENT_TIMESTAMP,
        PRIMARY KEY (id),
        KEY rental_id (rental_id)
    ) $charset_collate;";

    require_once ABSPATH . 'wp-admin/includes/upgrade.php';
    dbDelta($sql);
}
register_activation_hook(__FILE__, 'create_video_transactions_table');

//-----------------------Affiliate-----------------------------------------------------------


add_action('init', function () {
    if (isset($_GET['aff'])) {
        setcookie(
            'affiliate_ref',
            sanitize_text_field($_GET['aff']),
            time() + DAY_IN_SECONDS, // 1 day
            COOKIEPATH,
            COOKIE_DOMAIN,
            is_ssl(),
            true
        );
    }
});


// Show affiliate code field on user edit page
add_action('show_user_profile', 'add_affiliate_code_field');
add_action('edit_user_profile', 'add_affiliate_code_field');

function add_affiliate_code_field($user)
{
    if (!current_user_can('edit_users'))
        return;
    ?>
    <h3>Affiliate Settings</h3>
    <table class="form-table">
        <tr>
            <th><label for="affiliate_code">Affiliate Code</label></th>
            <td>
                <input type="text" name="affiliate_code" id="affiliate_code"
                    value="<?php echo esc_attr(get_user_meta($user->ID, 'affiliate_code', true)); ?>"
                    class="regular-text" />
                <p class="description">Set a custom affiliate code for this user (used in URLs like <code>?aff=code</code>).
                </p>
            </td>
        </tr>
    </table>
    <?php
}

// Save affiliate code field
add_action('personal_options_update', 'save_affiliate_code_field');
add_action('edit_user_profile_update', 'save_affiliate_code_field');

function save_affiliate_code_field($user_id)
{
    if (!current_user_can('edit_users'))
        return;

    if (isset($_POST['affiliate_code'])) {
        $new_code = sanitize_text_field($_POST['affiliate_code']);
        update_user_meta($user_id, 'affiliate_code', $new_code);
    }
}


add_action('admin_menu', 'register_affiliate_sales_menu');

function register_affiliate_sales_menu()
{
    add_menu_page(
        'Affiliate Sales',
        'Affiliate Sales',
        'manage_options',
        'affiliate-sales',
        'render_affiliate_sales_page',
        'dashicons-chart-line',
        26
    );
}

function render_affiliate_sales_page()
{
    global $wpdb;

    $per_page = 20;
    $paged = isset($_GET['paged']) ? max(1, intval($_GET['paged'])) : 1;
    $offset = ($paged - 1) * $per_page;

    $where = "WHERE vr.affiliate_code IS NOT NULL AND vr.affiliate_code != ''";
    $params = [];

    // if (!empty($_GET['f_021a'])) {
    //     $where .= " AND vr.affiliate_code LIKE %s";
    //     $params[] = '%' . sanitize_text_field($_GET['f_021a']) . '%';
    // }

    if (!empty($_GET['user'])) {
        $where .= " AND u.display_name LIKE %s";
        $params[] = '%' . sanitize_text_field($_GET['user']) . '%';
    }

    if (!empty($_GET['affiliate'])) {
        $where .= " AND vr.affiliate_code = %s";
        $params[] = sanitize_text_field($_GET['affiliate']);
    }

    if (!empty($_GET['start_date']) && !empty($_GET['end_date'])) {
        $where .= " AND DATE(vr.rented_at) BETWEEN %s AND %s";
        $params[] = sanitize_text_field($_GET['start_date']);
        $params[] = sanitize_text_field($_GET['end_date']);
    }

    if (!empty($_GET['product'])) {
        $where .= " AND p.post_title LIKE %s";
        $params[] = '%' . sanitize_text_field($_GET['product']) . '%';
    }

    $base_query = "
        FROM {$wpdb->prefix}video_rentals vr
        LEFT JOIN {$wpdb->prefix}users u ON vr.user_id = u.ID
        LEFT JOIN {$wpdb->prefix}posts p ON vr.video_id = p.ID
        LEFT JOIN {$wpdb->prefix}video_transactions vt ON vr.id = vt.rental_id
        $where
    ";

    $total = $wpdb->get_var($wpdb->prepare("SELECT COUNT(*) $base_query", ...$params));

    $results = $wpdb->get_results($wpdb->prepare(
        "SELECT vr.*, vt.transaction_id, vt.created_at, vt.amount as transaction_amount, 
                u.display_name as user_name, p.post_title as product_name
         $base_query
         ORDER BY vt.created_at DESC
         LIMIT %d OFFSET %d",
        ...array_merge($params, [$per_page, $offset])
    ));

    $total_pages = ceil($total / $per_page);

    echo '<div class="wrap">';
    echo '<h1>Affiliate Sales</h1>';
    echo '<form method="get" class="affiliate-filters">';
    echo '<input type="hidden" name="page" value="affiliate-sales" />';
    // echo '<input type="text" name="f_021a" placeholder="Affiliate Code (F_021a)" value="' . esc_attr($_GET['f_021a'] ?? '') . '" /> ';
    echo '<input type="text" name="user" placeholder="User Name" value="' . esc_attr($_GET['user'] ?? '') . '" /> ';
    echo '<input type="text" name="affiliate" placeholder="Affiliate Code" value="' . esc_attr($_GET['affiliate'] ?? '') . '" /> ';
    echo '<input type="text" name="product" placeholder="Product Name" value="' . esc_attr($_GET['product'] ?? '') . '" /> ';
    echo '<input type="date" name="start_date" value="' . esc_attr($_GET['start_date'] ?? '') . '" /> to ';
    echo '<input type="date" name="end_date" value="' . esc_attr($_GET['end_date'] ?? '') . '" /> ';
    echo '<input type="submit" class="button button-primary" value="Filter" />';
    echo '<a href="' . admin_url('admin.php?page=affiliate-sales') . '" class="button">Reset</a>';
    echo '</form>';

    echo '<table class="widefat striped">';
    echo '<thead><tr><th>Affiliate Code</th><th>User</th><th>Product</th><th>Amount</th><th>Transaction ID</th><th>Date/Time</th><th>Invoice</th></tr></thead><tbody>';

    if ($results) {
        foreach ($results as $row) {
            echo '<tr>';
            echo '<td>' . esc_html($row->affiliate_code) . '</td>';
            echo '<td>' . esc_html($row->user_name) . '</td>';
            echo '<td>' . esc_html($row->product_name) . '</td>';
            echo '<td>' . esc_html(number_format($row->amount, 2)) . '</td>';
            echo '<td>' . esc_html($row->transaction_id) . '</td>';
            echo '<td>' . esc_html($row->created_at) . '</td>';
            // echo '<td><a href="' . admin_url('admin-post.php?action=download_invoice&rid=' . $row->id) . '" class="button">Download</a></td>';
            $code = esc_attr($row->affiliate_code);
            echo '<td><button class="button button-primary download-invoice-btn" data-code="' . $code . '">Download Invoice</button></td>';
            echo '</tr>';
        }
    } else {
        echo '<tr><td colspan="7">No results found.</td></tr>';
    }
    echo '</tbody></table>';

    // Pagination
    if ($total_pages > 1) {
        echo '<div class="tablenav"><div class="tablenav-pages">';
        $current_url = remove_query_arg('paged');
        for ($i = 1; $i <= $total_pages; $i++) {
            if ($i == $paged) {
                echo "<span class='page-numbers current'>$i</span> ";
            } else {
                echo '<a class="page-numbers" href="' . esc_url(add_query_arg('paged', $i, $current_url)) . '">' . $i . '</a> ';
            }
        }
        echo '</div></div>';
    }

    echo '</div>';
}
function enqueue_invoice_download_scripts()
{
    // html2pdf external library
    wp_enqueue_script(
        'html2pdf-js',
        'https://cdnjs.cloudflare.com/ajax/libs/html2pdf.js/0.10.1/html2pdf.bundle.min.js',
        [],
        null,
        true
    );

    // Your custom script
    wp_enqueue_script(
        'download-invoice',
        get_template_directory_uri() . '/js/download-invoice.js',
        ['jquery', 'html2pdf-js'],
        time(),
        true
    );

    // Pass PHP variable to JS
    wp_localize_script('download-invoice', 'download_invoice_vars', [
        'invoice_template_url' => get_template_directory_uri() . '/invoices/affiliate-invoice.php',
        'trans_invoice_template_url' => get_template_directory_uri() . '/invoices/transaction_invoice.php',
    ]);
}
add_action('wp_enqueue_scripts', 'enqueue_invoice_download_scripts'); // For frontend
add_action('admin_enqueue_scripts', 'enqueue_invoice_download_scripts'); // For admin



add_action('admin_menu', function () {
    add_menu_page(
        'Transactions',
        'Transactions',
        'manage_options',
        'transaction-listing',
        'render_transaction_listing_page',
        'dashicons-list-view',
        25
    );
});
function render_transaction_listing_page()
{
    global $wpdb;

    $per_page = 20;
    $paged = max(1, intval($_GET['paged'] ?? 1));
    $offset = ($paged - 1) * $per_page;

    // Build WHERE clause based on filters
    $where = "WHERE 1=1";
    $params = [];

    if ($f = sanitize_text_field($_GET['f_022a'] ?? '')) {
        $where .= " AND t.transaction_id LIKE %s";
        $params[] = "%{$f}%";
    }
    if ($u = sanitize_text_field($_GET['user'] ?? '')) {
        $where .= " AND u.display_name LIKE %s";
        $params[] = "%{$u}%";
    }
    if (!empty($_GET['start_date']) && !empty($_GET['end_date'])) {
        $where .= " AND DATE(t.created_at) BETWEEN %s AND %s";
        $params[] = $_GET['start_date'];
        $params[] = $_GET['end_date'];
    }
    if ($type = sanitize_text_field($_GET['type'] ?? '')) {
        if ($type === 'affiliate') {
            $where .= " AND r.affiliate_code != ''";
        } elseif ($type === 'regular') {
            $where .= " AND (r.affiliate_code = '' OR r.affiliate_code IS NULL)";
        }
    }
    if ($p = sanitize_text_field($_GET['product'] ?? '')) {
        $where .= " AND p.post_title LIKE %s";
        $params[] = "%{$p}%";
    }

    // Base query with joins
    $base = "
        FROM {$wpdb->prefix}video_transactions t
        LEFT JOIN {$wpdb->prefix}video_rentals r ON t.rental_id = r.id
        LEFT JOIN {$wpdb->prefix}users u ON r.user_id = u.ID
        LEFT JOIN {$wpdb->prefix}posts p ON r.video_id = p.ID
        $where
    ";

    $total = $wpdb->get_var($wpdb->prepare("SELECT COUNT(*) $base", ...$params));
    $rows = $wpdb->get_results($wpdb->prepare("
        SELECT t.*, u.display_name AS user_name, p.post_title AS product_name,
               r.affiliate_code
        $base
        ORDER BY t.created_at DESC
        LIMIT %d OFFSET %d
    ", ...array_merge($params, [$per_page, $offset])));

    $total_pages = ceil($total / $per_page);

    // Filters form
    echo '<div class="wrap"><h1>Transactions</h1>';
    echo '<form method="get">';
    echo '<input type="hidden" name="page" value="transaction-listing" />';
    echo '<input placeholder="Trans ID (F_022a)" name="f_022a" value="' . esc_attr($_GET['f_022a'] ?? '') . '" />';
    echo '<input placeholder="User Name" name="user" value="' . esc_attr($_GET['user'] ?? '') . '" />';
    echo '<input type="date" name="start_date" value="' . esc_attr($_GET['start_date'] ?? '') . '" />';
    echo ' to <input type="date" name="end_date" value="' . esc_attr($_GET['end_date'] ?? '') . '" />';
    echo '<select name="type">
            <option value="">All</option>
            <option value="affiliate" ' . selected($_GET['type'] ?? '', 'affiliate', false) . '>Affiliate</option>
            <option value="regular" ' . selected($_GET['type'] ?? '', 'regular', false) . '>Regular</option>
          </select>';
    echo '<input placeholder="Product Name" name="product" value="' . esc_attr($_GET['product'] ?? '') . '" />';
    echo '<input type="submit" class="button button-primary" value="Filter" />';
    echo '<a href="' . admin_url('admin.php?page=transaction-listing') . '" class="button">Reset</a>';
    echo '</form>';

    // Table header
    echo '<table class="widefat striped"><thead><tr>
        <th>User</th><th>Date & Time</th><th>Product</th><th>F_022</th>
        <th>Amount</th><th>Trans ID</th><th>Type</th><th>Invoice</th></tr></thead><tbody>';

    if ($rows)
        foreach ($rows as $r) {
            $link_user = admin_url('user-edit.php?user_id=' . $r->rental_id);
            $affiliate_link = $r->affiliate_code
                ? admin_url('admin.php?page=affiliate-sales&affiliate=' . urlencode($r->affiliate_code))
                : '';

            echo '<tr>';
            echo '<td><a href="' . esc_url($link_user) . '">' . esc_html($r->user_name) . '</a></td>';
            echo '<td>' . esc_html($r->created_at) . '</td>';
            echo '<td>' . esc_html($r->product_name) . '</td>';
            echo '<td><code>' . esc_html($r->transaction_id) . '</code></td>';
            echo '<td>' . esc_html(number_format($r->amount, 2)) . '</td>';
            echo '<td>' . esc_html($r->transaction_id) . '</td>';
            echo '<td>' . ($affiliate_link
                ? '<a href="' . esc_url($affiliate_link) . '">Affiliate</a>'
                : 'Regular') . '</td>';
            echo '<td><button class="button download-invoice-btn-txn" data-tid="' . esc_attr($r->rental_id) . '">Download Invoice</button></td>';
            echo '</tr>';
        } else {
        echo '<tr><td colspan="8">No transactions found.</td></tr>';
    }

    echo '</tbody></table>';

    // Pagination
    if ($total_pages > 1) {
        echo '<div class="tablenav"><div class="tablenav-pages">';
        $base_url = remove_query_arg('paged');
        for ($i = 1; $i <= $total_pages; $i++) {
            if ($i === $paged)
                echo "<span class='page-numbers current'>$i</span> ";
            else
                echo '<a href="' . esc_url(add_query_arg('paged', $i, $base_url)) . '" class="page-numbers">' . $i . '</a> ';
        }
        echo '</div></div>';
    }

    echo '</div>';
}

//-------------------------Generate Afiiliate code---------------------------------
register_activation_hook(__FILE__, 'create_affiliate_code_table');
add_action('admin_menu', function () {
    add_menu_page(
        'Affiliate Codes',
        'Affiliates',
        'manage_options',
        'affiliate-codes',
        'render_affiliate_admin_page',
        'dashicons-admin-users',
        30
    );
});

function render_affiliate_admin_page()
{
    global $wpdb;
    $table = $wpdb->prefix . 'affiliate_codes';

    // Handle form submission
    if (isset($_POST['affiliate_code'])) {
        $code = sanitize_text_field($_POST['affiliate_code']);
        if ($code) {
            $wpdb->insert($table, ['code' => $code]);
            echo '<div class="notice notice-success"><p>Affiliate code added!</p></div>';
        }
    }

    // Fetch all affiliate codes
    $codes = $wpdb->get_results("SELECT * FROM $table ORDER BY id DESC");
    ?>
    <div class="wrap">
        <h1>Affiliate Codes</h1>
        <form method="post">
            <input type="text" name="affiliate_code" placeholder="Enter new code" required />
            <input type="submit" class="button button-primary" value="Add Code">
        </form>
        <hr>
        <h2>Existing Codes</h2>
        <table class="widefat">
            <thead>
                <tr>
                    <th>Code</th>
                    <th>Share Link</th>
                    <th>Created</th>
                </tr>
            </thead>
            <tbody>
                <?php foreach ($codes as $row): ?>
                    <tr>
                        <td><strong><?php echo esc_html($row->code); ?></strong></td>
                        <td><a href="<?php echo esc_url(home_url('/?aff=' . $row->code)); ?>"
                                target="_blank"><?php echo esc_url(home_url('/?aff=' . $row->code)); ?></a></td>
                        <td><?php echo esc_html($row->created_at); ?></td>
                    </tr>
                <?php endforeach; ?>
            </tbody>
        </table>
    </div>
    <?php
}

add_action('user_register', function ($user_id) {
    if (isset($_COOKIE['affiliate_ref'])) {
        update_user_meta($user_id, 'referred_by_affiliate', sanitize_text_field($_COOKIE['affiliate_ref']));
    }
});