<?php
if ( ! defined( 'ABSPATH' ) ) exit; // Salir si se accede directamente

global $easy_gpt_total_cost;
$easy_gpt_total_cost = 0.0;

// Añadir prefijo único a las funciones
function easy_gpt_process_pending_generations() {

    // Verificar el estado de la licencia
    $license_status = get_option('easy_gpt_license_status');
    $license_expires = get_option('easy_gpt_license_expires');
    $is_license_valid = $license_status === 'valid' && new DateTime($license_expires) > new DateTime();

    // Si la licencia no es válida, detener la ejecución
    if ( ! $is_license_valid ) {
        return;
    }

    global $wpdb;
    $table_generations = $wpdb->prefix . 'bulk_generations';
    $table_tasks = $wpdb->prefix . 'article_generation_tasks';

	$current_time = current_time('timestamp');
	$timeout_threshold = $current_time - (10 * MINUTE_IN_SECONDS);
	$timeout_threshold_formatted = date_i18n('Y-m-d H:i:s', $timeout_threshold);

	// Obtén tareas estancadas correctamente
	$stuck_tasks = $wpdb->get_results($wpdb->prepare(
		"SELECT id, generation_id FROM {$table_tasks} 
		 WHERE status = %s AND updated_at < %s",
		'processing',
		$timeout_threshold_formatted
	));

	foreach ( $stuck_tasks as $task ) {
		// Actualizar la tarea estancada a 'failed'
		$wpdb->update(
			$table_tasks,
			[
				'status' => 'failed',
				'updated_at' => date_i18n('Y-m-d H:i:s', $current_time),
				'error_message' => 'Stuck' // Aquí añades claramente el motivo del fallo
			],
			['id' => intval($task->id)]
		);

		// Actualizar el estado de la generación asociada
		easy_gpt_update_generation_status(intval($task->generation_id));
	}

    // Procesar nuevas tareas pendientes por cada generación
		$generations = $wpdb->get_results(
			"SELECT id, status FROM {$table_generations} WHERE status IN ('pending', 'processing')"
		);

    foreach ( $generations as $generation ) {
		////error_log("La generación con ID {$generation->id} está en estado '{$generation->status}' y será procesada.");
        $active_processing_task = $wpdb->get_var( $wpdb->prepare(
            "SELECT COUNT(*) FROM {$table_tasks} WHERE generation_id = %d AND status = %s",
            intval( $generation->id ),
            'processing'
        ) );

        if ( ! $active_processing_task ) {
			$now = current_time('mysql');

			$next_pending_task = $wpdb->get_row( $wpdb->prepare(
				"SELECT id, article_params
					FROM {$table_tasks}
					WHERE generation_id = %d
					  AND status = 'pending'
					  AND (scheduled_for IS NULL OR scheduled_for <= %s)
					ORDER BY
					  CASE WHEN scheduled_for IS NOT NULL AND scheduled_for <= %s THEN 0 ELSE 1 END,
					  CASE WHEN scheduled_for IS NULL THEN 1 ELSE 0 END,
					  scheduled_for ASC,
					  id ASC
					LIMIT 1",
				intval($generation->id),
				$now,
				$now
			) );

            if ( $next_pending_task ) {
                $article_params_serialized = $wpdb->get_var(
                    $wpdb->prepare(
                        "SELECT article_params FROM {$table_tasks} WHERE id = %d",
                        intval($next_pending_task->id)
                    )
                );
                
                // 2️⃣  Deserializar / decodificar JSON
                $article_params = maybe_unserialize($article_params_serialized);
                if ( ! is_array($article_params) ) {
                    $article_params = json_decode($article_params_serialized, true);
                }
                
                /*  🔍 LOG #1 – Estado bruto antes de sanear
                 *  (Así vemos si llega bien user_id y todos los campos)
                 */
                //error_log('📦 article_params RAW: ' . print_r($article_params, true));
                //error_log('👤 user_id (RAW)   : ' . (isset($article_params['user_id']) ? $article_params['user_id'] : 'NO DEFINIDO'));
                
                // 3️⃣  Sanitizar
                $article_params = easy_gpt_sanitize_article_params($article_params);
                
                /*  🔍 LOG #2 – Después de sanear
                 *  (Comprobamos que no se haya perdido o convertido en 0)
                 */
                //error_log('📦 article_params SANITIZED: ' . print_r($article_params, true));
                //error_log('👤 user_id (SANITIZED): ' . (isset($article_params['user_id']) ? $article_params['user_id'] : 'NO DEFINIDO'));

                $wpdb->update(
                    $table_tasks,
                    [ 'status' => 'processing', 'updated_at' => $current_time ],
                    [ 'id' => intval( $next_pending_task->id ) ]
                );

                $wpdb->query( $wpdb->prepare(
                    "UPDATE {$table_generations} SET status = %s WHERE id = %d AND status = %s",
                    'processing',
                    intval( $generation->id ),
                    'pending'
                ) );

                if ( easy_gpt_generate_complete_article( intval( $next_pending_task->id ), $article_params ) ) {
                    $wpdb->update(
                        $table_tasks,
                        [ 'status' => 'completed', 'updated_at' => $current_time ],
                        [ 'id' => intval( $next_pending_task->id ) ]
                    );

                    // Sumar 1 al campo 'articles_generated' en 'bulk_generations'
                    $wpdb->query( $wpdb->prepare(
                        "UPDATE {$table_generations} SET articles_generated = articles_generated + 1 WHERE id = %d",
                        intval( $generation->id )
                    ) );
                } else {
                    $wpdb->update(
                        $table_tasks,
                        [ 'status' => 'failed', 'updated_at' => $current_time ],
                        [ 'id' => intval( $next_pending_task->id ) ]
                    );
                }

                easy_gpt_update_generation_status( intval( $generation->id ) );
            }
        }
    }
}

function easy_gpt_update_generation_status( $generation_id ) {
    global $wpdb;
    $table_tasks = $wpdb->prefix . 'article_generation_tasks';
    $table_generations = $wpdb->prefix . 'bulk_generations';

    $generation_id = intval( $generation_id );

    $current_status = $wpdb->get_var( $wpdb->prepare(
        "SELECT status FROM {$table_generations} WHERE id = %d",
        $generation_id
    ));

    $tasks = $wpdb->get_results( $wpdb->prepare(
        "SELECT status FROM {$table_tasks} WHERE generation_id = %d",
        $generation_id
    ) );

    $all_completed = true;
    $any_failed = false;

    foreach ( $tasks as $task ) {
        $status = sanitize_text_field( $task->status );
        if ( $status == 'pending' || $status == 'processing' ) {
            $all_completed = false;
        }
        if ( $status == 'failed' ) {
            $any_failed = true;
        }
    }

    if ($all_completed) {
        $new_status = $any_failed ? 'complete with errors' : 'completed';
    } else {
        // Si está en 'paused' o 'cancelled', y aún hay tareas pendientes, no cambiar el estado
        if (in_array($current_status, ['paused', 'cancelled'])) {
            return; // No actualizamos el estado
        }
        $new_status = 'processing';
    }
	
    $wpdb->update(
        $table_generations,
        [ 'status' => $new_status ],
        [ 'id' => $generation_id ]
    );
}

