<?php

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

// phpcs:disable WordPress.DB.DirectDatabaseQuery.DirectQuery,WordPress.DB.DirectDatabaseQuery.NoCaching

/**
 * Fired during plugin activation
 *
 * @link       https://webequipe.com
 * @since      1.0.0
 *
 * @package    Webequipe_Spin_Win_Wheel
 * @subpackage Webequipe_Spin_Win_Wheel/includes
 */

/**
 * Fired during plugin activation.
 *
 * This class defines all code necessary to run during the plugin's activation.
 *
 * @since      1.0.0
 * @package    Webequipe_Spin_Win_Wheel
 * @subpackage Webequipe_Spin_Win_Wheel/includes
 * @author     Webequipe <support@webequipe.com>
 */

/**
 * Generate a persistent 8-digit unique ID for a spin item.
 *
 * @return string 8-digit numeric string.
 */
function webequipe_sww_generate_spin_item_unique_id() {
	$min = 10000000;
	$max = 99999999;
	return (string) wp_rand( $min, $max );
}

/**
 * Format a MySQL datetime string for admin list/detail display.
 *
 * Uses mysql2date() when available (correct timezone handling). Falls back to strtotime + wp_date.
 * Returns an em dash for empty or invalid MySQL zero dates (avoids "November 30, -0001" style output).
 *
 * @param mixed $raw_date Value from DB (string, null, or numeric timestamp as string).
 * @return string Formatted date or "—".
 */
function webequipe_sww_format_mysql_datetime_display( $raw_date ) {
	if ( null === $raw_date ) {
		return '—';
	}

	$raw = trim( (string) $raw_date );
	if ( '' === $raw ) {
		return '—';
	}

	// MySQL zero / invalid calendar dates.
	if ( preg_match( '/^0000-00-00/', $raw ) ) {
		return '—';
	}

	$date_format = get_option( 'date_format' );

	// Unix timestamp stored as a 10-digit string (seconds since epoch).
	if ( ctype_digit( $raw ) && 10 === strlen( $raw ) ) {
		$ts = (int) $raw;
		if ( $ts > 0 ) {
			return wp_date( $date_format, $ts );
		}
		return '—';
	}

	if ( function_exists( 'mysql2date' ) ) {
		$formatted = mysql2date( $date_format, $raw );
		if ( is_string( $formatted ) && '' !== $formatted ) {
			return $formatted;
		}
	}

	$ts = strtotime( $raw );
	if ( false !== $ts ) {
		return wp_date( $date_format, $ts );
	}

	return '—';
}

/**
 * Get the number of times a spin item has already won (for winner selection logic).
 *
 * @param int    $spin_id            Spin (wheel) ID.
 * @param string $spin_item_unique_id Spin item unique ID.
 * @return int Win count.
 */
function webequipe_sww_get_win_count_by_item( $spin_id, $spin_item_unique_id ) {
	if ( empty( $spin_item_unique_id ) || $spin_id < 1 ) {
		return 0;
	}
	global $wpdb;
	return (int) $wpdb->get_var(
		$wpdb->prepare(
			"SELECT COUNT(*) FROM {$wpdb->prefix}spin_emails WHERE spin_id = %d AND spin_item_unique_id = %s",
			$spin_id,
			$spin_item_unique_id
		)
	);
}

/**
 * Insert a new address
 *
 * @param array $args
 *
 * @return int|WP_Error
 */

