<?php
add_filter('cron_schedules', 'wp_auto_spinner_once_a_minute');
function wp_auto_spinner_once_a_minute($schedules)
{

    // Adds once weekly to the existing schedules.
    $schedules['once_a_minute'] = array(
        'interval' => 60,
        'display' => __('once a minute'),
    );
    return $schedules;
}

if (!wp_next_scheduled('wp_auto_spinner_spin_hook')) {
    wp_schedule_event(time(), 'once_a_minute', 'wp_auto_spinner_spin_hook');
}

add_action('wp_auto_spinner_spin_hook', 'wp_auto_spinner_spin_function_wrap');

function wp_auto_spinner_spin_function_wrap()
{

    $autospin = get_option('wp_auto_spin', array());

    //if internal cron not active return
    if (!in_array('OPT_AUTO_SPIN_CRON', $autospin)) {
        return;
    }

    //if an external cron run less than 20 minutes ago, skip
    $WP_AUTO_SPINNER_EXTERNAL_CRON_TIME = get_option('WP_AUTO_SPINNER_EXTERNAL_CRON_TIME', time());

    if (time() - $WP_AUTO_SPINNER_EXTERNAL_CRON_TIME < 20 * 60) {
        return;
    }

    //fire processing the queue
    wp_auto_spinner_spin_function();

}

/**
 * Function to process the queue and spin the posts
 * This function will be called by the cron job directly from the cron.php file using the external cron
 * It will also be called by the internal cron job
 */