function easy_gpt_generate_complete_article( $task_id, $article_params ) {
    global $easy_gpt_total_cost, $wpdb;

    // Verificar si $article_params es una cadena JSON y decodificarla
    if ( is_string( $article_params ) ) {
        $article_params = json_decode( $article_params, true );
    }

    // Verificar si la decodificación fue exitosa
    if ( ! is_array( $article_params ) ) {
        return false;
    }

    // Sanitizar $article_params
    $article_params = easy_gpt_sanitize_article_params( $article_params );

    $content_type = isset($article_params['content_type']) ? $article_params['content_type'] : 'article';
    $is_product = ($content_type === 'product');
    
    ////error_log("Es un producto? $is_product");
    
    // Generar todos los componentes necesarios antes de crear el artículo
    $api_key = sanitize_text_field( get_option( 'easy_gpt_options' )['easy_gpt_api_key'] );

	// 1. Generar el título
	$title_response = easy_gpt_generate_title_via_cron($article_params);
	$table_tasks = $wpdb->prefix . 'article_generation_tasks';

	// Log para verificar si se obtuvo una respuesta
	//error_log("🔄 Intentando generar el título para la tarea ID: " . intval($task_id));

	if (!$title_response['success']) {
		// Log detallado del error
		//error_log("❌ Error al generar el título para la tarea ID: " . intval($task_id) . ". Error: " . $title_response['error']);

		// Guardar el mensaje de error en la base de datos
		$wpdb->update(
			$table_tasks,
			[
				'status' => 'failed',
				'updated_at' => current_time('mysql'),
				'error_message' => $title_response['error']
			],
			['id' => intval($task_id)]
		);

		// Log para confirmar que el error se guardó en la base de datos
		//error_log("📄 Error registrado en la base de datos para la tarea ID: " . intval($task_id));

		easy_gpt_update_generation_status(intval($task_id));

		return false;
	}

	// Log del título generado correctamente
	//error_log("✅ Título generado para la tarea ID: " . intval($task_id) . ". Título: " . $title_response['text']);

	$title = $title_response['text'];


    // 2. Generar el esquema
    $outline = easy_gpt_generate_outline_via_cron( array_merge( $article_params, [ 'title' => $title ] ) );
    if ( ! $outline ) {
        return false;
    }

    // 3. Generar el extracto
    $excerpt = easy_gpt_generate_excerpt_via_cron( array_merge( $article_params, [ 'title' => $title, 'outline' => $outline ] ) );
    if ( ! $excerpt ) {
        return false;
    }

    // 4. Generar el SEO
    $seo = easy_gpt_generate_seo_via_cron( array_merge( $article_params, [ 'title' => $title, 'outline' => $outline ] ) );
    if ( ! $seo ) {
        return false;
    }

    // 5. Generar las categorías
    $category_name = easy_gpt_generate_category_via_cron( array_merge( $article_params, [ 'title' => $title, 'outline' => $outline ] ) );
    if ( ! $category_name ) {
        return false;
    }


    $category_taxonomy = $is_product ? 'product_cat' : 'category';
    
    // Buscar la categoría en la taxonomía correspondiente
    $category_term = get_term_by('name', $category_name, $category_taxonomy);
    
    if (!$category_term) {
        // Si la categoría no existe, crearla en la taxonomía correcta
        $new_category = wp_insert_term($category_name, $category_taxonomy);
        if (!is_wp_error($new_category) && isset($new_category['term_id'])) {
            $category_id = intval($new_category['term_id']);
        } else {
            $category_id = null; // Si hay error, no asignamos categoría
        }
    } else {
        $category_id = intval($category_term->term_id);
    }

    // 6. Generar las etiquetas
    $tags = easy_gpt_generate_tags_via_cron( array_merge( $article_params, [ 'title' => $title, 'outline' => $outline ] ) );
    if ( ! $tags ) {
        return false;
    }

    // 7. Generar el contenido del artículo completo
    $article = easy_gpt_generate_article_via_cron( array_merge( $article_params, [ 'title' => $title, 'outline' => $outline ] ) );
    if ( ! $article ) {
        return false;
    }

// 8. Generar las imágenes
$image_urls = [];
if (!empty($article_params['auto_images'])) {
    $num_images = intval($article_params['num_images']);

    // Definir valores predeterminados si no están definidos
    $model = sanitize_text_field($article_params['model']);
    $temperature = isset($article_params['temperature']) ? round(floatval($article_params['temperature']), 2) : 0.7;

    for ($i = 0; $i < $num_images; $i++) {
        $current_image_number = $i + 1;
        $image_prompt = !empty($article_params['image_prompts'][$i]) 
            ? sanitize_text_field($article_params['image_prompts'][$i]) 
            : $article_params['prompt'];

        // LOG para verificar el número de imagen y datos relevantes
        //error_log("🔄 Generando imagen número: {$current_image_number} de un total de {$num_images}");

        $image_url_data = easy_gpt_generate_image_via_cron(array_merge(
            $article_params,
            [
                'title' => sanitize_text_field($title),
                'prompt' => sanitize_text_field($image_prompt),
                'outline' => sanitize_textarea_field($outline),
                'image_index' => $current_image_number,
                'total_images' => $num_images,
                'keywords' => sanitize_text_field($article_params['keywords']),
                'model' => sanitize_text_field($article_params['image_model']),
                'text_model' => sanitize_text_field($article_params['model']),
                'temperature' => $temperature,
                'image_size' => sanitize_text_field($article_params['image_size']),
                'image_quality' => sanitize_text_field($article_params['image_quality']),
                'image_style' => sanitize_text_field($article_params['image_style']),
                'language' => sanitize_text_field($article_params['language']),
                'writing_style' => sanitize_text_field($article_params['writing_style']),
                'writing_tone' => sanitize_text_field($article_params['writing_tone']),
                'content_type' => sanitize_text_field($article_params['content_type']),
            ]
        ));

        if ($image_url_data) {
            //error_log("✅ Imagen número {$current_image_number} generada correctamente: " . $image_url_data['image_url']);
            //error_log("📝 Título generado: " . $image_url_data['title']);
            //error_log("🖼️ Alt generado: " . $image_url_data['alt']);
            $image_urls[] = $image_url_data;
        } else {
            //error_log("❌ Error al generar la imagen número {$current_image_number}");
        }
    }

    if (empty($image_urls)) {
        //error_log("⚠️ No se generaron imágenes correctamente.");
        return false;
    }
}


//error_log('🧩 article_params: ' . print_r($article_params, true));
    // Obtener el autor predeterminado desde los ajustes
    $author_id = ! empty( $article_params['user_id'] )
        ? intval( $article_params['user_id'] )           // ← el que recibimos de la tarea
        : intval( get_option( 'easy_gpt_default_author', 1 ) ); // respaldo


    // Preparar los datos del artículo
    $post_data = [
        'post_title'    => sanitize_text_field( $title ),
        'post_content'  => wp_kses_post( $article ),
        'post_excerpt'  => sanitize_textarea_field( $excerpt ),
        'post_category' => [ $category_id ], // Usar el ID numérico de la categoría
        'tags_input'    => array_map( 'sanitize_text_field', explode( ', ', $tags ) ),
        'post_type'     => $is_product ? 'product' : 'post',
        'post_author'  => $author_id,
    ];


    // Verificar si debe publicarse inmediatamente o programarse
    if ( $article_params['publish_action'] === 'publish_immediately' ) {
        $post_data['post_status'] = 'publish';
    } elseif ( $article_params['publish_action'] === 'schedule' ) {
        // Programar la publicación
        $scheduled_date = isset( $article_params['scheduled_publish_date'] ) ? sanitize_text_field( $article_params['scheduled_publish_date'] ) : current_time( 'mysql' );
        $post_data['post_status']   = 'future';
        $post_data['post_date']     = $scheduled_date;
        $post_data['post_date_gmt'] = get_gmt_from_date( $scheduled_date );
    } else {
        $post_data['post_status'] = 'draft';
    }

    // 9. Crear el artículo en WordPress con todos los componentes
    $post_id = wp_insert_post( wp_slash( $post_data ) );

    if ( ! $post_id || is_wp_error( $post_id ) ) {
        return false;
    }


    if ($is_product && !empty($article_params['enable_product_prices'])) {
        easy_gpt_generate_product_price($article_params, $post_id, $title);
    }
    
    
    if ($is_product) {
        if ($category_id) {
            wp_set_object_terms($post_id, [$category_id], 'product_cat');
        }
    
        if (!empty($tags)) {
            $tag_names = array_map('sanitize_text_field', explode(',', $tags));
            $tag_ids = [];
    
            foreach ($tag_names as $tag_name) {
                $tag_term = get_term_by('name', trim($tag_name), 'product_tag');
                if (!$tag_term) {
                    $new_tag = wp_insert_term(trim($tag_name), 'product_tag');
                    if (!is_wp_error($new_tag)) {
                        $tag_ids[] = intval($new_tag['term_id']);
                    }
                } else {
                    $tag_ids[] = intval($tag_term->term_id);
                }
            }
    
            if (!empty($tag_ids)) {
                wp_set_object_terms($post_id, $tag_ids, 'product_tag');
            }
        }
    }

// 10. Descargar y asignar las imágenes a la biblioteca de medios
if (!empty($article_params['auto_images'])) {
    require_once ABSPATH . 'wp-admin/includes/file.php';
    require_once ABSPATH . 'wp-admin/includes/media.php';
    require_once ABSPATH . 'wp-admin/includes/image.php';

    $image_ids         = [];
    $local_image_urls  = []; // Aquí se guardarán las URLs de las imágenes en WordPress

    foreach ($image_urls as $index => $image_data) {
        $image_url = esc_url_raw($image_data['image_url']);
        $image_title = sanitize_text_field($image_data['title']); // Título limpio para uso en el título
        $image_alt = sanitize_text_field($image_data['alt']); // Alt de la imagen

        // Preparar un nombre de archivo basado en el título
        $filename = sanitize_title($image_title) . '.jpg';

        // Descargar la imagen a una ubicación temporal
        $tmp = download_url($image_url);
        if (is_wp_error($tmp)) {
            continue; // Saltar si la descarga falla
        }

        // Preparar el archivo para la carga
        $file_array = [
            'name'     => $filename,
            'tmp_name' => $tmp,
        ];

        // Subir la imagen a la biblioteca de medios
        $image_id = media_handle_sideload($file_array, $post_id, $image_title);

        // Si hubo un error al subir, eliminar el archivo temporal y continuar
        if (is_wp_error($image_id)) {
            @unlink($file_array['tmp_name']);
            continue;
        }

        // Guardar los datos de la imagen en arrays
        $image_ids[] = intval($image_id);
        $local_image_url = wp_get_attachment_url($image_id);
        $local_image_urls[] = esc_url($local_image_url);

        // Asignar título y alt a la imagen correctamente
        wp_update_post([
            'ID' => $image_id,
            'post_title' => $image_title,
            'post_name' => sanitize_title($image_title),
        ]);

        update_post_meta($image_id, '_wp_attachment_image_alt', $image_alt);
    }

    // 11. Establecer la primera imagen como destacada si está configurado
    if (!empty($article_params['set_featured_image']) && !empty($image_ids)) {
        set_post_thumbnail($post_id, $image_ids[0]);

        // Actualizar título y alt de la imagen destacada
        $featured_image_data = $image_urls[0];
        $featured_image_id = $image_ids[0];

        wp_update_post([
            'ID' => $featured_image_id,
            'post_title' => sanitize_text_field($featured_image_data['title']),
        ]);

        update_post_meta($featured_image_id, '_wp_attachment_image_alt', sanitize_text_field($featured_image_data['alt']));
    }

    // 12. Insertar imágenes en el contenido del artículo usando las URLs locales
    $new_content = easy_gpt_insert_images_into_content($article, $local_image_urls, $article_params['set_featured_image']);
	wp_update_post( wp_slash([
		'ID' => $post_id,
		'post_content' => wp_kses_post($new_content),
	]) );
}


    // 13. Guardar el SEO meta
    if ( ! empty( $seo['seo_title'] ) ) {
        update_post_meta( $post_id, '_yoast_wpseo_title', sanitize_text_field( $seo['seo_title'] ) );
    }
    if ( ! empty( $seo['seo_description'] ) ) {
        update_post_meta( $post_id, '_yoast_wpseo_metadesc', sanitize_textarea_field( $seo['seo_description'] ) );
    }

    // 14. Actualizar el coste total y los tokens utilizados
    update_post_meta( $post_id, '_easy_gpt_cost', floatval( $easy_gpt_total_cost ) );

    // Después de generar y calcular el coste del artículo, actualiza la base de datos
    $table_generations = $wpdb->prefix . 'bulk_generations';

    // Obtén la generación a la que pertenece esta tarea
    $generation_id = $wpdb->get_var( $wpdb->prepare(
        "SELECT generation_id FROM {$wpdb->prefix}article_generation_tasks WHERE id = %d",
        intval( $task_id )
    ) );

    $generation_id = intval( $generation_id );

    // Actualiza el coste total en la tabla de generaciones en masa
    $wpdb->query( $wpdb->prepare(
        "UPDATE {$table_generations} SET total_cost = total_cost + %f WHERE id = %d",
        floatval( $easy_gpt_total_cost ),
        $generation_id
    ) );

    // Actualiza el coste total en la tabla de tareas
    $wpdb->query( $wpdb->prepare(
        "UPDATE {$wpdb->prefix}article_generation_tasks SET cost = %f WHERE id = %d",
        floatval( $easy_gpt_total_cost ),
        intval( $task_id )
    ) );

    return true;
}