function webequipe_sww_insert_spin($args = [])
{
    global $wpdb;

    if (empty($args['spin_title'])) {
        return new \WP_Error('no-name', __('You must provide a name.', 'webequipe-spin-win-wheel'));
    }

    $defaults = [
        'spin_title' => '',
        'created_by' => get_current_user_id(),
        'created_at' => current_time('mysql'),
    ];

    $data = wp_parse_args($args, $defaults);

    if (isset($data['id'])) {
        $id = $data['id'];
        unset($data['id']);

        $updated = $wpdb->update(
            $wpdb->prefix . 'spin_posts',
            $data,
            ['id' => $id],
            [
                '%s',
                '%s',
                '%s',
                '%s',
                '%s',
                '%s',
                '%s',
                '%s',
                '%s',
                '%s',
            ],
            ['%d']
        );

        return $updated;
    } else {
        $inserted = $wpdb->insert(
            $wpdb->prefix . 'spin_posts',
            $data,
            [
                '%s',
                '%s',
                '%s',
                '%s',
                '%s',
                '%s',
                '%s',
                '%s',
                '%s',
                '%s',
                '%s',
                '%s',
            ]
        );

        if (!$inserted) {
            return new \WP_Error('failed-to-insert', __('Failed to insert data', 'webequipe-spin-win-wheel'));
        }

        return $wpdb->insert_id;
    }
}



/**
 * Fetch spins (PHPCS-compliant)
 */
/**
 * Fetch spins.
 *
 * @param array $args Query arguments.
 * @return array List of spins.
 */
function webequipe_sww_get_spins($args = [])
{
    global $wpdb;

    $defaults = [
        'number' => 20,
        'offset' => 0,
        'orderby' => 'id',
        'order' => 'DESC',
    ];

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

    // Whitelist and sanitize ORDER BY fields.
    $allowed_orderby = ['id', 'created_at', 'spin_title'];
    $allowed_order = ['ASC', 'DESC'];

    // Whitelist validation ensures these are safe identifiers.
    $orderby = in_array($args['orderby'], $allowed_orderby, true) ? $args['orderby'] : 'id';
    $order = in_array(strtoupper($args['order']), $allowed_order, true) ? strtoupper($args['order']) : 'DESC';

    $offset = (int) $args['offset'];
    $number = (int) $args['number'];

    // Prepare the query from hardcoded strings, only values use placeholders.
    switch ( $orderby ) {
        case 'created_at':
            if ( 'ASC' === $order ) {
                return $wpdb->get_results(
                    $wpdb->prepare(
                        "SELECT * FROM {$wpdb->prefix}spin_posts WHERE deleted != 1 ORDER BY created_at ASC LIMIT %d, %d",
                        $offset,
                        $number
                    )
                );
            }
            return $wpdb->get_results(
                $wpdb->prepare(
                    "SELECT * FROM {$wpdb->prefix}spin_posts WHERE deleted != 1 ORDER BY created_at DESC LIMIT %d, %d",
                    $offset,
                    $number
                )
            );
        case 'spin_title':
            if ( 'ASC' === $order ) {
                return $wpdb->get_results(
                    $wpdb->prepare(
                        "SELECT * FROM {$wpdb->prefix}spin_posts WHERE deleted != 1 ORDER BY spin_title ASC LIMIT %d, %d",
                        $offset,
                        $number
                    )
                );
            }
            return $wpdb->get_results(
                $wpdb->prepare(
                    "SELECT * FROM {$wpdb->prefix}spin_posts WHERE deleted != 1 ORDER BY spin_title DESC LIMIT %d, %d",
                    $offset,
                    $number
                )
            );
        case 'id':
        default:
            if ( 'ASC' === $order ) {
                return $wpdb->get_results(
                    $wpdb->prepare(
                        "SELECT * FROM {$wpdb->prefix}spin_posts WHERE deleted != 1 ORDER BY id ASC LIMIT %d, %d",
                        $offset,
                        $number
                    )
                );
            }
            return $wpdb->get_results(
                $wpdb->prepare(
                    "SELECT * FROM {$wpdb->prefix}spin_posts WHERE deleted != 1 ORDER BY id DESC LIMIT %d, %d",
                    $offset,
                    $number
                )
            );
    }
}




/**
 * Fetch all spins.
 *
 * @return array List of spins.
 */
