<?php

namespace RistrettoApps\Spawnster\Services;

use Spawnster;

/**
 * Provides scheduled content generation functionality.
 *
 * @package    Spawnster
 * @subpackage Spawnster/Services
 * @author     Ristretto Apps
 */
class ScheduledContentService {

	/**
	 * The OpenAI Service instance.
	 *
	 * @var OpenAiService
	 */
	private $openai_service;

	/**
	 * The Content Research Service instance.
	 *
	 * @var ContentResearchService
	 */
	private $content_research_service;

	/**
	 * The Post Vector Table Service instance.
	 *
	 * @var PostVectorTableService
	 */
	private $post_vector_table_service;

	/**
	 * Constructor for the ScheduledContentService class.
	 *
	 * @param OpenAiService           $openai_service           The OpenAI Service instance.
	 * @param ContentResearchService  $content_research_service The Content Research Service instance.
	 * @param PostVectorTableService  $post_vector_table_service The Post Vector Table Service instance.
	 */
	public function __construct( OpenAiService $openai_service, ContentResearchService $content_research_service, PostVectorTableService $post_vector_table_service ) {
		$this->openai_service = $openai_service;
		$this->content_research_service = $content_research_service;
		$this->post_vector_table_service = $post_vector_table_service;
	}

	/**
	 * Generate AI content for a job.
	 *
	 * @param int $job_id The job ID.
	 * @return void
	 */
	public function generate_ai_content( int $job_id ): void {
		$job = get_post( $job_id );
		if ( ! $job || $job->post_type !== 'spawnster_job' ) {
			return;
		}

		$specific_topic = get_post_meta( $job_id, 'specificTopic', true );
		$category = (int) get_post_meta( $job_id, 'topicCategory', true );
		$past_articles = (int) get_post_meta( $job_id, 'pastArticles', true );
		$word_count_goal = (int) get_post_meta( $job_id, 'wordCountGoal', true );

		// Fetch and summarize related content
		$summarized_contents = $this->content_research_service->fetch_and_summarize_content(
			$specific_topic,
			$category,
			$past_articles
		);

		// Generate a new topic if needed
		$final_topic = $this->content_research_service->generate_new_topic(
			$job_id,
			$specific_topic,
			$category,
			$summarized_contents
		);

		// Generate the actual post content
		$this->generate_post( $job_id, $final_topic, $summarized_contents, $word_count_goal );
	}

	/**
	 * Generate a post with the given topic and research.
	 *
	 * @param int    $job_id               The job ID.
	 * @param string $topic                The topic for the post.
	 * @param array  $summarized_contents  The summarized research content.
	 * @param int    $word_count_goal      The target word count.
	 * @return void
	 */
	private function generate_post( int $job_id, string $topic, array $summarized_contents, int $word_count_goal ): void {
		$job = get_post( $job_id );
		$author_id = $job->post_author;

		// Create research context
		$research_context = '';
		foreach ( $summarized_contents as $content ) {
			$research_context .= "- " . $content['summary'] . "\n";
		}

		// Generate the post content
		$language_instruction = $this->openai_service->get_language_instruction();
		$prompt = sprintf(
			'Write a comprehensive, engaging blog post about "%s" with approximately %d words. Use the following research as context and reference material:\n\nResearch Context:\n%s\n\nWrite a well-structured blog post with:\n1. An engaging introduction\n2. Clear sections with headings\n3. Valuable insights and information\n4. A compelling conclusion\n\nMake sure the content is original, informative, and provides real value to readers.%s',
			$topic,
			$word_count_goal,
			$research_context,
			$language_instruction
		);

		$result = $this->openai_service->generate_response_with_options( $prompt, array(
			'max_tokens' => min( $word_count_goal * 2, 4000 ),
			'temperature' => 0.7,
		) );

		if ( is_wp_error( $result ) ) {
			OpenAiService::log( 'Failed to generate content for job ' . $job_id . ': ' . $result->get_error_message() );
			return;
		}

		$content = $result['choices'][0]['message']['content'] ?? '';

		// Create the post
		$post_data = array(
			'post_title'   => $topic,
			'post_content' => $content,
			'post_status'  => 'draft',
			'post_author'  => $author_id,
			'post_type'    => 'post',
		);

		$post_id = wp_insert_post( $post_data );

		if ( is_wp_error( $post_id ) ) {
			error_log( 'Failed to create post for job ' . $job_id . ': ' . $post_id->get_error_message() );
			return;
		}

		// Set the category
		$category = get_post_meta( $job_id, 'topicCategory', true );
		if ( $category ) {
			wp_set_post_categories( $post_id, array( $category ) );
		}

		// Create embedding for the post
		$this->create_embedding_for_post( $post_id, $content );

		// Update job with generated post info
		update_post_meta( $job_id, 'last_generated_post_id', $post_id );
		update_post_meta( $job_id, 'last_generated_date', current_time( 'mysql' ) );
	}

	/**
	 * Create an embedding for a post.
	 *
	 * @param int    $post_id The post ID.
	 * @param string $content The post content.
	 * @return void
	 */
	private function create_embedding_for_post( int $post_id, string $content ): void {
		// Create embedding using OpenAI
		$embedding_result = $this->openai_service->create_embedding( $content );

		if ( is_wp_error( $embedding_result ) ) {
			error_log( 'Failed to create embedding for post ' . $post_id . ': ' . $embedding_result->get_error_message() );
			return;
		}

		$embedding = $embedding_result['data'][0]['embedding'] ?? null;

		if ( ! $embedding ) {
			error_log( 'No embedding data received for post ' . $post_id );
			return;
		}

		// Store the embedding in the database
		$result = $this->post_vector_table_service->insert( $post_id, $embedding );

		if ( is_wp_error( $result ) ) {
			error_log( 'Failed to store embedding for post ' . $post_id . ': ' . $result->get_error_message() );
		}
	}

	/**
	 * Schedule a content generation job.
	 *
	 * @param int    $job_id      The job ID.
	 * @param string $schedule    The schedule (hourly, daily, weekly, etc.).
	 * @param int    $delay_hours The delay in hours before first execution.
	 * @return bool               True if scheduled successfully, false otherwise.
	 */
	public function schedule_job( int $job_id, string $schedule, int $delay_hours = 0 ): bool {
		$timestamp = time() + ( $delay_hours * HOUR_IN_SECONDS );
		
		$scheduled = wp_schedule_event( $timestamp, $schedule, 'spawnster_generate_content', array( $job_id ) );
		
		if ( $scheduled ) {
			update_post_meta( $job_id, 'scheduled_next_run', $timestamp );
			return true;
		}

		return false;
	}

	/**
	 * Clear a scheduled job.
	 *
	 * @param int $job_id The job ID.
	 * @return void
	 */
	public function clear_scheduled_job( int $job_id ): void {
		wp_clear_scheduled_hook( 'spawnster_generate_content', array( $job_id ) );
		delete_post_meta( $job_id, 'scheduled_next_run' );
	}

	/**
	 * Add custom cron intervals.
	 *
	 * @param array $schedules The existing schedules.
	 * @return array The modified schedules.
	 */
	public function add_cron_intervals( array $schedules ): array {
		$schedules['spawnster_monthly'] = array(
			'interval' => 30 * DAY_IN_SECONDS,
			'display'  => 'Monthly',
		);
		$schedules['spawnster_yearly'] = array(
			'interval' => YEAR_IN_SECONDS,
			'display'  => 'Yearly',
		);

		return $schedules;
	}
} 