<?php

if ( !defined( 'ABSPATH' ) ) {
    exit;
}
// Exit if accessed directly
function freshenup_build_base_query(
    $post_types = ['post'],
    $include_categories = [],
    $exclude_categories = [],
    $include_tags = [],
    $exclude_tags = [],
    $authors = []
) {
    global $wpdb;
    $posts_table = $wpdb->posts;
    $term_relationships = $wpdb->term_relationships;
    $term_taxonomy = $wpdb->term_taxonomy;
    $sql = "FROM {$posts_table} p";
    $query_params = [];
    // WPML / Polylang joins
    if ( defined( 'ICL_SITEPRESS_VERSION' ) ) {
        $sql .= " LEFT JOIN {$wpdb->prefix}icl_translations icl ON p.ID = icl.element_id AND icl.element_type LIKE 'post_%'";
    } elseif ( function_exists( 'pll_get_post_language' ) ) {
        $sql .= " LEFT JOIN {$wpdb->term_relationships} pll_tr ON p.ID = pll_tr.object_id\r\n                  LEFT JOIN {$wpdb->term_taxonomy} pll_tt ON pll_tr.term_taxonomy_id = pll_tt.term_taxonomy_id\r\n                  LEFT JOIN {$wpdb->terms} pll_terms ON pll_tt.term_id = pll_terms.term_id";
    }
    // If any taxonomies are needed, join relationships and taxonomy tables
    $needs_taxonomy_join = !empty( $include_categories ) && $include_categories[0] !== esc_html__( 'all categories', 'freshenup' ) || !empty( $exclude_categories ) && $exclude_categories[0] !== esc_html__( 'no categories', 'freshenup' ) || !empty( $include_tags ) && $include_tags[0] !== esc_html__( 'all tags', 'freshenup' );
    if ( $needs_taxonomy_join ) {
        $sql .= " INNER JOIN {$term_relationships} tr ON p.ID = tr.object_id\r\n                  INNER JOIN {$term_taxonomy} tt ON tr.term_taxonomy_id = tt.term_taxonomy_id";
    }
    // WHERE: post type and status
    if ( $post_types[0] !== esc_html__( 'all post types', 'freshenup' ) ) {
        $placeholders = implode( ',', array_fill( 0, count( $post_types ), '%s' ) );
        $sql .= " WHERE p.post_type IN ({$placeholders}) AND p.post_status = %s";
        $query_params = array_merge( $post_types, ['publish'] );
    } else {
        $sql .= " WHERE p.post_status = %s";
        $query_params = ['publish'];
    }
    // WPML/Polylang language filtering
    if ( defined( 'ICL_SITEPRESS_VERSION' ) ) {
        $sql .= " AND (icl.source_language_code IS NULL)";
    } elseif ( function_exists( 'pll_get_post_language' ) ) {
        $default_lang = pll_default_language();
        $sql .= " AND (pll_tt.taxonomy = 'language' AND pll_terms.slug = %s)";
        $query_params[] = $default_lang;
    }
    // Category inclusion
    if ( !empty( $include_categories ) && $include_categories[0] !== esc_html__( 'all categories', 'freshenup' ) ) {
        $placeholders = implode( ',', array_fill( 0, count( $include_categories ), '%d' ) );
        $sql .= " AND tt.taxonomy = 'category' AND tt.term_id IN ({$placeholders})";
        $query_params = array_merge( $query_params, $include_categories );
    }
    // Tag inclusion
    if ( !empty( $include_tags ) && $include_tags[0] !== esc_html__( 'all tags', 'freshenup' ) ) {
        $placeholders = implode( ',', array_fill( 0, count( $include_tags ), '%d' ) );
        $sql .= " AND tt.taxonomy = 'post_tag' AND tt.term_id IN ({$placeholders})";
        $query_params = array_merge( $query_params, $include_tags );
    }
    // Category exclusion
    if ( !empty( $exclude_categories ) && $exclude_categories[0] !== esc_html__( 'no categories', 'freshenup' ) ) {
        $placeholders = implode( ',', array_fill( 0, count( $exclude_categories ), '%d' ) );
        $sql .= " AND p.ID NOT IN (\r\n            SELECT object_id\r\n            FROM {$term_relationships} tr2\r\n            INNER JOIN {$term_taxonomy} tt2 ON tr2.term_taxonomy_id = tt2.term_taxonomy_id\r\n            WHERE tt2.taxonomy = 'category'\r\n            AND tt2.term_id IN ({$placeholders})\r\n        )";
        $query_params = array_merge( $query_params, $exclude_categories );
    }
    // Tag exclusion
    if ( !empty( $exclude_tags ) && $exclude_tags[0] !== esc_html__( 'no tags', 'freshenup' ) ) {
        $placeholders = implode( ',', array_fill( 0, count( $exclude_tags ), '%d' ) );
        $sql .= " AND p.ID NOT IN (\r\n            SELECT object_id\r\n            FROM {$term_relationships} tr3\r\n            INNER JOIN {$term_taxonomy} tt3 ON tr3.term_taxonomy_id = tt3.term_taxonomy_id\r\n            WHERE tt3.taxonomy = 'post_tag'\r\n            AND tt3.term_id IN ({$placeholders})\r\n        )";
        $query_params = array_merge( $query_params, $exclude_tags );
    }
    // Author filtering
    if ( !empty( $authors ) && $authors[0] !== esc_html__( 'all authors', 'freshenup' ) ) {
        $placeholders = implode( ',', array_fill( 0, count( $authors ), '%d' ) );
        $sql .= " AND p.post_author IN ({$placeholders})";
        $query_params = array_merge( $query_params, $authors );
    }
    return [
        'sql'    => $sql,
        'params' => $query_params,
    ];
}