// Programar la tarea cron con prefijo único
if (!wp_next_scheduled('easy_gpt_process_pending_generations')) {
    wp_schedule_event(time(), 'five_minutes', 'easy_gpt_process_pending_generations');
}

add_action('easy_gpt_process_pending_generations', 'easy_gpt_process_pending_generations');

function easy_gpt_add_cron_interval($schedules) {
    $schedules['five_minutes'] = array(
        'interval' => 300, // 300 segundos = 5 minutos
        'display' => esc_html__('Every Five Minutes', 'easy-gpt-for-wp')
    );
    return $schedules;
}
add_filter('cron_schedules', 'easy_gpt_add_cron_interval');

/* Funciones para generar artículos */

function easy_gpt_sanitize_article_params($params) {
    $sanitized_params = [];
    foreach ($params as $key => $value) {
        if (is_array($value)) {
            $sanitized_params[$key] = easy_gpt_sanitize_article_params($value);
        } else {
            $sanitized_params[$key] = is_numeric($value) ? $value : sanitize_text_field($value);
        }
    }
    return $sanitized_params;
}

function easy_gpt_generate_product_price($article_params, $post_id, $title) {
    global $wpdb;

    // Obtener la moneda configurada en WooCommerce
    $currency = get_option('woocommerce_currency', 'USD'); // Si no hay configuración, por defecto USD

    // Verificar si el usuario ha proporcionado un precio manual
    if (!empty($article_params['product_prices'])) {
        $prices = explode("\n", trim($article_params['product_prices']));
        $price = floatval(trim($prices[0])); // Tomar el primer precio disponible
    } else {
        // Si no hay precio manual, generarlo con OpenAI
        $prompt = "Generate a reasonable price for a product titled '{$title}' in {$currency}. The response must be only a numeric value, without any currency symbol, letters, or additional text.";

        $response = easy_gpt_call_openai_api_no_session($prompt, $article_params['model'], $article_params['temperature'], get_option('easy_gpt_options')['easy_gpt_api_key']);

        // Extraer solo números
        $price = isset($response['text']) ? floatval(preg_replace('/[^0-9.]/', '', $response['text'])) : 0;

        // Si la IA no devuelve un número válido, asignar un precio por defecto
        if ($price <= 0) {
            $price = rand(10, 100); // Precio aleatorio entre 10 y 100 si OpenAI falla
        }
    }

    // Guardar el precio en el meta de WooCommerce
    update_post_meta($post_id, '_regular_price', $price);
    update_post_meta($post_id, '_price', $price); // WooCommerce usa _price como campo principal
    update_post_meta($post_id, '_currency', $currency); // Opcional: almacenar la moneda usada

    return $price;
}

function easy_gpt_generate_title_via_cron($article_params) {
    // Verificar y sanitizar los parámetros necesarios
    $prompt = $article_params['prompt'];
    $keywords = $article_params['keywords'];
    $specific_instructions = $article_params['specific_instructions_title'];
    $model = $article_params['model'];
    $temperature = $article_params['temperature'];
    $language = $article_params['language'];
    $writing_style = $article_params['writing_style'];
    $writing_tone = $article_params['writing_tone'];
    $api_key = get_option('easy_gpt_options')['easy_gpt_api_key'];

    // Determinar si es un artículo o un producto
    $entity_type = ($article_params['content_type'] === 'product') ? "product" : "article";

    // Crear el prompt completo
    $full_prompt = "Title Generation for a {$entity_type}: Using the prompt '$prompt', keywords '$keywords', and specific instructions '$specific_instructions', generate a title that fits the style '$writing_style' and tone '$writing_tone' in '$language' language. Only return the title without enclosing it in quotes.";

    // Log del prompt y parámetros
    //error_log("🔄 Generando título para '{$entity_type}':");
    //error_log("Prompt: $full_prompt");
    //error_log("Modelo: $model, Temperatura: $temperature, Lenguaje: $language");

    // Llamada a la API
    $response = easy_gpt_call_openai_api_no_session($full_prompt, $model, $temperature, $api_key);

    // Log de la respuesta cruda
    //error_log("📩 Respuesta recibida en generate_title: " . print_r($response, true));

    // Manejo de errores y respuesta
    if (!$response || !isset($response['text'])) {
        $error_message = isset($response['error']) ? $response['error'] : 'Unknown error generating title.';
        //error_log("❌ Error al generar el título: $error_message");

        return [
            'success' => false,
            'error' => sanitize_text_field($error_message)
        ];
    }

    //error_log("✅ Título generado correctamente: " . $response['text']);

    return [
        'success' => true,
        'text' => sanitize_text_field($response['text'])
    ];
}