function webequipe_sww_get_all_spins()
{
    global $wpdb;

    $defaults = [
        'number' => 1000,
        'offset' => 0,
        'orderby' => 'id',
        'order' => 'DESC',
    ];

    $args = wp_parse_args([], $defaults);

    // Whitelist and sanitize sortable fields.
    $allowed_orderby = ['id', 'created_at', 'spin_title'];
    $allowed_order = ['ASC', 'DESC'];

    // Whitelist validation ensures these are safe identifiers.
    $orderby = in_array($args['orderby'], $allowed_orderby, true) ? $args['orderby'] : 'id';
    $order = in_array(strtoupper($args['order']), $allowed_order, true) ? strtoupper($args['order']) : 'DESC';

    $offset = (int) $args['offset'];
    $number = (int) $args['number'];

    // Prepare the query from hardcoded strings, only values use placeholders.
    switch ( $orderby ) {
        case 'created_at':
            if ( 'ASC' === $order ) {
                return $wpdb->get_results(
                    $wpdb->prepare(
                        "SELECT * FROM {$wpdb->prefix}spin_posts ORDER BY created_at ASC LIMIT %d, %d",
                        $offset,
                        $number
                    )
                );
            }
            return $wpdb->get_results(
                $wpdb->prepare(
                    "SELECT * FROM {$wpdb->prefix}spin_posts ORDER BY created_at DESC LIMIT %d, %d",
                    $offset,
                    $number
                )
            );
        case 'spin_title':
            if ( 'ASC' === $order ) {
                return $wpdb->get_results(
                    $wpdb->prepare(
                        "SELECT * FROM {$wpdb->prefix}spin_posts ORDER BY spin_title ASC LIMIT %d, %d",
                        $offset,
                        $number
                    )
                );
            }
            return $wpdb->get_results(
                $wpdb->prepare(
                    "SELECT * FROM {$wpdb->prefix}spin_posts ORDER BY spin_title DESC LIMIT %d, %d",
                    $offset,
                    $number
                )
            );
        case 'id':
        default:
            if ( 'ASC' === $order ) {
                return $wpdb->get_results(
                    $wpdb->prepare(
                        "SELECT * FROM {$wpdb->prefix}spin_posts ORDER BY id ASC LIMIT %d, %d",
                        $offset,
                        $number
                    )
                );
            }
            return $wpdb->get_results(
                $wpdb->prepare(
                    "SELECT * FROM {$wpdb->prefix}spin_posts ORDER BY id DESC LIMIT %d, %d",
                    $offset,
                    $number
                )
            );
    }
}

/**
 * Get the count of total address
 *
 * @return int
 */
function webequipe_sww_spin_count()
{
    global $wpdb;

    return (int) $wpdb->get_var("SELECT count(id) FROM {$wpdb->prefix}spin_posts WHERE deleted != 1");
}

/**
 * Fetch a single contact from the DB
 *
 * @param int $id
 *
 * @return object
 */
function webequipe_sww_get_spin($id)
{
    global $wpdb;

    return $wpdb->get_row(
        $wpdb->prepare("SELECT * FROM {$wpdb->prefix}spin_posts WHERE id = %d", $id)
    );
}

/**
 * Delete an address
 *
 * @param int $id
 *
 * @return int|bool
 */
function webequipe_sww_delete_spin($id)
{
    global $wpdb;

    return $wpdb->update(
        $wpdb->prefix . 'spin_posts',
        [
            'deleted' => '1',
            'deleted_by' => get_current_user_id(),
            'deleted_at' => current_time('mysql'),
        ],
        [
            'id' => $id,
        ]
    );
}

/**
 * Fetch a single email from the DB.
 *
 * @param string $email Email address to check.
 * @return array Email enquiry data.
 */