function freshenup_get_eligible_posts_count(
    $post_types = ['post'],
    $include_categories = [],
    $exclude_categories = [],
    $include_tags = [],
    $exclude_tags = [],
    $authors = [],
    $min_days = 365,
    $min_days_freshenup = 365,
    $min_days_published = 365,
    $can_update_multiple = 'can'
) {
    global $wpdb;
    $sql = "SELECT \r\n        COUNT(DISTINCT p.ID) as total_posts,\r\n        COUNT(DISTINCT CASE \r\n            WHEN DATEDIFF(NOW(), p.post_modified) >= %d \r\n            AND DATEDIFF(NOW(), p.post_date) >= %d\r\n            AND NOT EXISTS (\r\n                SELECT 1 FROM {$wpdb->postmeta} pm \r\n                WHERE pm.post_id = p.ID \r\n                AND pm.meta_key = 'freshenup_post_sent'\r\n                AND DATEDIFF(NOW(), FROM_UNIXTIME(pm.meta_value)) < %d\r\n            )\r\n            AND NOT EXISTS (";
    if ( $can_update_multiple === 'cannot' ) {
        $sql .= "SELECT 1 FROM {$wpdb->postmeta} pm \r\n                WHERE pm.post_id = p.ID \r\n                AND pm.meta_key IN ('freshenup_updating', 'freshenup_awaiting_moderation', \r\n                            'freshenup_approved', 'freshenup_new_content')\r\n                AND pm.meta_value != ''";
    } else {
        $sql .= "SELECT 1 FROM {$wpdb->postmeta} pm \r\n                WHERE pm.post_id = p.ID \r\n                AND pm.meta_key IN ('freshenup_updating', 'freshenup_awaiting_moderation')\r\n                AND pm.meta_value != ''";
    }
    $sql .= ")\r\n            THEN p.ID \r\n        END) as eligible_posts,\r\n        COUNT(DISTINCT CASE \r\n            WHEN DATEDIFF(NOW(), p.post_modified) < %d \r\n            OR DATEDIFF(NOW(), p.post_date) < %d \r\n            OR EXISTS (\r\n                SELECT 1 FROM {$wpdb->postmeta} pm \r\n                WHERE pm.post_id = p.ID \r\n                AND pm.meta_key = 'freshenup_post_sent'\r\n                AND DATEDIFF(NOW(), FROM_UNIXTIME(pm.meta_value)) < %d\r\n            )\r\n            THEN p.ID \r\n        END) as excluded_too_recent,\r\n        COUNT(DISTINCT CASE \r\n            WHEN EXISTS (\r\n                SELECT 1 FROM {$wpdb->postmeta} pm \r\n                WHERE pm.post_id = p.ID \r\n                AND pm.meta_key IN ('freshenup_updating', 'freshenup_awaiting_moderation', \r\n                            'freshenup_approved', 'freshenup_new_content')\r\n                AND pm.meta_value != ''\r\n            )\r\n            THEN p.ID \r\n        END) as excluded_by_meta,\r\n        COUNT(DISTINCT CASE \r\n            WHEN DATEDIFF(NOW(), p.post_modified) >= %d \r\n            AND DATEDIFF(NOW(), p.post_date) >= %d\r\n            THEN p.ID \r\n        END) as old_enough_posts\r\n    FROM {$wpdb->posts} p";
    // Polylang join
    if ( function_exists( 'pll_get_post_language' ) ) {
        $sql .= " LEFT JOIN {$wpdb->term_relationships} pll_tr ON p.ID = pll_tr.object_id\r\n                  LEFT JOIN {$wpdb->term_taxonomy} pll_tt ON pll_tr.term_taxonomy_id = pll_tt.term_taxonomy_id\r\n                  LEFT JOIN {$wpdb->terms} pll_terms ON pll_tt.term_id = pll_terms.term_id";
    } else {
        if ( defined( 'ICL_SITEPRESS_VERSION' ) ) {
            $sql .= " LEFT JOIN {$wpdb->prefix}icl_translations icl ON p.ID = icl.element_id AND icl.element_type LIKE 'post_%'";
        }
    }
    $sql .= " WHERE p.post_status = 'publish'";
    $params = [
        $min_days,
        $min_days_published,
        $min_days_freshenup,
        // For eligible_posts
        $min_days,
        $min_days_published,
        $min_days_freshenup,
        // For excluded_too_recent
        $min_days,
        $min_days_published,
    ];
    // Language filter
    // Add Polylang condition
    if ( function_exists( 'pll_get_post_language' ) ) {
        $default_lang = pll_default_language();
        $sql .= " AND (pll_tt.taxonomy = 'language' AND pll_terms.slug = %s)";
        $params[] = $default_lang;
    } elseif ( defined( 'ICL_SITEPRESS_VERSION' ) ) {
        $sql .= " AND (icl.source_language_code IS NULL)";
    }
    // Post types
    if ( $post_types[0] !== esc_html__( 'all post types', 'freshenup' ) ) {
        $placeholders = implode( ',', array_fill( 0, count( $post_types ), '%s' ) );
        $sql .= " AND p.post_type IN ({$placeholders})";
        $params = array_merge( $params, $post_types );
    }
    // Include categories
    if ( !empty( $include_categories ) && $include_categories[0] !== esc_html__( 'all categories', 'freshenup' ) ) {
        $sql .= " AND p.ID IN (\r\n            SELECT object_id \r\n            FROM {$wpdb->term_relationships} tr\r\n            INNER JOIN {$wpdb->term_taxonomy} tt ON tr.term_taxonomy_id = tt.term_taxonomy_id\r\n            WHERE tt.taxonomy = 'category' \r\n            AND tt.term_id IN (" . implode( ',', array_fill( 0, count( $include_categories ), '%d' ) ) . ")\r\n        )";
        $params = array_merge( $params, $include_categories );
    }
    // Exclude categories
    if ( !empty( $exclude_categories ) && $exclude_categories[0] !== esc_html__( 'no categories', 'freshenup' ) ) {
        $sql .= " AND p.ID NOT IN (\r\n            SELECT object_id \r\n            FROM {$wpdb->term_relationships} tr2\r\n            INNER JOIN {$wpdb->term_taxonomy} tt2 ON tr2.term_taxonomy_id = tt2.term_taxonomy_id\r\n            WHERE tt2.taxonomy = 'category' \r\n            AND tt2.term_id IN (" . implode( ',', array_fill( 0, count( $exclude_categories ), '%d' ) ) . ")\r\n        )";
        $params = array_merge( $params, $exclude_categories );
    }
    // Include tags
    if ( !empty( $include_tags ) && $include_tags[0] !== esc_html__( 'all tags', 'freshenup' ) ) {
        $sql .= " AND p.ID IN (\r\n            SELECT object_id \r\n            FROM {$wpdb->term_relationships} tr3\r\n            INNER JOIN {$wpdb->term_taxonomy} tt3 ON tr3.term_taxonomy_id = tt3.term_taxonomy_id\r\n            WHERE tt3.taxonomy = 'post_tag' \r\n            AND tt3.term_id IN (" . implode( ',', array_fill( 0, count( $include_tags ), '%d' ) ) . ")\r\n        )";
        $params = array_merge( $params, $include_tags );
    }
    // Exclude tags
    if ( !empty( $exclude_tags ) && $exclude_tags[0] !== esc_html__( 'no tags', 'freshenup' ) ) {
        $sql .= " AND p.ID NOT IN (\r\n            SELECT object_id \r\n            FROM {$wpdb->term_relationships} tr4\r\n            INNER JOIN {$wpdb->term_taxonomy} tt4 ON tr4.term_taxonomy_id = tt4.term_taxonomy_id\r\n            WHERE tt4.taxonomy = 'post_tag' \r\n            AND tt4.term_id IN (" . implode( ',', array_fill( 0, count( $exclude_tags ), '%d' ) ) . ")\r\n        )";
        $params = array_merge( $params, $exclude_tags );
    }
    // Filter by authors
    if ( !empty( $authors ) && $authors[0] !== esc_html__( 'all authors', 'freshenup' ) ) {
        $placeholders = implode( ',', array_fill( 0, count( $authors ), '%d' ) );
        $sql .= " AND p.post_author IN ({$placeholders})";
        $params = array_merge( $params, $authors );
    }
    // Execute query
    // phpcs:ignore WordPress.DB.PreparedSQL.NotPrepared -- SQL built with proper placeholders above
    $prepared_sql = $wpdb->prepare( $sql, $params );
    // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching, WordPress.DB.PreparedSQL.NotPrepared, PluginCheck.Security.DirectDB.UnescapedDBParameter -- Complex query built with proper %s/%d placeholders
    $results = $wpdb->get_row( $prepared_sql );
    return [
        'total'     => (int) $results->total_posts,
        'eligible'  => (int) $results->eligible_posts,
        'breakdown' => [
            'too_recent'       => (int) $results->excluded_too_recent,
            'excluded_by_meta' => (int) $results->excluded_by_meta,
            'old_enough'       => (int) $results->old_enough_posts,
        ],
    ];
}