function easy_gpt_generate_outline_via_cron($article_params) {
    $prompt = $article_params['prompt'];
    $keywords = $article_params['keywords'];
    $title = $article_params['title'];
    $specific_instructions = $article_params['specific_instructions_outline'];
    $num_subheadings = intval($article_params['num_subheadings']);
    $type_subheadings = $article_params['subheading_types'];
    $min_words = intval($article_params['min_words']);
    $max_words = intval($article_params['max_words']);
    $model = $article_params['model'];
    $temperature = $article_params['temperature'];
    $language = $article_params['language'];
    $writing_style = $article_params['writing_style'];
    $writing_tone = $article_params['writing_tone'];
    $api_key = get_option('easy_gpt_options')['easy_gpt_api_key'];

    $subheading_instructions = '';
    if (strpos($type_subheadings, 'H3') !== false) {
        $subheading_instructions .= "Mark 'H3' subheadings with a '## ' prefix. ";
    }
    if (strpos($type_subheadings, 'H4') !== false) {
        $subheading_instructions .= "Mark 'H4' subheadings with '### ' prefix. ";
    }

    // Determinar si es un artículo o un producto
    $entity_type = ($article_params['content_type'] === 'product') ? "product" : "article";

    $full_prompt = "Generate an outline for a {$entity_type} titled '{$title}' with the following details (only return the headings, don't explain anything, do not include an introduction or conclusion):\n" .
                   "Prompt: {$prompt}\n" .
                   "Keywords: {$keywords}\n" .
                   "Specific instructions: {$specific_instructions}\n" .
                   "Number of H2 Subheadings: {$num_subheadings} (create only {$num_subheadings} h2 subheadings)\n" .
                   "Total Words for the {$entity_type}: Minimum {$min_words} words, Maximum {$max_words} words.\n" .
                   "Ensure the outline and the number of sections are appropriate for the total word count of the {$entity_type}.\n" .
                   "Type of Additional Subheadings you can use (only if necessary): {$type_subheadings} (Place each subheading on a new line. Mark 'H2' subheadings with a '# ' prefix. {$subheading_instructions})\n" .
                   "Language: {$language}\n" .
                   "Writing Style: {$writing_style}\n" .
                   "Tone: {$writing_tone}\n" .
                   "Incorporate the keyword '{$keywords}' naturally in about half of the headings. Ensure the headings are varied and do not repeat the keyword in each heading.";


    $response = easy_gpt_call_openai_api_no_session($full_prompt, $model, $temperature, $api_key);

    return isset($response['text']) ? sanitize_textarea_field($response['text']) : false;
}

function easy_gpt_generate_excerpt_via_cron($article_params) {
    $title = $article_params['title'];
    $prompt = $article_params['prompt'];
    $keywords = $article_params['keywords'];
    $outline = $article_params['outline'];
    $specific_instructions_excerpt = $article_params['specific_instructions_excerpt'];
    $model = $article_params['model'];
    $temperature = $article_params['temperature'];
    $language = $article_params['language'];
    $writing_style = $article_params['writing_style'];
    $writing_tone = $article_params['writing_tone'];
    $api_key = get_option('easy_gpt_options')['easy_gpt_api_key'];

    $entity_type = ($article_params['content_type'] === 'product') ? "product" : "article";
    
   $full_prompt = "Generate an excerpt for a {$entity_type} titled '{$title}' with the following details:\n" .
                   "Prompt: {$prompt}\n" .
                   "Keywords: {$keywords}\n" .
                   "Outline: {$outline}\n" .
                   "Specific Instructions for Excerpt: {$specific_instructions_excerpt}\n" .
                   "Language: {$language}\n" .
                   "Writing Style: {$writing_style}\n" .
                   "Tone: {$writing_tone}\n" .
                   "Maximum Words for the excerpt: 60 words. Do not include the title in the excerpt.";

    $response = easy_gpt_call_openai_api_no_session($full_prompt, $model, $temperature, $api_key);

    return isset($response['text']) ? sanitize_textarea_field($response['text']) : false;
}

function easy_gpt_generate_seo_via_cron($article_params) {
    $title = $article_params['title'];
    $prompt = $article_params['prompt'];
    $keywords = $article_params['keywords'];
    $outline = $article_params['outline'];
    $model = $article_params['model'];
    $temperature = $article_params['temperature'];
    $language = $article_params['language'];
    $writing_style = $article_params['writing_style'];
    $writing_tone = $article_params['writing_tone'];
    $api_key = get_option('easy_gpt_options')['easy_gpt_api_key'];

    // Determinar si es un artículo o un producto
    $entity_type = ($article_params['content_type'] === 'product') ? "product" : "article";
    
    // Generar el título SEO
    $prompt_title = "Generate an SEO-friendly metatitle for a {$entity_type} with the following details, ensuring the metatitle does not exceed 60 characters (only return the metatitle without enclosing it in quotes):\n" .
                    "Title: {$title}\n" .
                    "Prompt: {$prompt}\n" .
                    "Keywords: {$keywords}\n" .
                    "Outline: {$outline}\n" .
                    "Language: {$language}\n" .
                    "Writing Style: {$writing_style}\n" .
                    "Tone: {$writing_tone}";
    
    // Generar la meta descripción SEO
    $prompt_description = "Generate an SEO-friendly metadescription for a {$entity_type} with the following details, ensuring the metadescription does not exceed 155 characters (only return the metadescription without enclosing it in quotes):\n" .
                          "Title: {$title}\n" .
                          "Prompt: {$prompt}\n" .
                          "Keywords: {$keywords}\n" .
                          "Outline: {$outline}\n" .
                          "Language: {$language}\n" .
                          "Writing Style: {$writing_style}\n" .
                          "Tone: {$writing_tone}";

    $title_response = easy_gpt_call_openai_api_no_session($prompt_title, $model, $temperature, $api_key);
    $description_response = easy_gpt_call_openai_api_no_session($prompt_description, $model, $temperature, $api_key);

    return [
        'seo_title' => isset($title_response['text']) ? sanitize_text_field($title_response['text']) : '',
        'seo_description' => isset($description_response['text']) ? sanitize_textarea_field($description_response['text']) : '',
        'total_cost' => floatval($title_response['total_cost'] ?? 0) + floatval($description_response['total_cost'] ?? 0),
    ];
}

function easy_gpt_generate_category_via_cron($article_params) {
    $title = $article_params['title'];
    $prompt = $article_params['prompt'];
    $outline = $article_params['outline'];
    $model = $article_params['model'];
    $temperature = $article_params['temperature'];
    $language = $article_params['language'];
    $keywords = $article_params['keywords'];
    $api_key = get_option('easy_gpt_options')['easy_gpt_api_key'];

    // Determinar si es un artículo o un producto
    $is_product = ($article_params['content_type'] === 'product');
    $taxonomy = $is_product ? 'product_cat' : 'category';

    // Obtener las categorías disponibles en la taxonomía correspondiente
    $categories = get_terms(['taxonomy' => $taxonomy, 'hide_empty' => false]);
    $category_names = array_map(function($cat) {
        return $cat->name;
    }, $categories);
    $category_list = !empty($category_names) ? implode(", ", $category_names) : "None available";

    // Construir el prompt basado en si es un artículo o un producto
    $entity_type = $is_product ? "product" : "article";
    $full_prompt = "Given the existing {$entity_type} categories: {$category_list}. Suggest only 1 category for a {$entity_type} titled '{$title}' with details:\n" .
                   "Prompt: {$prompt}\n" .
                   "Outline: {$outline}\n" .
                   "Keywords: {$keywords}\n" .
                   "Language: {$language}\n" .
                   "Only return the name of the category";

    // Llamada a OpenAI para obtener la categoría sugerida
    $response = easy_gpt_call_openai_api_no_session($full_prompt, $model, $temperature, $api_key);

    return isset($response['text']) ? sanitize_text_field($response['text']) : false;
}