function webequipe_sww_get_email_enquiry($email)
{
    global $wpdb;

    $email_enquiry_data = [];

    // âœ… Sanitize input email.
    $email_enquiry_data['email'] = sanitize_email($email);

    // âœ… Safe count query (no user input here).
    $email_enquiry_data['rows'] = (int) $wpdb->get_var("SELECT COUNT(*) FROM {$wpdb->prefix}spin_emails");

    // âœ… Define table name safely.

    // Execute prepared query.
    $has_email = (int) $wpdb->get_var(
        $wpdb->prepare(
            "SELECT COUNT(*) FROM {$wpdb->prefix}spin_emails WHERE email = %s",
            $email_enquiry_data['email']
        )
    );

    // âœ… Check allow_multiple_spin option.
    $allow_multiple_spin = (int) get_option('wsww_setting_options_allow_multiple_spin', 0);

    $email_enquiry_data['email_found'] = $allow_multiple_spin ? 0 : $has_email;

    return $email_enquiry_data;
}


/**
 * Fetch a single email from the DB
 *
 * @param int $email
 *
 * @return object
 */
function webequipe_sww_check_last_entry($email)
{
    global $wpdb;

    $table = $wpdb->prefix . 'spin_emails';
    $email = sanitize_email($email);

    $last_created_at = $wpdb->get_var(
        $wpdb->prepare(
            "SELECT created_at FROM {$wpdb->prefix}spin_emails WHERE email = %s ORDER BY created_at DESC LIMIT 1",
            $email
        )
    );

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

    // Alternative approach: Use MySQL's timezone functions to detect the actual storage timezone

    // First, let's see what MySQL thinks about timezones
    global $wpdb;
    $mysql_utc_now = $wpdb->get_var("SELECT UTC_TIMESTAMP()");
    $mysql_local_now = strtotime($wpdb->get_var("SELECT NOW()") . ' UTC');


    // Calculate offset between MySQL's NOW() and UTC_TIMESTAMP()
    $mysql_utc_ts = strtotime($mysql_utc_now . ' UTC');
    $mysql_local_ts = strtotime($mysql_local_now . ' UTC');
    $mysql_offset = $mysql_local_ts - $mysql_utc_ts;


    $db_timestamp = strtotime($last_created_at . ' UTC');
    $last_time = $db_timestamp - $mysql_offset;

    $current_time = current_time('timestamp');



    return $mysql_local_now - $db_timestamp;
}



/**
 * Get winners list.
 *
 * @param array $args {
 *     Optional. Arguments for filtering and pagination.
 *
 *     @type int    $number  Number of results per page. Default 20.
 *     @type int    $offset  Offset for pagination. Default 0.
 *     @type string $orderby Column to order by. One of 'id', 'email', 'created_at'. Default 'id'.
 *     @type string $order   Sort direction. 'ASC' or 'DESC'. Default 'DESC'.
 *     @type int    $spin_id Filter by spin_id. Default 0 (no filter).
 *     @type string $search  Search by email (LIKE). Default empty.
 * }
 *
 * @return array|null List of result objects or null on failure.
 */