function freshenup_get_weighted_random_post(
    $post_types = ['post'],
    $include_categories = [],
    $exclude_categories = [],
    $include_tags = [],
    $exclude_tags = [],
    $authors = [],
    $min_days = 365,
    $min_days_freshenup = 365,
    $min_days_published = 365,
    $can_update_multiple = 'can'
) {
    global $wpdb;
    // Get base query
    $base_query = freshenup_build_base_query(
        $post_types,
        $include_categories,
        $exclude_categories,
        $include_tags,
        $exclude_tags,
        $authors
    );
    // First, get all eligible posts with their ages
    $sql = "SELECT p.ID, DATEDIFF(NOW(), p.post_modified) as age\r\n            " . $base_query['sql'] . "\r\n            AND DATEDIFF(NOW(), p.post_modified) >= %d\r\n            AND DATEDIFF(NOW(), p.post_date) >= %d";
    // Add freshenup days check
    $sql .= " AND NOT EXISTS (\r\n        SELECT 1 FROM {$wpdb->postmeta} \r\n        WHERE post_id = p.ID \r\n        AND meta_key = 'freshenup_post_sent'\r\n        AND DATEDIFF(NOW(), FROM_UNIXTIME(meta_value)) < %d\r\n    )";
    // Add can_update_multiple check
    if ( $can_update_multiple === 'cannot' ) {
        $sql .= " AND NOT EXISTS (\r\n            SELECT 1 FROM {$wpdb->postmeta} \r\n            WHERE post_id = p.ID \r\n            AND meta_key IN ('freshenup_updating', 'freshenup_awaiting_moderation', \r\n                            'freshenup_approved', 'freshenup_new_content', 'freshenup_post_sent')\r\n            AND meta_value != ''\r\n        )";
    } else {
        // If posts can be updated multiple times, only exclude currently processing ones
        $sql .= " AND NOT EXISTS (\r\n            SELECT 1 FROM {$wpdb->postmeta} \r\n            WHERE post_id = p.ID \r\n            AND meta_key IN ('freshenup_updating', 'freshenup_awaiting_moderation')\r\n            AND meta_value != ''\r\n        )";
    }
    // phpcs:ignore WordPress.DB.PreparedSQL.NotPrepared -- SQL built with proper placeholders above
    $prepared_sql = $wpdb->prepare( 
        $sql,
        // phpcs:ignore WordPress.DB.PreparedSQL.NotPrepared
        array_merge( $base_query['params'], [$min_days, $min_days_published, $min_days_freshenup] )
     );
    // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching, WordPress.DB.PreparedSQL.NotPrepared, PluginCheck.Security.DirectDB.UnescapedDBParameter -- Complex query built with proper %s/%d placeholders
    $eligible_posts = $wpdb->get_results( $prepared_sql );
    if ( empty( $eligible_posts ) ) {
        return false;
    }
    // Calculate weights for each post based on age
    $total_weight = 0;
    $weights = [];
    foreach ( $eligible_posts as $post ) {
        // Use a logarithmic weight to favor older posts but not too extremely
        $weight = log( $post->age - 119 );
        // -119 so log starts at 1 for 120 days
        $weights[$post->ID] = $weight;
        $total_weight += $weight;
    }
    // Select a random post based on weights
    $random = wp_rand( 0, mt_getrandmax() ) / mt_getrandmax() * $total_weight;
    $current_weight = 0;
    foreach ( $weights as $post_id => $weight ) {
        $current_weight += $weight;
        if ( $current_weight >= $random ) {
            return $post_id;
        }
    }
    // Fallback to first post (shouldn't normally reach here)
    return reset( $eligible_posts )->ID;
}