function easy_gpt_generate_tags_via_cron($article_params) {
    $title = $article_params['title'];
    $prompt = $article_params['prompt'];
    $outline = $article_params['outline'];
    $model = $article_params['model'];
    $temperature = $article_params['temperature'];
    $language = $article_params['language'];
    $keywords = $article_params['keywords'];
    $api_key = get_option('easy_gpt_options')['easy_gpt_api_key'];

    // Determinar si es un artículo o un producto
    $entity_type = ($article_params['content_type'] === 'product') ? "product" : "article";
    
    $full_prompt = "Suggest 3 tags for a {$entity_type} titled '{$title}' with details:\n" .
                   "Prompt: {$prompt}\n" .
                   "Outline: {$outline}\n" .
                   "Keywords: {$keywords}\n" .
                   "Language: {$language}\n" .
                   "Only return the 3 tags separated by comma without # symbol";


    $response = easy_gpt_call_openai_api_no_session($full_prompt, $model, $temperature, $api_key);

    return isset($response['text']) ? sanitize_text_field($response['text']) : false;
}

function easy_gpt_generate_article_via_cron($article_params) {
    // Verificar si $article_params es una cadena JSON y decodificarla
    if (is_string($article_params)) {
        $article_params = json_decode($article_params, true);
    }

    // Verificar si la decodificación fue exitosa
    if (!is_array($article_params)) {
        return false;
    }

    // Extraer los parámetros necesarios
    $title = $article_params['title'];
    $prompt = $article_params['prompt'];
    $keywords = $article_params['keywords'];
    $outline = $article_params['outline'];
    $specific_instructions_content = $article_params['specific_instructions_content'];
    $min_words = intval($article_params['min_words']);
    $max_words = intval($article_params['max_words']);
    $model = $article_params['model'];
    $temperature = $article_params['temperature'];
    $language = $article_params['language'];
    $writing_style = $article_params['writing_style'];
    $writing_tone = $article_params['writing_tone'];
    $api_key = get_option('easy_gpt_options')['easy_gpt_api_key'];
	$include_citations = isset($article_params['include_citations_bulk']) ? boolval($article_params['include_citations_bulk']) : false;
	$final_review = isset($article_params['final_review_bulk']) ? boolval($article_params['final_review_bulk']) : false;

    $format_article = isset($article_params['format_article']) ? $article_params['format_article'] : false;
    $includeBibliography = isset($article_params['include_bibliography']) ? $article_params['include_bibliography'] : false;
    $includeLinks = isset($article_params['include_links']) ? $article_params['include_links'] : false;

    $links_instructions = $includeLinks ? " You can insert links using <a> tags to justify data or claims, recommendations in the middle of the text, for example, according to a study made by <a> ... </a>, if possible use the name for the link, but do not say for more information." : "";

    $bibliography_instructions = $includeBibliography 
        ? " Include a bibliography at the end of the article using Chicago style. If the source is an online medium, include the link using <a> </a> tags. Use <h2> as a header for the bibliography section. The bibliography must only include entries with complete and real data. If specific data is missing (e.g., author name, title, publication date, URL), do not include that entry. The bibliography should not exceed 200 words. Return both the conclusion and the bibliography, and if you don't have enough data to generate a proper bibliography, omit the bibliography section entirely."
        : "(only return the conclusion)";
    
    $format_instructions = $format_article ? " and use <i>italic</i> tags for scientific terms or foreign words, and <b>bold</b> tags for significant phrases or parts of sentences that emphasize major findings, novel ideas, or critical points, characteristics, facts, or also to make the lecture easy." : "";

    // Determinar si es un artículo o un producto
    $entity_type = ($article_params['content_type'] === 'product') ? "product" : "article";

    // **Campos de Video Añadidos**
    $include_video = isset($article_params['include_videos_bulk']) ? boolval($article_params['include_videos_bulk']) : false;
    $video_position = isset($article_params['video_position_bulk']) ? sanitize_text_field($article_params['video_position_bulk']) : 'end';
    $after_paragraph = isset($article_params['video_paragraph_bulk']) ? max(1, intval($article_params['video_paragraph_bulk'])) : 3;

//error_log("DEBUG: include_videos_bulk = " . ($include_video ? 'true' : 'false'));
//error_log("DEBUG: video_position_bulk = " . $video_position);
//error_log("DEBUG: video_paragraph_bulk = " . $after_paragraph);

    $include_video_flag = $include_video ? '1' : '0';
    //error_log("DEBUG: video_flag = " . $include_video_flag);
    $video_result = easy_gpt_get_youtube_video_url($title, $keywords, $language, $include_video_flag);


    $video_url = isset($video_result['video_url']) ? $video_result['video_url'] : '';

    // Generar la introducción
    $intro_prompt = "Generate an introduction for a {$entity_type} titled '{$title}' with the following details, formatted with <p> tags for each paragraph{$format_instructions}, do not include the title in the introducction, do not use # or * and <html> tag, (only return the introduction):\n" .
                    "Prompt: {$prompt}\n" .
                    "Keywords: {$keywords}\n" .
                    "Language: {$language}\n" .
                    "Writing Style: {$writing_style}\n" .
                    "Tone: {$writing_tone}\n" .
                    "Maximum Words for the introduction: 200 words.\n";


    $intro_response = easy_gpt_call_openai_api_no_session($intro_prompt, $model, $temperature, $api_key);

    if (!$intro_response) {
        return false;
    }

    $responses = [$intro_response['text']];

    if (!empty($video_url) && $include_video) {
        if ($video_position === 'start') {
            $responses[0] .= "$video_url"; // Después de la introducción
        }
    }

    // Dividir el outline en secciones H2, H3, H4
    $sections = explode("\n", $outline);
    $h2_sections = [];
    $current_h2 = null;

    foreach ($sections as $section) {
        $section = trim($section);

        if (substr($section, 0, 2) === '# ') {
            if ($current_h2) {
                $h2_sections[] = $current_h2;
            }
            $current_h2 = [$section];
        } elseif ($current_h2) {
            $current_h2[] = $section;
        }
    }

    if ($current_h2) {
        $h2_sections[] = $current_h2;
    }

    $min_words_per_section = $min_words / max(count($h2_sections), 1);
    $max_words_per_section = $max_words / max(count($h2_sections), 1);

	$citation_instructions = $include_citations
    ? " and blockquotes (`<i>`) (blockquotes only if necesary) with the autor name (like real) where relevant." 
    : ".";
	
	$citation_instructions2 = $include_citations
    ? ", blockquotes (with the person of the quote), " 
    : " ";	
	 
	
	
    foreach ($h2_sections as $index => $h2_section) {
        //error_log("Generando...");
        
        $h2_title = array_shift($h2_section);
        //error_log($h2_title);
        $h3_h4 = implode("\n", $h2_section);
        if (empty($h3_h4)) {
            $h3_h4 = "do not use any subheading.";
        }

		////error_log("Contenido previo - ". $index . ": ". $previous_content);
		$previous_content = implode("\n", $responses); // Unir todo lo generado hasta el momento
		

$section_prompt = "Continue writing the article about {$entity_type} titled '{$title}', ensuring a smooth transition from the previous sections. Avoid repeating general information already covered.

Previously written sections:\n{$previous_content}\n

Generate a detailed section with the following details:

- Section Title: {$h2_title}
- Subheadings: {$h3_h4}
- Format: Use proper HTML tags, like <h2> for section titles, <h3>, <h4> for subheadings, <p> for paragraphs, and <ul><li> for lists, and <blockquote> for quotes. {$format_instructions}.  
  - Do not use # and <html> tag.
  - Important: In the section Apply bold <b> for key concepts, important phrases, and crucial data.  
  - Apply italics <i> to scientific terms, foreign words...  
  - Incorporate lists (`<ul><li>`){$citation_instructions}
  - Ensure these formatting elements appear naturally throughout the entire section, not just in the introduction or conclusion.
  - Before introducing any `<h3>` or `<h4>`, ensure there is a short introductory paragraph (2-3 sentences) explaining what will be covered in the subsection.

---

Refining Introductions and Transitions:
* Vary how the section starts: Instead of beginning with a direct statement about the topic, consider alternative openings:  
   - Ask a rhetorical question to engage the reader.  
   - Use an intriguing fact or statistic to draw attention.  
   - Introduce a brief anecdote or historical reference (if relevant).  
   - Make a comparison or contrast with another related concept.  
*Avoid starting multiple sections or paragraphs with the same noun or phrase. Instead, use synonyms, rephrase, or introduce the idea in a different way.  
*Make transitions natural and fluid, do not use always the same, variety
*Ensure logical connections between subtopics, so the article flows smoothly rather than feeling fragmented.  

---

The section must begin with a short, engaging introduction that: 
   - Do not start by repeating the article’s main topic.  
   - Introduce the section in a natural and engaging way to maintain reader interest.  
   - Avoid generic phrasing—connect the section to the broader article context.  
   - You can use a rhetorical question.

Detailed Section Development
- Expand each subheading into 2-4 paragraphs.  
- Use lists{$citation_instructions2}or tables when appropriate to improve readability.  
- Introduce new insights rather than restating previous content.  
- Add real-world examples, statistics, or historical context where relevant.
- {$links_instructions}

---

### Enhancing Readability and Style
- Avoid repetitive sentence structures (e.g., multiple paragraphs starting with the same noun or phrase).  
- If a keyword (singular or plural) appeared in the first 20 words of the last 3 paragraphs, avoid it in the new paragraph.
- Diversify sentence structures: Mix short and long sentences, use subordinate clauses, and include comparisons or rhetorical questions.
- Ensure a smooth, engaging flow that keeps the reader interested.  
- Use proper linking phrases for smooth transitions between subtopics. 

---

Formatting Consistency
Ensure proper distribution of formatting elements:  
  - Bold (`<b>`) should emphasize key facts, not entire sentences.  
  - Italics (`<i>`) should highlight technical terms and foreign words.  
  - Lists and blockquotes should naturally complement the content, rather than being forced in.  
  - Dont use ** or *, use <b> or <i> insteed

---

- Prompt: {$prompt}  
- Keywords: {$keywords}  
- Specific Instructions: {$specific_instructions_content}  
- Language: {$language}  
- Style: {$writing_style}  
- Tone: {$writing_tone}  

- Do not forget Apply bold <b> for key concepts, important phrases, and crucial data. 
- Word Limit: Between {$min_words_per_section} and {$max_words_per_section} words.  

{$links_instructions}";


		////error_log($section_prompt);

        $response = easy_gpt_call_openai_api_no_session($section_prompt, $model, $temperature, $api_key, $post_id);

        if (!$response) {
            wp_send_json_error(['message' => "Failed to generate section for '{$h2_title}'"]);
            wp_die();
        }

        $responses[] = $response['text'];

        // Insertar video si la opción es 'random' y esta es la sección seleccionada
        if (!empty($video_url) && $include_video && $video_position === 'random' && $index === $insert_video_after_section) {
            $responses[] .= "$video_url";
        }
    }

    // Generar la conclusión

    if (!empty($video_url) && $include_video && $video_position === 'end') {
        $responses[] .= "$video_url";
    }

	$previous_content = implode("\n", $responses); // Unir todo el contenido generado antes de la conclusión

	$conclusion_prompt = "Generate a strong conclusion for a {$entity_type} titled '{$title}'. The conclusion should summarize the main insights without repeating detailed information already covered. Ensure a natural and engaging closing statement.

	Previously written content:\n{$previous_content}\n

	Consider the key points from this outline: {$outline}. Format the conclusion with <p> tags for each paragraph{$format_instructions}. Provide a <h2> heading that naturally summarizes the key message of the conclusion, avoiding generic titles like 'Conclusion'.\n

	Prompt: {$prompt}\n
	Keywords: {$keywords}\n
	Language: {$language}\n
	Writing Style: {$writing_style}\n
	Tone: {$writing_tone}\n
	Maximum Words for the conclusion: 200 words.\n
	{$bibliography_instructions}";


    $conclusion_response = easy_gpt_call_openai_api_no_session($conclusion_prompt, $model, $temperature, $api_key, $post_id);

    if (!$conclusion_response) {
        wp_send_json_error(['message' => "Failed to generate conclusion"]);
        wp_die();
    }

    $responses[] = $conclusion_response['text'];


	$full_article = implode("\n", $responses);

	$is_deepseek = strpos($model, 'deepseek-') === 0;

	if ($final_review && !$is_deepseek) {	

		// 📌 **Paso adicional: Revisar el artículo después de la conclusión pero antes del video**
		$review_prompt = "Here is a complete article about {$entity_type} titled '{$title}'. Review and refine it to improve coherence, eliminate redundancies, and ensure a more natural flow.

	Previously written content:\n{$full_article}\n

	Instructions for Refinement:
	- Each section (H2) must start with a short, engaging introduction (2-3 sentences) if missing.
	- Ensure a logical transition between sections and subheadings (H3, H4).
	- Avoid repetitive sentence structures: Do not start multiple paragraphs with the same noun or phrase.
	- Reword initial sentences to introduce variety while keeping the meaning intact.
	- Do not add new information—only refine and optimize existing content.
	- Summarize the conclusion concisely without repeating details already covered.
	- Use bold (`<b>`) for key concepts, important phrases, and crucial data.  
	- Apply italics (`<i>`) to scientific terms, foreign words...  
	- Use <a> for links
	- If there are ** or * change per <b> or <i> tags

	Formatting Instructions:
	- Maintain proper structure using <h2> for section titles, <h3> and <h4> for subheadings, <p> for paragraphs, and <ul><li> for lists and  <i> for quotes, {$format_instructions}, do not write <html> tag.
	- If a YouTube URL is present, leave it unchanged.

	Only return the review article, whithout any notes.

	Article for Review:
	{$full_article}"; 


		$review_response = easy_gpt_call_openai_api($review_prompt, $model, $temperature, $api_key, $post_id);

		if (!$review_response) {
			wp_send_json_error(['message' => "Failed to review the article"]);
			wp_die();
		}

		// Reemplazar el contenido con la versión revisada
		$full_article = easy_gpt_clean_response_text($review_response['text']);
			
	}
	else{
		$full_article = easy_gpt_clean_response_text($full_article);
	}

	// 📌 **Solo ahora, insertar el video si corresponde**
	if (!empty($video_url) && $include_video && $video_position === 'after_paragraph') {
		$paragraphs = preg_split('/(<p\b[^>]*>.*?<\/p>)/i', $full_article, -1, PREG_SPLIT_DELIM_CAPTURE | PREG_SPLIT_NO_EMPTY);

		//error_log("Total paragraphs found: " . count($paragraphs));
		//error_log("After paragraph number: " . $after_paragraph);

		// Validar el número de párrafos
		if ($after_paragraph > 0 && $after_paragraph <= count($paragraphs)) {
			// Insertar el video después del párrafo especificado
			$insert_index = $after_paragraph;
			if (isset($paragraphs[$insert_index])) {
				array_splice($paragraphs, $insert_index, 0, "\n<p>{$video_url}</p>\n");
				//error_log("Inserted video after paragraph {$after_paragraph}.");
			} else {
				$paragraphs[] = "\n<p>{$video_url}</p>\n";
				//error_log("Paragraph index {$insert_index} not found. Inserted video at the end.");
			}
		} else {
			$paragraphs[] = "\n<p>{$video_url}</p>\n";
			//error_log("After paragraph number {$after_paragraph} exceeds paragraph count. Inserted video at the end.");
		}

		$full_article = implode("", $paragraphs);
	}

    // Combinar todas las secciones del artículo en una sola variable
    $generated_article = $full_article;

    return wp_kses_post($generated_article);
}