function webequipe_sww_get_winners($args = [])
{
    global $wpdb;

    $defaults = [
        'number' => 20,
        'offset' => 0,
        'orderby' => 'id',
        'order' => 'DESC',
        'spin_id' => 0,
        'search' => '',
    ];

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

    // Whitelist ORDER BY fields and directions.
    $allowed_orderby = ['id', 'email', 'created_at'];
    $allowed_order = ['ASC', 'DESC'];

    // Whitelist validation ensures these are safe identifiers.
    $orderby = in_array($args['orderby'], $allowed_orderby, true) ? $args['orderby'] : 'id';
    $order = in_array(strtoupper($args['order']), $allowed_order, true) ? strtoupper($args['order']) : 'DESC';

    // Normalize scalar args.
    $spin_id = absint($args['spin_id']);
    $offset = absint($args['offset']);
    $number = absint($args['number']);

    // Search term.
    $search_raw = isset($args['search']) ? $args['search'] : '';
    $search_raw = sanitize_text_field(wp_unslash($search_raw));

    $search_like = '';
    if ('' !== $search_raw) {
        $search_like = '%' . $wpdb->esc_like($search_raw) . '%';
    }

    // Prepare the query from hardcoded strings, only values use placeholders.
    switch ( $orderby ) {
        case 'email':
            if ( 'ASC' === $order ) {
                return $wpdb->get_results(
                    $wpdb->prepare(
                        "SELECT * FROM {$wpdb->prefix}spin_emails WHERE ( %d = 0 OR spin_id = %d ) AND ( %s = '' OR email LIKE %s ) ORDER BY email ASC LIMIT %d, %d",
                        $spin_id,
                        $spin_id,
                        $search_like,
                        $search_like,
                        $offset,
                        $number
                    )
                );
            }
            return $wpdb->get_results(
                $wpdb->prepare(
                    "SELECT * FROM {$wpdb->prefix}spin_emails WHERE ( %d = 0 OR spin_id = %d ) AND ( %s = '' OR email LIKE %s ) ORDER BY email DESC LIMIT %d, %d",
                    $spin_id,
                    $spin_id,
                    $search_like,
                    $search_like,
                    $offset,
                    $number
                )
            );
        case 'created_at':
            if ( 'ASC' === $order ) {
                return $wpdb->get_results(
                    $wpdb->prepare(
                        "SELECT * FROM {$wpdb->prefix}spin_emails WHERE ( %d = 0 OR spin_id = %d ) AND ( %s = '' OR email LIKE %s ) ORDER BY created_at ASC LIMIT %d, %d",
                        $spin_id,
                        $spin_id,
                        $search_like,
                        $search_like,
                        $offset,
                        $number
                    )
                );
            }
            return $wpdb->get_results(
                $wpdb->prepare(
                    "SELECT * FROM {$wpdb->prefix}spin_emails WHERE ( %d = 0 OR spin_id = %d ) AND ( %s = '' OR email LIKE %s ) ORDER BY created_at DESC LIMIT %d, %d",
                    $spin_id,
                    $spin_id,
                    $search_like,
                    $search_like,
                    $offset,
                    $number
                )
            );
        case 'id':
        default:
            if ( 'ASC' === $order ) {
                return $wpdb->get_results(
                    $wpdb->prepare(
                        "SELECT * FROM {$wpdb->prefix}spin_emails WHERE ( %d = 0 OR spin_id = %d ) AND ( %s = '' OR email LIKE %s ) ORDER BY id ASC LIMIT %d, %d",
                        $spin_id,
                        $spin_id,
                        $search_like,
                        $search_like,
                        $offset,
                        $number
                    )
                );
            }
            return $wpdb->get_results(
                $wpdb->prepare(
                    "SELECT * FROM {$wpdb->prefix}spin_emails WHERE ( %d = 0 OR spin_id = %d ) AND ( %s = '' OR email LIKE %s ) ORDER BY id DESC LIMIT %d, %d",
                    $spin_id,
                    $spin_id,
                    $search_like,
                    $search_like,
                    $offset,
                    $number
                )
            );
    }
}





/**
 * Fetch a single winner from the DB
 *
 * @param int $id
 *
 * @return object
 */
function webequipe_sww_get_winner_detail($id)
{
    global $wpdb;

    return $wpdb->get_row(
        $wpdb->prepare("SELECT * FROM {$wpdb->prefix}spin_emails WHERE id = %d", $id)
    );
}

/**
 * Get the count of total winners.
 *
 * @param array $args Query arguments.
 * @return int Total number of winners.
 */