function freshenup_backup_current_post_revision(  $post_id  ) {
    $post = get_post( $post_id, ARRAY_A );
    if ( !$post ) {
        return false;
    }
    // Save the revision. not using wp_save_post_revision in case revisions are disabled.
    // Modify the post array to create a revision
    $post['post_status'] = 'inherit';
    $post['post_type'] = 'revision';
    $post['post_parent'] = $post_id;
    $post['post_date'] = current_time( 'mysql' );
    // Ensure the revision has a timestamp
    $post['post_date_gmt'] = current_time( 'mysql', 1 );
    // Remove the post ID to let wp_insert_post() create a new entry
    unset($post['ID']);
    // Insert the revision
    $revision_id = wp_insert_post( $post );
    // Fire the hook for consistency with WordPress core
    if ( $revision_id ) {
        // phpcs:ignore WordPress.NamingConventions.PrefixAllGlobals.NonPrefixedHooknameFound -- Intentionally firing WP core hook for compatibility
        do_action( '_wp_put_post_revision', $revision_id, $post_id );
    }
    return $revision_id;
}

function freshenup_get_prompt_values(  $prompt_id  ) {
    // Get the serialized data
    $serialized_prompt = get_option( 'freshenup_prompts', '' );
    // Unserialize the data
    $prompt = maybe_unserialize( $serialized_prompt );
    // The prompt ID is actually the key in the array
    if ( isset( $prompt[$prompt_id]['content'] ) ) {
        $prompt_content = $prompt[$prompt_id]['content'];
    } else {
        return false;
    }
    // Create a DOMDocument to parse the HTML content
    $dom = new DOMDocument();
    // Suppress warnings about HTML5 elements
    @$dom->loadHTML( mb_convert_encoding( $prompt_content, 'HTML-ENTITIES', 'UTF-8' ), LIBXML_HTML_NOIMPLIED | LIBXML_HTML_NODEFDTD );
    // Create a DOMXPath object to query the DOM
    $xpath = new DOMXPath($dom);
    // Get all editable spans
    $spans = $xpath->query( "//span[@class='editable']" );
    // Initialize values with defaults
    $values = array(
        'name'                => $prompt[$prompt_id]['name'],
        'id'                  => $prompt_id,
        'posts_count'         => null,
        'days'                => null,
        'percentage'          => null,
        'post_types'          => null,
        'include_categories'  => null,
        'exclude_categories'  => null,
        'include_tags'        => null,
        'exclude_tags'        => null,
        'authors'             => null,
        'min_days'            => 365,
        'min_days_freshenup'  => 365,
        'min_days_published'  => 365,
        'can_update_multiple' => esc_html__( 'can', 'freshenup' ),
        'internal_links'      => null,
        'moderate'            => null,
    );
    foreach ( $spans as $span ) {
        $value = $span->getAttribute( 'data-value' );
        $type = $span->getAttribute( 'data-type' );
        switch ( $type ) {
            case 'posts':
                $values['posts_count'] = intval( $value );
                break;
            case 'days':
                $values['days'] = ( $value === esc_html__( 'every day', 'freshenup' ) ? esc_html__( 'every day', 'freshenup' ) : explode( '-', $value ) );
                break;
            case 'percentage':
                $values['percentage'] = intval( $value );
                break;
            case 'post_types':
                $values['post_types'] = ( $value === esc_html__( 'all', 'freshenup' ) ? [] : explode( '-', $value ) );
                break;
            case 'include_categories':
                $values['include_categories'] = ( $value === esc_html__( 'all', 'freshenup' ) ? [] : explode( '-', $value ) );
                break;
            case 'exclude_categories':
                $values['exclude_categories'] = ( $value === esc_html__( 'no categories', 'freshenup' ) ? [] : explode( '-', $value ) );
                break;
            case 'include_tags':
                $values['include_tags'] = ( $value === esc_html__( 'all', 'freshenup' ) ? [] : explode( '-', $value ) );
                break;
            case 'exclude_tags':
                $values['exclude_tags'] = ( $value === esc_html__( 'no tags', 'freshenup' ) ? [] : explode( '-', $value ) );
                break;
            case 'authors':
                $values['authors'] = ( $value === esc_html__( 'all', 'freshenup' ) ? [] : explode( '-', $value ) );
                break;
            case 'min_days':
                $values['min_days'] = intval( $value );
                break;
            case 'min_days_freshenup':
                $values['min_days_freshenup'] = intval( $value );
                break;
            case 'min_days_published':
                $values['min_days_published'] = intval( $value );
                break;
            case 'can_update_multiple':
                $values['can_update_multiple'] = $value;
                break;
            case 'internal_links':
                $values['internal_links'] = esc_html( $value );
                break;
            case 'moderation':
                $values['moderate'] = esc_html( $value );
                break;
        }
    }
    return $values;
}