function wp_auto_spinner_spin_function()
{

    //check if there is a running previous cron job
    //if there is a running cron job, skip this call
    //a running cron job is marked by the presence of the option WP_AUTO_SPINNER_CRON_RUNNING
    //if the option is not present, then this is the first call of the cron job
    //if the option is present, then check the time of the option
    //if the time exceeds 6 minutes then the cron job is stuck and we need to reset it

     //get the current time
     $timenow = current_time('timestamp');

    //get the option
    $WP_AUTO_SPINNER_CRON_RUNNING = get_option('WP_AUTO_SPINNER_CRON_RUNNING', false);

    //if the option is not present, then this is the first call of the cron job
    if ($WP_AUTO_SPINNER_CRON_RUNNING === false) {

        //set the option to the current time
        update_option('WP_AUTO_SPINNER_CRON_RUNNING', time());

    } else {

        //the option is present, check the time
        //if the time exceeds 6 minutes then the cron job is stuck and we need to reset it
        if (time() - $WP_AUTO_SPINNER_CRON_RUNNING > 6 * 60) {

            //the cron job is stuck, reset it
            delete_option('WP_AUTO_SPINNER_CRON_RUNNING');

        } else {

            echo 'Cron started at ' . date('h:i:s') . ' but the previous cron job is still running';

            //update last run cron call
            update_option('wp_auto_spinner_last_run', $timenow);

            //the cron job is not stuck, skip this call
            return;

        }

    }

    //options
    $autospin = get_option('wp_auto_spin', array());

    //remove filters on the query
    remove_all_filters('pre_get_posts');

   

    //update the last run time
    update_option('wp_auto_spinner_last_run', $timenow);

    if (!in_array('OPT_AUTO_SPIN_QUEUE_DISABLED', $autospin)) {

        // log call
        //wp_auto_spinner_log_new ( 'cron call', 'we should now process one waiting to be spinned article' );

        // get one post deserve spin
        // get execluded cateogries array
        $execl = get_option('wp_auto_spin_execl', array());
        $post_status = array('publish', 'draft', 'pending');

        if (in_array('OPT_AUTO_SPIN_SCHEDULED', $autospin)) {
            $post_status = array_merge($post_status, array('future'));
        }

        // The Query
        $the_query = new WP_Query(array(
            'category__not_in' => $execl,
            'post_status' => $post_status,
            'posts_per_page' => 1,

            'ignore_sticky_posts' => true,
            'post_type' => 'any',

            'meta_query' => array(

                array(
                    'key' => 'wp_auto_spinner_scheduled',
                    'compare' => 'EXISTS',
                ), array(
                    'key' => 'spinned_cnt',
                    'compare' => 'NOT EXISTS',
                ),

            ),

        ));

        // The Loop
        if ($the_query->have_posts()) {

            echo time() . ' Cron started at ' . date('h:i:s');

            while ($the_query->have_posts()) {

                $the_query->the_post();

                $newid = get_the_id();

                if (trim($newid) == '') {
                    return;
                }

                $post_id = get_the_id();

                update_option('wp_auto_spinner_last_spin', $post_id);

                //increment number of times this post was retired to be rewritten
                //custom field name is wp_auto_spinner_scheduled_cnt
                $cnt = get_post_meta($post_id, 'wp_auto_spinner_scheduled_cnt', true);

                //default value is 0
                if (trim($cnt) == '') {
                    $cnt = 0;
                }

                wp_auto_spinner_log_new('Cron Call >> top post', '#' . get_the_id() . ' retriedCount:' . $cnt);

                //increment the value
                $cnt++;

                //if the post was retired more than WP_AUTO_SPINNER_QUEUE_RETRIES times, remove from the queue
                //this is happend before rewriting the post to avoid blocking the queue
                if ($cnt >= WP_AUTO_SPINNER_QUEUE_RETRIES) {

                    //delete the counter
                    delete_post_meta($post_id, 'wp_auto_spinner_scheduled_cnt');

                    //removing the post from the queue so if spinning got failed, do not block
                    delete_post_meta($post_id, 'wp_auto_spinner_scheduled');

                    //log the event and retries count
                    wp_auto_spinner_log_new('Cron >> Post removed' . $cnt, 'doing the final retry, reached max retries of ' . $cnt);

                } else {

                    //update the counter
                    update_post_meta($post_id, 'wp_auto_spinner_scheduled_cnt', $cnt);

                }

                //spin the post
                $spin_result = wp_auto_spinner_post_spin($post_id);

                //if $spin_result is not boolean and is not == false, then remove the item from the queue
                if (!is_bool($spin_result) && $spin_result !== false) {

                    //not an openAI fail case so remove from the queue

                    //delete the counter
                    delete_post_meta($post_id, 'wp_auto_spinner_scheduled_cnt');

                    //removing the post from the queue so if spinning got failed, do not block
                    delete_post_meta($post_id, 'wp_auto_spinner_scheduled');

                    //if option OPT_AUTO_SPIN_STATUS_PUBLISH is enabled, publish the post
                    if (in_array('OPT_AUTO_SPIN_STATUS_PUBLISH', $autospin)) {
                        $res = wp_auto_spinner_update_post_status_to_publish($post_id);
                        wp_auto_spinner_log_new('Cron >> Post Published', $res);
                    }

                }

                break;

            }
        } else {
            // no posts found
            //wp_auto_spinner_log_new ( 'Cron >> Cancel', 'No waiting to be spinned posts' );

            echo 'Cron started at ' . date('h:i:s') . ' but no waiting posts in the queue';

        }

        /* Restore original Post Data */
        wp_reset_postdata();
    } else {

        echo 'Queue processing is disabled. visit settings if you want to enable it back';

    }

    //release the lock
    delete_option('WP_AUTO_SPINNER_CRON_RUNNING');

}

/**
 * Update the post status to 'publish' when the post is updated.
 * @param int $post_id The post ID.
 * @return string
 */
function wp_auto_spinner_update_post_status_to_publish($post_id)
{
    // Get the current post status
    $current_status = get_post_status($post_id);

    // Check if the post is not already published
    if ($current_status !== 'publish') {
        // Update the post status to 'publish'
        $updated_post = array(
            'ID' => $post_id,
            'post_status' => 'publish',
        );

        //before updating the post mark it as checked not to get it rewritten again as a new published post
        update_post_meta($post_id, 'wp_auto_spinner_checked', 'yes');

        // Update the post with the new status
        wp_update_post($updated_post);

        return "Post status updated to 'publish'.";
    } else {
        return "Post is already in 'publish' status.";
    }
}