function easy_gpt_generate_image_via_cron($article_params) {
    $prompt = $article_params['prompt'];
    $keywords = $article_params['keywords'];
    $title = $article_params['title'];
    $outline = $article_params['outline'];
    $model = $article_params['image_model'];
    $text_model = $article_params['text_model'] ?? $article_params['text_model']; // Usar 'model' si 'text_model' no está definido
    $temperature = isset($article_params['temperature']) ? round(floatval($article_params['temperature']), 2) : 0.7;
    $image_index = $article_params['image_index'];
    $total_images = $article_params['total_images'];
    $image_size = $article_params['image_size'];
    $image_quality = $article_params['image_quality'];
    $image_style = $article_params['image_style'];
    $language = $article_params['language'];
    $writing_style = $article_params['writing_style'];
    $writing_tone = $article_params['writing_tone'];
    $api_key = get_option('easy_gpt_options')['easy_gpt_api_key'];
    $entity_type = ($article_params['content_type'] === 'product') ? "product" : "article";

    // Log inicial
    //error_log("Iniciando generación de imagen para el índice {$image_index} de un total de {$total_images}");

    // Proceso de selección del subtítulo
    $selected_subtitle = '';
    $subtitles = array_filter(array_map('trim', explode("\n", $outline)));
    $total_subtitles = count($subtitles);

    if ($image_index == 1 || $total_subtitles === 0 || $total_images <= 1) {
        $selected_subtitle = $title;
    } else {
        $block_size = max(1, ceil($total_subtitles / max(1, ($total_images - 1))));
        $start_index = max(0, ($image_index - 2) * $block_size);
        $end_index = min($total_subtitles, $start_index + $block_size);

        $available_subtitles = array_slice($subtitles, $start_index, $end_index - $start_index);
        $selected_subtitle = $available_subtitles[array_rand($available_subtitles)] ?? $title;
    }

    //error_log("Subtítulo seleccionado para la imagen {$image_index}: {$selected_subtitle}");

    // 1. Generar TITLE
    $title_prompt = "Generate an original, unique, and concise title for an image of an article. The title should reflect a specific aspect or detail of the image and be relevant to the following context:\n" .
                    "Selected Subtitle or Title: {$selected_subtitle}\n" .
                    "Image Prompt: {$prompt}\n" .
                    "Keywords: {$keywords}\n" .
                    "Language: {$language}\n" .
                    "Writing Style: {$writing_style}\n" .
                    "Writing Tone: {$writing_tone}\n" .
                    "Ensure the title is specific, creative, and clearly distinguishes this image from others in the same article. Only return the title itself, do not include any explanation, commentary, or additional text. Return just the pure title.";

    //error_log("Llamando a easy_gpt_call_openai_api_no_session para TITLE con datos: Prompt: {$title_prompt}, Modelo: {$text_model}, Temperatura: {$temperature}");
    $title_response = easy_gpt_call_openai_api_no_session($title_prompt, $text_model, $temperature, $api_key);
    $title_text = trim($title_response['text'] ?? '');
    //error_log("Título generado para la imagen {$image_index}: {$title_text}");

    // 2. Generar ALT usando el TÍTULO generado
    $alt_prompt = "Generate an alt text short for an image based on the following details, don't say image, only return de alt text:\n" .
                  "Image Title: {$title_text}\n" .
                  "Prompt: {$prompt}\n" .
                  "Keywords: {$keywords}\n" .
                  "Language: {$language}\n" .
                  "Writing Style: {$writing_style}\n" .
                  "Writing Tone: {$writing_tone}";

    //error_log("Llamando a easy_gpt_call_openai_api_no_session para ALT con datos: Prompt: {$alt_prompt}, Modelo: {$text_model}, Temperatura: {$temperature}");
    $alt_response = easy_gpt_call_openai_api_no_session($alt_prompt, $text_model, $temperature, $api_key);
    $alt_text = trim($alt_response['text'] ?? '');
    //error_log("Alt generado para la imagen {$image_index}: {$alt_text}");

    // 3. Generar Imagen usando ALT y TITLE en el prompt
    $full_prompt = "Generate an image for a {$entity_type} titled '{$title_text}' with the following details. Do not include text in the image:\n" .
                   "Image Title: {$title_text}\n" .
                   "Alt Text: {$alt_text}\n" .
                   "Prompt: {$prompt}\n" .
                   "Keywords: {$keywords}\n" .
                   "Image Size: {$image_size}\n" .
                   "Image Quality: {$image_quality}\n" .
                   "Image Style: {$image_style}\n" .
                   "Only return the image URL.";

    //error_log("Llamando a easy_gpt_call_openai_image_api_no_session con datos: Prompt: {$full_prompt}, Modelo: {$model}, Tamaño: {$image_size}, Calidad: {$image_quality}");
    $image_response = easy_gpt_call_openai_image_api_no_session($full_prompt, $model, $image_size, $image_quality, $api_key);
    $image_url = esc_url_raw($image_response['image_url'] ?? '');

    if ($image_url) {
        //error_log("Imagen generada correctamente para la imagen {$image_index}: {$image_url}");
        return [
            'image_url' => $image_url,
            'title' => sanitize_text_field($title_text),
            'alt' => sanitize_text_field($alt_text)
        ];
    } else {
        //error_log("Error al generar la imagen para la imagen {$image_index}");
        return false;
    }
}