function freshenup_generate_scheduled_content(  $prompt_id, $execution_number  ) {
    // Retrieve the prompt values
    $prompt_values = freshenup_get_prompt_values( $prompt_id );
    if ( $prompt_values === false ) {
        return;
    }
    // Choose an outdated post based on prompt values
    $selected_post_id = freshenup_get_weighted_random_post(
        $prompt_values['post_types'],
        $prompt_values['include_categories'],
        $prompt_values['exclude_categories'],
        $prompt_values['include_tags'],
        $prompt_values['exclude_tags'],
        $prompt_values['authors'],
        $prompt_values['min_days'],
        $prompt_values['min_days_freshenup'],
        $prompt_values['min_days_published'],
        $prompt_values['can_update_multiple']
    );
    if ( $selected_post_id === false ) {
        return;
    }
    // Send the post content to the API to start working on the update
    freshenup_send_data_to_api(
        $selected_post_id,
        $prompt_values['id'],
        $prompt_values['percentage'],
        $prompt_values['internal_links']
    );
}

add_action(
    'freshenup_generate_content_hook',
    'freshenup_generate_scheduled_content',
    10,
    2
);
function freshenup_send_data_to_api(
    $post_id,
    $prompt_id,
    $percentage,
    $add_internal_links = null
) {
    $post_id = (int) $post_id;
    $prompt_id = (int) $prompt_id;
    $unique_id = $post_id . substr( time(), -5 ) . wp_rand( 10, 99 );
    $post = get_post( $post_id );
    if ( !$post || !is_a( $post, 'WP_Post' ) ) {
        return;
    }
    $plugin_version = ( defined( 'FRESHENUP_VERSION' ) ? FRESHENUP_VERSION : '' );
    // Get the API key
    $api_key = freshenup_get_api_key();
    $ai_api_provider = 'openai';
    // Get the custom prompt
    $custom_prompt = get_option( 'freshenup_custom_prompt', '' );
    // Internal links
    $internal_links = array();
    if ( $add_internal_links == esc_html__( 'Add internal links', 'freshenup' ) ) {
        $internal_links = freshenup_get_yarpp_related_posts_array( $post_id );
    }
    // Prepare the data, ensuring all values are set
    $data = [
        'call'              => 'freshenup_content',
        'prompt_id'         => (int) $prompt_id,
        'post_id'           => (int) $post_id,
        'unique_id'         => (int) $unique_id,
        'post_title'        => $post->post_title,
        'post_content'      => $post->post_content,
        'post_date'         => $post->post_date,
        'post_modified'     => $post->post_modified,
        'percentage'        => $percentage,
        'ai_provider'       => $ai_api_provider,
        'custom_prompt'     => $custom_prompt,
        'internal_links'    => wp_json_encode( $internal_links ),
        'locale'            => get_locale(),
        'license_id'        => '',
        'install_id'        => '',
        'site_private_key'  => '',
        'url'               => '',
        'wp_url'            => get_site_url(),
        'trialtf'           => false,
        'plugin_version'    => $plugin_version,
        'prompts'           => get_option( 'freshenup_prompts' ),
        'encrypted_api_key' => ( $api_key ? freshenup_encrypt_for_transit( $api_key ) : '' ),
    ];
    // Safely get Freemius data
    if ( function_exists( 'freshenup_fs' ) ) {
        $fs = freshenup_fs();
        if ( $fs ) {
            $license = $fs->_get_license();
            $site = $fs->get_site();
            if ( $license ) {
                $data['license_id'] = $license->id;
            }
            if ( $site ) {
                $data['install_id'] = $site->id;
                $data['site_private_key'] = $site->secret_key;
                $data['url'] = $site->url;
            }
        }
    }
    // Encode data to JSON, handling potential encoding issues
    $body = wp_json_encode( $data );
    if ( $body === false ) {
        return;
    }
    $api_url = 'https://freshenup.io/api_connect.php';
    $args = [
        'body'        => $body,
        'headers'     => [
            'Content-Type'         => 'application/json',
            'X-Freshenup-Site-Key' => freshenup_get_or_generate_site_key(),
        ],
        'data_format' => 'body',
        'timeout'     => 60,
    ];
    $response = wp_remote_post( $api_url, $args );
    $response_code = wp_remote_retrieve_response_code( $response );
    if ( $response_code != 200 ) {
        return;
    }
    // Check if response body is empty
    $response_body = wp_remote_retrieve_body( $response );
    if ( empty( $response_body ) ) {
        return;
    }
    // Decode the API response
    $api_response = json_decode( $response_body, true );
    if ( isset( $api_response['success'] ) && $api_response['success'] === true ) {
        // add info to the post meta with the post id to alert updating
        update_post_meta( $post_id, 'freshenup_updating', '1' );
        $store_time = time();
        // add info to the post meta with the post id to store last time it was sent to freshenup
        update_post_meta( $post_id, 'freshenup_post_sent', $store_time );
        // Schedule the status check with Action Scheduler
        freshenup_schedule_status_check( $post_id, $prompt_id, $unique_id );
    } else {
        // Handle failed API response
    }
}