function webequipe_sww_winner_count($args = [])
{
    global $wpdb;

    $defaults = [
        'spin_id' => 0,
        'search' => '',
    ];

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

    // Normalize spin_id.
    $spin_id = absint($args['spin_id']);

    // Normalize and sanitize search term.
    $search_raw = isset($args['search']) ? $args['search'] : '';
    $search_raw = sanitize_text_field(wp_unslash($search_raw));

    $search_like = '';
    if ('' !== $search_raw) {
        $search_like = '%' . $wpdb->esc_like($search_raw) . '%';
    }

    /**
     * WHERE logic (same trick as the other function so placeholders are fixed):
     *
     * WHERE ( %d = 0 OR spin_id = %d )
     *   AND ( %s = '' OR email LIKE %s )
     *
     * - If $spin_id is 0  → no spin filter.
     * - If $spin_id > 0   → spin_id must match.
     *
     * - If $search_like is ''  → no email filter.
     * - If $search_like != ''  → email LIKE $search_like must match.
     */

    // Table name uses $wpdb->prefix (not user input). All user data goes via placeholders.
    $count = (int) $wpdb->get_var(
        $wpdb->prepare(
            "
                SELECT COUNT(id)
                FROM {$wpdb->prefix}spin_emails
                WHERE ( %d = 0 OR spin_id = %d )
                  AND ( %s = '' OR email LIKE %s )
            ",
            $spin_id,
            $spin_id,
            $search_like,
            $search_like
        )
    );

    return $count;
}



/**
 * Delete single winner
 */

add_action('admin_post_wsww-winner-delete', 'webequipe_sww_handle_winner_delete');

/**
 * Export winners to CSV.
 */
add_action('admin_post_wsww_export_winners', 'webequipe_sww_export_winners_csv');

function webequipe_sww_export_winners_csv()
{
    // Verify nonce from the export request.
    $nonce = isset( $_GET['_wpnonce'] ) ? sanitize_text_field( wp_unslash( $_GET['_wpnonce'] ) ) : '';
    if ( ! wp_verify_nonce( $nonce, 'wsww_export_winners' ) ) {
        wp_die( esc_html__( 'Security check failed.', 'webequipe-spin-win-wheel' ) );
    }

    // Check user capabilities.
    if (!current_user_can('manage_options')) {
        wp_die(esc_html__('You do not have sufficient permissions to access this page.', 'webequipe-spin-win-wheel'));
    }

    // Get all winners data.
    $winners = webequipe_sww_get_winners(
        [
            'number' => 9999,
            'offset' => 0,
        ]
    );

    // âœ… Use wp_date() instead of date().
    $filename = 'webequipe-spin-win-wheel-winners-' . wp_date('Y-m-d-H-i-s') . '.csv';

    // Set headers for CSV download.
    header('Content-Type: text/csv');
    header('Content-Disposition: attachment; filename="' . $filename . '"');
    header('Pragma: no-cache');
    header('Expires: 0');

    // Open output stream.
    $output = fopen('php://output', 'w');

    // Add CSV headers.
    $headers = [
        'ID',
        'Email',
        'Name',
        'Phone',
        'Spin Title',
        'Label',
        'Value',
        'Claim Status',
        'Winning Date',
        'Page URL',
    ];
    fputcsv($output, $headers);

    // Add data rows.
    foreach ($winners as $winner) {
        // Get spin post title.
        $spin_title = 'N/A';
        if (isset($winner->spin_id)) {
            $spin_post = webequipe_sww_get_spin($winner->spin_id);
            $spin_title = $spin_post ? $spin_post->spin_title : 'N/A';
        }

        // Get spin value.
        $spin_value = 'N/A';
        if (isset($winner->spin_id)) {
            $spin_post = webequipe_sww_get_spin($winner->spin_id);
            if ($spin_post && isset($spin_post->spins)) {
                $spins_data = json_decode($spin_post->spins, true);
                if (is_array($spins_data)) {
                    foreach ($spins_data as $spin_item) {
                        if (isset($spin_item['spin_label']) && $spin_item['spin_label'] === $winner->spin_label) {
                            $spin_value = isset($spin_item['spin_value']) ? $spin_item['spin_value'] : 'N/A';
                            break;
                        }
                    }
                }
            }
        }

        $row = [
            $winner->id,
            $winner->email,
            $winner->name,
            $winner->phone,
            $spin_title,
            $winner->spin_label,
            $spin_value,
            ucfirst($winner->claim),
            wp_date(get_option('date_format'), strtotime($winner->created_at)),
            $winner->page_url,
        ];

        fputcsv($output, $row);
    }

    exit;
}