function easy_gpt_call_openai_api_no_session($prompt, $model, $temperature, $api_key) {
    global $easy_gpt_options;
    global $easy_gpt_total_cost;
	
	$options = get_option('easy_gpt_options');

    $allowed_tags = array(
        'b' => array(),
        'i' => array(),
        'h2' => array(),
        'h3' => array(),
        'h4' => array(),
        'a' => array(
            'href' => array(),
            'title' => array(),
            'rel' => array(),
            'target' => array(),
        ),
        'ul' => array(),
        'ol' => array(),
        'li' => array(),
        'p' => array(),
    );

    $prompt = wp_kses($prompt, $allowed_tags);
    $model = sanitize_text_field($model);
    $temperature = floatval($temperature);

    // Detectar proveedor
    if (strpos($model, 'gemini-') === 0 || strpos($model, 'imagen-') === 0) {
        $provider = 'gemini';
    } elseif (strpos($model, 'deepseek-') === 0) {
        $provider = 'deepseek';
    } else {
        $provider = 'openai';
    }
	
	//error_log("[EasyGPT] Using Provider: $provider, Model: $model");

    // API Key correcta
    switch ($provider) {
        case 'gemini':
            $api_key = $options['easy_gpt_gemini_api_key'] ?? '';
            break;
        case 'deepseek':
            $api_key = $options['easy_gpt_deepseek_api_key'] ?? '';
            break;
        case 'openai':
        default:
            $api_key = $options['easy_gpt_api_key'] ?? '';
            break;
    }

    if (strpos($model, 'gpt-5') !== false || strpos($model, 'o1') !== false || strpos($model, 'o3') !== false || strpos($model, 'o4') !== false) {
        $temperature = 1;
    }

    $input_cost_per_token = floatval($easy_gpt_options['model_costs'][$model]['input'] ?? 0);
    $output_cost_per_token = floatval($easy_gpt_options['model_costs'][$model]['output'] ?? 0);

    // Crear URL y payload
    switch ($provider) {
        case 'gemini':
            $url = "https://generativelanguage.googleapis.com/v1beta/models/{$model}:generateContent?key={$api_key}";
            $postData = [
                'contents' => [[
                    'parts' => [['text' => $prompt]]
                ]]
            ];
            break;

        case 'deepseek':
            $url = 'https://api.deepseek.com/v1/chat/completions';
            $postData = [
                'model' => $model,
                'messages' => [['role' => 'user', 'content' => $prompt]],
                'temperature' => $temperature
            ];
            break;

        case 'openai':
        default:
            if (strpos($model, 'gpt-5') !== false || strpos($model, 'gpt-4o') !== false || strpos($model, 'gpt-3.5-turbo') !== false || strpos($model, 'gpt-4') !== false || strpos($model, 'gpt-4.1') !== false || strpos($model, 'o1') !== false || strpos($model, 'o3') !== false || strpos($model, 'o4') !== false) {
                $url = 'https://api.openai.com/v1/chat/completions';
                $postData = [
                    'model' => $model,
                    'messages' => [['role' => 'user', 'content' => $prompt]],
                    'temperature' => $temperature
                ];
            } else {
                $url = 'https://api.openai.com/v1/completions';
                $postData = [
                    'model' => $model,
                    'prompt' => $prompt,
                    'temperature' => $temperature
                ];
            }
            break;
    }

    // Log envío
    //error_log("[EasyGPT] Sending request to: $url");
    //error_log("[EasyGPT] Payload: " . json_encode($postData));

    $headers = ['Content-Type' => 'application/json'];
    if ($provider !== 'gemini') {
        $headers['Authorization'] = 'Bearer ' . $api_key;
    }

    $response = wp_remote_post($url, [
        'headers' => $headers,
        'body' => wp_json_encode($postData),
        'timeout' => 300
    ]);

    if (is_wp_error($response)) {
        //error_log("[EasyGPT] Request Error: " . $response->get_error_message());
        return ['success' => false, 'error' => $response->get_error_message()];
    }

    $body = wp_remote_retrieve_body($response);
    $decoded = json_decode($body, true);

    //error_log("[EasyGPT] Response: " . print_r($decoded, true));

    if (isset($decoded['error'])) {
        $error_message = $decoded['error']['message'] ?? 'Unknown API error';
        //error_log("[EasyGPT] API Error: $error_message");
        return ['success' => false, 'error' => $error_message];
    }

    // Procesar respuesta
    if ($provider === 'gemini') {
        $text = $decoded['candidates'][0]['content']['parts'][0]['text'] ?? 'No text received';
        return ['success' => true, 'text' => trim($text), 'prompt_tokens' => 0, 'completion_tokens' => 0, 'total_tokens' => 0, 'total_cost' => 0.0];
    }

    if (isset($decoded['usage'])) {
        $prompt_tokens = intval($decoded['usage']['prompt_tokens'] ?? 0);
        $completion_tokens = intval($decoded['usage']['completion_tokens'] ?? 0);
        $total_tokens = intval($decoded['usage']['total_tokens'] ?? 0);

        $input_cost = ($prompt_tokens / 1000) * $input_cost_per_token;
        $output_cost = ($completion_tokens / 1000) * $output_cost_per_token;
        $additional_cost = $input_cost + $output_cost;

        $easy_gpt_total_cost += $additional_cost;

        $text = $decoded['choices'][0]['message']['content'] ?? ($decoded['choices'][0]['text'] ?? '');

        return [
            'success' => true,
            'text' => trim($text),
            'prompt_tokens' => $prompt_tokens,
            'completion_tokens' => $completion_tokens,
            'total_tokens' => $total_tokens,
            'total_cost' => $additional_cost,
        ];
    }

    return ['success' => false, 'error' => 'No token usage data received'];
}