/**
 * Schedule the status check using Action Scheduler
 */
function freshenup_schedule_status_check(  $post_id, $prompt_id, $unique_id  ) {
    if ( !function_exists( 'as_schedule_recurring_action' ) ) {
        return;
    }
    $hook = 'freshenup_check_job_status';
    $group = 'freshenup-status-checks';
    $post_id = (int) $post_id;
    $prompt_id = (int) $prompt_id;
    $unique_id = (int) $unique_id;
    // Cancel any existing scheduled checks for this post
    as_unschedule_all_actions( $hook, array(
        'post_id'   => $post_id,
        'prompt_id' => $prompt_id,
        'unique_id' => $unique_id,
    ), $group );
    // Schedule new recurring action
    as_schedule_recurring_action(
        time(),
        // Start immediately
        1800,
        // 30 minutes in seconds
        $hook,
        array(
            'post_id'   => $post_id,
            'prompt_id' => $prompt_id,
            'unique_id' => $unique_id,
        ),
        $group
    );
}

function freshenup_unschedule_update(  $post_id, $prompt_id, $unique_id  ) {
    global $wpdb;
    $args_to_find = array(
        'post_id'   => (int) $post_id,
        'prompt_id' => (int) $prompt_id,
        'unique_id' => (int) $unique_id,
    );
    $result = as_unschedule_all_actions( 'freshenup_check_job_status', $args_to_find, 'freshenup-status-checks' );
}