function webequipe_sww_handle_winner_delete()
{
    $nonce = isset($_GET['_wpnonce']) ? sanitize_text_field(wp_unslash($_GET['_wpnonce'])) : '';
    if (!isset($_GET['id']) || !wp_verify_nonce($nonce, 'wsww-winner-delete')) {
        wp_die(esc_html__('Security check failed.', 'webequipe-spin-win-wheel'));
    }

    if (!current_user_can('manage_options')) {
        wp_die(esc_html__('You do not have permission to perform this action.', 'webequipe-spin-win-wheel'));
    }

    $winner_id = isset($_GET['id']) ? absint(wp_unslash($_GET['id'])) : 0;
    if (!$winner_id) {
        wp_die(esc_html__('Invalid winner ID.', 'webequipe-spin-win-wheel'));
    }

    global $wpdb;
    $table_name = $wpdb->prefix . 'spin_emails';

    $deleted = $wpdb->delete($table_name, ['id' => $winner_id], ['%d']);

    if ($deleted) {
        $redirect_url = admin_url('admin.php?page=wsww-spin-winner&deleted=1&message=' . urlencode(esc_html__('Winner successfully deleted.', 'webequipe-spin-win-wheel')));
        // Add nonce to redirect URL for security
        $redirect_url = wp_nonce_url($redirect_url, 'wsww-message-display', '_wpnonce');
        wp_safe_redirect($redirect_url);
        exit;
    } else {
        wp_die(esc_html__('Failed to delete the winner.', 'webequipe-spin-win-wheel'));
    }
}

/**
 * Delete single spin
 */

add_action('admin_post_wsww-spin-delete-spin', 'webequipe_sww_handle_spin_delete_spin');

function webequipe_sww_handle_spin_delete_spin()
{
    $nonce = isset($_GET['_wpnonce']) ? sanitize_text_field(wp_unslash($_GET['_wpnonce'])) : '';
    if (!isset($_GET['id']) || !wp_verify_nonce($nonce, 'wsww-spin-delete-spin')) {
        wp_die(esc_html__('Security check failed.', 'webequipe-spin-win-wheel'));
    }

    if (!current_user_can('manage_options')) {
        wp_die(esc_html__('You do not have permission to perform this action.', 'webequipe-spin-win-wheel'));
    }

    $winner_id = isset($_GET['id']) ? absint(wp_unslash($_GET['id'])) : 0;
    if (!$winner_id) {
        wp_die(esc_html__('Invalid winner ID.', 'webequipe-spin-win-wheel'));
    }

    global $wpdb;
    $table_name = $wpdb->prefix . 'spin_posts';

    $deleted = $wpdb->delete($table_name, ['id' => $winner_id], ['%d']);

    if ($deleted) {
        $redirect_url = admin_url('admin.php?page=wsww-spin&deleted=1&message=' . urlencode(esc_html__('Spin successfully deleted.', 'webequipe-spin-win-wheel')));
        // Add nonce to redirect URL for security
        $redirect_url = wp_nonce_url($redirect_url, 'wsww-message-display', '_wpnonce');
        wp_safe_redirect($redirect_url);
        exit;
    } else {
        wp_die(esc_html__('Failed to delete the spin.', 'webequipe-spin-win-wheel'));
    }
}

/**
 * Claim Update
 *
 * @param int $id
 *
 * @return object
 */
function webequipe_sww_claim_update($id)
{
    global $wpdb;

    $wpdb->update(
        $wpdb->prefix . 'spin_emails',
        [
            'claim' => 'yes',
            'updated_at' => current_time('mysql'),
        ],
        [
            'id' => $id,
        ]
    );

    return $id;
}