function easy_gpt_call_openai_image_api_no_session($prompt, $model, $image_size, $image_quality, $api_key) {
    global $easy_gpt_options;
    global $easy_gpt_total_cost;

    $provider = 'openai';
    if (strpos($model, 'gemini-') === 0 || strpos($model, 'imagen-') === 0) {
        $provider = 'gemini';
    }
	
	//error_log("[EasyGPT] Using Provider: $provider, Model: $model");

    $options = get_option('easy_gpt_options');

    // API Key correcta
    switch ($provider) {
        case 'gemini':
            $api_key = $options['easy_gpt_gemini_api_key'] ?? '';
            break;
        case 'deepseek':
            $api_key = $options['easy_gpt_deepseek_api_key'] ?? '';
            break;
        case 'openai':
        default:
            $api_key = $options['easy_gpt_api_key'] ?? '';
            break;
    }

    // Preparar URL y request body
    if ($provider === 'gemini') {
        if (strpos($model, 'imagen-') === 0) {
            $url = "https://generativelanguage.googleapis.com/v1beta/models/{$model}:predict?key={$api_key}";
            $request_body = [
                "instances" => [["prompt" => $prompt]],
                "parameters" => ["sampleCount" => 1]
            ];
        } else {
            $url = "https://generativelanguage.googleapis.com/v1beta/models/{$model}:generateContent?key={$api_key}";
            $request_body = [
                "contents" => [[
                    "parts" => [["text" => $prompt]]
                ]]
            ];
        }
    } else {
        $url = 'https://api.openai.com/v1/images/generations';
        $request_body = [
            'model' => $model,
            'prompt' => $prompt
        ];
    }

    $args = [
        'method'  => 'POST',
        'headers' => [
            'Content-Type' => 'application/json',
        ],
        'body'    => wp_json_encode($request_body),
        'timeout' => 300,
    ];

    if ($provider === 'openai') {
        $args['headers']['Authorization'] = 'Bearer ' . sanitize_text_field($api_key);
    }

    $response = wp_remote_post($url, $args);

    if (is_wp_error($response)) {
        //error_log('❌ Image API request error: ' . $response->get_error_message());
        return null;
    }

    $response_code = wp_remote_retrieve_response_code($response);
    $response_body = wp_remote_retrieve_body($response);
    $decodedResponse = json_decode($response_body, true);

    if ($response_code != 200 || isset($decodedResponse['error'])) {
        //error_log('❌ Image API error. Response: ' . print_r($decodedResponse, true));
        return null;
    }

    // Procesar respuesta
    $image_url = '';

    if ($provider === 'openai') {
        if (isset($decodedResponse['data'][0]['url'])) {
            $image_url = esc_url_raw($decodedResponse['data'][0]['url']);
        } else {
            //error_log('❌ OpenAI: No image URL found.');
            return null;
        }
    } elseif ($provider === 'gemini') {
        if (strpos($model, 'imagen-') === 0) {
            if (isset($decodedResponse['predictions'][0]['bytesBase64Encoded'])) {
                $base64_image = $decodedResponse['predictions'][0]['bytesBase64Encoded'];
            } else {
                //error_log('❌ Imagen Model: No image data found.');
                return null;
            }
        } else {
            if (isset($decodedResponse['candidates'][0]['content']['parts'][0]['inline_data']['data'])) {
                $base64_image = $decodedResponse['candidates'][0]['content']['parts'][0]['inline_data']['data'];
            } else {
                //error_log('❌ Gemini Model: No image data found.');
                return null;
            }
        }

        $image_data = base64_decode($base64_image);

        if ($image_data === false) {
            //error_log('❌ Failed to decode base64 image.');
            return null;
        }

        // Guardar temporalmente en /uploads
        $upload_dir = wp_upload_dir();
        $filename = 'gemini_image_' . uniqid() . '.png';
        $file_path = trailingslashit($upload_dir['path']) . $filename;
        $file_url = trailingslashit($upload_dir['url']) . $filename;

        file_put_contents($file_path, $image_data);

        $image_url = esc_url_raw($file_url);
    }
// Calcular el coste de la imagen
$image_cost = 0.0;
//error_log("[EasyGPT] Calculando coste de imagen para modelo: $model");

if (in_array($model, ['dall-e-3', 'dall-e-2', 'imagen-3.0-generate-002'])) {
    //error_log("[EasyGPT] Modelo detectado como DALL-E o Imagen (modelos de imagen).");

    if (isset($easy_gpt_options['model_costs'][$model]['image'])) {
        if ($model === 'dall-e-3') {
            if (isset($easy_gpt_options['model_costs'][$model]['image'][$image_quality][$image_size])) {
                $image_cost = floatval($easy_gpt_options['model_costs'][$model]['image'][$image_quality][$image_size]);
                //error_log("[EasyGPT] Coste encontrado (dall-e-3): $image_cost (calidad: $image_quality, tamaño: $image_size)");
            } else {
                //error_log("[EasyGPT] No se encontró el coste específico en dall-e-3 para calidad: $image_quality y tamaño: $image_size");
            }
        } else {
            if (isset($easy_gpt_options['model_costs'][$model]['image'][$image_size])) {
                $image_cost = floatval($easy_gpt_options['model_costs'][$model]['image'][$image_size]);
                //error_log("[EasyGPT] Coste encontrado (dall-e-2 o imagen-3.0): $image_cost (tamaño: $image_size)");
            } else {
                //error_log("[EasyGPT] No se encontró el coste específico en $model para tamaño: $image_size");
            }
        }
    } else {
        //error_log("[EasyGPT] No se encontró entrada 'image' en model_costs para el modelo: $model");
    }
} else {
    $output_cost_per_token = floatval($easy_gpt_options['model_costs'][$model]['output'] ?? 0);
    $image_cost = $output_cost_per_token;
    //error_log("[EasyGPT] Coste asignado usando output cost por token: $image_cost");
}

$easy_gpt_total_cost += $image_cost;

//error_log("[EasyGPT] Coste total acumulado tras imagen: $easy_gpt_total_cost");

return [
    'image_url' => $image_url,
    'total_cost' => $image_cost
];


}

function easy_gpt_insert_images_into_content($content, $image_urls, $set_featured_image) {
    $content_parts = preg_split('/(<h2[^>]*>.*?<\/h2>)/i', $content, -1, PREG_SPLIT_DELIM_CAPTURE);
    $new_content = '';
    $image_index = $set_featured_image ? 1 : 0; // Inicia en 1 si la primera imagen es destacada

    foreach ($content_parts as $part) {
        $new_content .= $part;

        // Solo insertamos imágenes después de los encabezados H2
        if (stripos($part, '<h2') !== false && isset($image_urls[$image_index])) {
            // Obtener ID de la imagen a partir de la URL
            $attachment_id = attachment_url_to_postid($image_urls[$image_index]);

            // Obtener el alt y title desde los metadatos de WordPress
            $image_alt = get_post_meta($attachment_id, '_wp_attachment_image_alt', true);
            $image_title = get_the_title($attachment_id);

            // Construir la etiqueta de imagen con ALT y TITLE
            $new_content .= '<img src="' . esc_url($image_urls[$image_index]) . '" alt="' . esc_attr($image_alt) . '" title="' . esc_attr($image_title) . '" style="max-width:100%;height:auto;">';

            $image_index++;
        }
    }

    return $new_content;
}