/**
 * Callback function for the status check
 */
function freshenup_check_job_status(  $post_id, $prompt_id, $unique_id  ) {
    $post_id = (int) $post_id;
    $prompt_id = (int) $prompt_id;
    $unique_id = (int) $unique_id;
    // Get the updating status
    $is_updating = get_post_meta( $post_id, 'freshenup_updating', true );
    // Check if start time is set
    $start_time = get_post_meta( $post_id, 'freshenup_check_start_time', true );
    if ( empty( $start_time ) ) {
        // First run - set the start time
        $start_time = time();
        update_post_meta( $post_id, 'freshenup_check_start_time', $start_time );
    }
    // Check if 2 days have passed (2 days * 24 hours * 60 minutes * 60 seconds)
    if ( time() - $start_time > 2 * 24 * 60 * 60 ) {
        // More than 2 days have passed - clean up and stop checking
        delete_post_meta( $post_id, 'freshenup_updating' );
        delete_post_meta( $post_id, 'freshenup_check_start_time' );
        update_post_meta( $post_id, 'freshenup_status', 'timeout' );
        // Schedule cleanup for 1 minute later
        as_schedule_single_action(
            time() + 60,
            'freshenup_cleanup_cron',
            array(
                'post_id'   => (int) $post_id,
                'prompt_id' => (int) $prompt_id,
                'unique_id' => (int) $unique_id,
            ),
            'freshenup-cleanup'
        );
        return;
    }
    // Get the API key
    $api_key = freshenup_get_api_key();
    // Prepare the data, ensuring all values are set
    $data = [
        'call'              => 'freshenup_check_job_status',
        'prompt_id'         => (int) $prompt_id,
        'post_id'           => (int) $post_id,
        'unique_id'         => (int) $unique_id,
        'license_id'        => '',
        'install_id'        => '',
        'site_private_key'  => '',
        'url'               => '',
        'wp_url'            => get_site_url(),
        'trialtf'           => false,
        'encrypted_api_key' => ( $api_key ? freshenup_encrypt_for_transit( $api_key ) : '' ),
    ];
    // Safely get Freemius data
    if ( function_exists( 'freshenup_fs' ) ) {
        $fs = freshenup_fs();
        if ( $fs ) {
            $license = $fs->_get_license();
            $site = $fs->get_site();
            if ( $license ) {
                $data['license_id'] = $license->id;
            }
            if ( $site ) {
                $data['install_id'] = $site->id;
                $data['site_private_key'] = $site->secret_key;
                $data['url'] = $site->url;
            }
        }
    }
    // Encode data to JSON, handling potential encoding issues
    $body = wp_json_encode( $data );
    if ( $body === false ) {
        return;
    }
    $api_url = 'https://freshenup.io/api_connect.php';
    $args = [
        'body'        => $body,
        'headers'     => [
            'Content-Type'         => 'application/json',
            'X-Freshenup-Site-Key' => freshenup_get_or_generate_site_key(),
        ],
        'data_format' => 'body',
        'timeout'     => 30,
    ];
    $response = wp_remote_post( $api_url, $args );
    if ( is_wp_error( $response ) ) {
        return;
    }
    $response_body = wp_remote_retrieve_body( $response );
    $status_data = json_decode( $response_body, true );
    if ( isset( $status_data['status'] ) ) {
        switch ( $status_data['status'] ) {
            case 'completed':
                freshenup_receive_new_content(
                    $post_id,
                    $prompt_id,
                    $unique_id,
                    wp_kses_post( $status_data['new_content'] ),
                    wp_kses_post( $status_data['summary_changes'] ),
                    sanitize_text_field( $status_data['api_cost'] )
                );
                // Job is done, update post meta and cancel future checks
                delete_post_meta( $post_id, 'freshenup_updating' );
                delete_post_meta( $post_id, 'freshenup_check_start_time' );
                // Schedule cleanup for 1 minute later
                as_schedule_single_action(
                    time() + 60,
                    'freshenup_cleanup_cron',
                    array(
                        'post_id'   => (int) $post_id,
                        'prompt_id' => (int) $prompt_id,
                        'unique_id' => (int) $unique_id,
                    ),
                    'freshenup-cleanup'
                );
                return;
            case 'failed':
                // Handle failure case
                delete_post_meta( $post_id, 'freshenup_updating' );
                delete_post_meta( $post_id, 'freshenup_check_start_time' );
                // Schedule cleanup for 1 minute later
                as_schedule_single_action(
                    time() + 60,
                    'freshenup_cleanup_cron',
                    array(
                        'post_id'   => (int) $post_id,
                        'prompt_id' => (int) $prompt_id,
                        'unique_id' => (int) $unique_id,
                    ),
                    'freshenup-cleanup'
                );
                // Optionally store failure status
                update_post_meta( $post_id, 'freshenup_status', 'failed' );
                return;
            case 'insufficient_quota':
                // Handle insufficient quota notification
                freshenup_send_email_notification( 'api_credit' );
                return;
        }
    }
}