/**
 * Handle claim update via normal form POST
 */
add_action('admin_post_wsww_claim_update', 'webequipe_sww_handle_claim_update');

function webequipe_sww_handle_claim_update()
{
    $nonce = isset($_POST['_wpnonce']) ? sanitize_text_field(wp_unslash($_POST['_wpnonce'])) : '';
    if (!isset($_POST['id']) || !wp_verify_nonce($nonce, 'wsww-claim-update-form')) {
        wp_die(esc_html__('Security check failed.', 'webequipe-spin-win-wheel'));
    }

    if (!current_user_can('manage_options')) {
        wp_die(esc_html__('No permission!', 'webequipe-spin-win-wheel'));
    }

    $winner_id = isset($_POST['id']) ? absint(wp_unslash($_POST['id'])) : 0;
    if (!$winner_id) {
        wp_die(esc_html__('Invalid winner ID.', 'webequipe-spin-win-wheel'));
    }

    webequipe_sww_claim_update($winner_id);

    $redirect_url = !empty($_POST['redirect_to']) ? esc_url_raw(wp_unslash($_POST['redirect_to'])) : admin_url();
    $redirect_url = add_query_arg('message', urlencode(esc_html__('Claim updated successfully!', 'webequipe-spin-win-wheel')), $redirect_url);
    // Add nonce to redirect URL for security
    $redirect_url = wp_nonce_url($redirect_url, 'wsww-message-display', '_wpnonce');

    wp_safe_redirect($redirect_url);
    exit;
}

/**
 * Handle color code
 * @param string $color color code
 * @return string color code
 */


function webequipe_sww_normalize_hex_for_color_input($color)
{
    $color = trim(strtolower($color));
    if (preg_match('/^#([a-f0-9]{8})$/', $color)) {
        return '#' . substr($color, 1, 6);
    }
    if (preg_match('/^#([a-f0-9]{4})$/', $color, $m)) {
        return '#' . str_repeat($m[1][0], 2)
            . str_repeat($m[1][1], 2)
            . str_repeat($m[1][2], 2);
    }
    if (preg_match('/^#([a-f0-9]{3})$/', $color, $m)) {
        return '#' . str_repeat($m[1][0], 2)
            . str_repeat($m[1][1], 2)
            . str_repeat($m[1][2], 2);
    }
    if (preg_match('/^#([a-f0-9]{6})$/', $color)) {
        return $color;
    }
    if (
        preg_match('/rgba?\(\s*(\d{1,3})\s*,\s*(\d{1,3})\s*,\s*(\d{1,3})/i', $color, $m) ||
        preg_match('/^\s*(\d{1,3})\s*,\s*(\d{1,3})\s*,\s*(\d{1,3})\s*$/', $color, $m)
    ) {
        $r = max(0, min(255, (int) $m[1]));
        $g = max(0, min(255, (int) $m[2]));
        $b = max(0, min(255, (int) $m[3]));
        return sprintf('#%02x%02x%02x', $r, $g, $b);
    }

    return '#000000';
}

/**
 * Remove added slashes/entities from stored spin text before escaping for output.
 *
 * @param mixed $text Raw text value.
 * @return string Clean text.
 */
function webequipe_sww_normalize_spin_text($text)
{
    if (!is_string($text)) {
        return '';
    }

    $text = wp_unslash($text);

    return wp_specialchars_decode($text, ENT_QUOTES);
}


/**
 * Replace placeholders in a template with provided values.
 *
 * @param string $template The message template containing placeholders like {customer_name}.
 * @param array  $data     Key-value pairs where key = placeholder name, value = replacement.
 * @return string          The formatted message.
 */
function webequipe_sww_formatMessage($template, $data = [])
{
    foreach ($data as $key => $value) {
        $template = str_replace('{' . $key . '}', $value, $template);
    }
    return $template;
}