// Add the action hook for the status check
add_action(
    'freshenup_check_job_status',
    'freshenup_check_job_status',
    10,
    3
);
// Add cleanup hook
add_action(
    'freshenup_cleanup_cron',
    'freshenup_unschedule_update',
    10,
    3
);
function freshenup_update_post_modified_date(  $post_id  ) {
    $post_data = array(
        'ID'                => $post_id,
        'post_modified'     => current_time( 'mysql' ),
        'post_modified_gmt' => current_time( 'mysql', 1 ),
    );
    wp_update_post( $post_data );
}

function freshenup_receive_new_content(
    $post_id,
    $prompt_id,
    $unique_id,
    $new_content,
    $summary_changes,
    $api_cost
) {
    $prompt_values = freshenup_get_prompt_values( $prompt_id );
    $post = get_post( $post_id );
    if ( !$post ) {
        return;
    }
    // Store previous content before modification
    update_post_meta( $post_id, 'freshenup_previous_content', $post->post_content );
    update_post_meta( $post_id, 'freshenup_new_content_date', current_time( 'mysql' ) );
    update_post_meta( $post_id, 'freshenup_old_content_date', $post->post_modified );
    update_post_meta( $post_id, 'freshenup_new_content', $new_content );
    update_post_meta( $post_id, 'freshenup_summary_changes', $summary_changes );
    update_post_meta( $post_id, 'freshenup_spent', $api_cost );
    update_post_meta( $post_id, 'freshenup_prompt_id', $prompt_id );
    // If moderation is disabled, apply content immediately
    if ( $prompt_values['moderate'] == esc_html__( 'Do not moderate', 'freshenup' ) ) {
        freshenup_apply_new_content( $post_id, $prompt_id, $new_content );
    } else {
        // Create a revision manually
        $post_array = get_post( $post_id, ARRAY_A );
        // Get as array to avoid modifying the object
        $post_array['post_content'] = $new_content;
        $post_array['post_status'] = 'inherit';
        $post_array['post_type'] = 'revision';
        $post_array['post_parent'] = $post_id;
        $post_array['post_date'] = current_time( 'mysql' );
        $post_array['post_date_gmt'] = current_time( 'mysql', 1 );
        unset($post_array['ID']);
        // Ensure WordPress creates a new revision
        $revision_id = wp_insert_post( $post_array );
        if ( $revision_id ) {
            // phpcs:ignore WordPress.NamingConventions.PrefixAllGlobals.NonPrefixedHooknameFound -- Intentionally firing WP core hook for compatibility
            do_action( '_wp_put_post_revision', $revision_id, $post_id );
        }
        // Mark post as awaiting moderation
        update_post_meta( $post_id, 'freshenup_awaiting_moderation', true );
        // Notify admin about pending moderation
        freshenup_send_email_notification( 'pending_posts' );
    }
}

function freshenup_apply_new_content(  $post_id, $prompt_id, $new_content  ) {
    if ( empty( $post_id ) || empty( $new_content ) ) {
        return;
    }
    // store a revision before applying changes
    freshenup_backup_current_post_revision( $post_id );
    $cleaned_content = freshenup_strip_all_freshenup_wrappers( $new_content );
    // Prepare the post data for update
    $post_data = array(
        'ID'                => $post_id,
        'post_content'      => $cleaned_content,
        'post_modified'     => current_time( 'mysql' ),
        'post_modified_gmt' => current_time( 'mysql', true ),
    );
    // Disable revision creation for this update since we already created one
    remove_action( 'pre_post_update', 'wp_save_post_revision' );
    // Update the post
    $update_result = wp_update_post( $post_data, true );
    // Re-enable revision creation
    add_action( 'pre_post_update', 'wp_save_post_revision' );
    if ( is_wp_error( $update_result ) ) {
        return $update_result;
    }
    // Store metadata about this update
    update_post_meta( $post_id, 'freshenup_last_update', current_time( 'mysql' ) );
    // Clear the updating flag
    delete_post_meta( $post_id, 'freshenup_updating' );
    return true;
}
