<?php
/**
 * WBAG Blog Writer
 *
 * Generates complete blog posts and creates WordPress draft posts.
 *
 * @package 2fox4_WP_Blog_Agent
 * @subpackage Includes
 * @since 1.0.0
 */

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

/**
 * WBAG_Blog_Writer class.
 *
 * Generates complete blog posts using AI and creates WordPress draft posts.
 *
 * @since 1.0.0
 */
class WBAG_Blog_Writer {

	/**
	 * Run the blog writer.
	 *
	 * Main method to generate and publish a blog post.
	 *
	 * @since 1.0.0
	 *
	 * @param array $topic Optional. Topic data array. If not provided, gets next approved topic.
	 * @return array|WP_Error Array with post_id, edit_url, title, image_prompts on success, WP_Error on failure.
	 */
	public static function run( $topic = null ) {
		// Get topic if not provided.
		if ( empty( $topic ) ) {
			$topic = WBAG_Topic_Scout::get_next_approved();

			if ( is_wp_error( $topic ) || empty( $topic ) ) {
				return new WP_Error(
					'no_approved_topics',
					__( 'No approved topics available.', 'wp-blog-agent' )
				);
			}
		}

		// Load settings.
		$settings = get_option( 'wbag_settings', array() );

		// Validate API key.
		if ( empty( $settings['api_key'] ) ) {
			return new WP_Error(
				'missing_api_key',
				__( 'API key not configured.', 'wp-blog-agent' )
			);
		}

		// Update topic status to 'writing'.
		$status_update = self::update_topic_status( $topic['slug'], 'writing' );
		if ( is_wp_error( $status_update ) ) {
			return $status_update;
		}

		// Generate blog post content.
		$content = WBAG_Api::generate_blog_post( $topic, $settings );
		if ( is_wp_error( $content ) ) {
			return $content;
		}

		// Generate SEO meta.
		$seo_meta = WBAG_Api::generate_seo_meta( $topic, $settings );
		if ( is_wp_error( $seo_meta ) ) {
			return $seo_meta;
		}

		// Generate image prompts.
		$image_prompts = WBAG_Api::generate_image_prompts( $topic, $settings );
		if ( is_wp_error( $image_prompts ) ) {
			return $image_prompts;
		}

		// Create WordPress draft post.
		$post_id = self::create_draft_post( $topic, $content, $seo_meta, $settings );
		if ( is_wp_error( $post_id ) ) {
			return $post_id;
		}

		// Set SEO meta using RankMath or Yoast.
		$seo_result = WBAG_RankMath::set_seo_meta( $post_id, $seo_meta, $settings );
		if ( is_wp_error( $seo_result ) ) {
			return $seo_result;
		}

		// Update topic status to 'published'.
		$status_update = self::update_topic_status( $topic['slug'], 'published' );
		if ( is_wp_error( $status_update ) ) {
			return $status_update;
		}

		// Build edit URL.
		$edit_url = get_edit_post_link( $post_id, 'raw' );

		// Return success result.
		return array(
			'post_id'       => $post_id,
			'edit_url'      => $edit_url,
			'title'         => $topic['title'],
			'image_prompts' => $image_prompts,
		);
	}

	/**
	 * Create a WordPress draft post.
	 *
	 * Creates a new WordPress post with the generated content.
	 *
	 * @since 1.0.0
	 *
	 * @param array  $topic    Topic data array.
	 * @param string $content  Generated blog post HTML content.
	 * @param array  $seo_meta SEO metadata array.
	 * @param array  $settings Plugin settings array.
	 * @return int|WP_Error Post ID on success, WP_Error on failure.
	 */
	private static function create_draft_post( $topic, $content, $seo_meta, $settings ) {
		// Get current user or first admin.
		$current_user = wp_get_current_user();
		$author_id    = $current_user->ID;

		if ( empty( $author_id ) ) {
			// Fallback to first admin user.
			$admins = get_users(
				array(
					'role'   => 'administrator',
					'number' => 1,
				)
			);

			if ( empty( $admins ) ) {
				return new WP_Error(
					'no_author',
					__( 'No administrator user found to assign as author.', 'wp-blog-agent' )
				);
			}

			$author_id = $admins[0]->ID;
		}

		// Find or create category.
		$category_id = self::find_or_create_category( $topic['subtopic'] );
		if ( is_wp_error( $category_id ) ) {
			return $category_id;
		}

		// Extract tags from secondary keywords.
		$tags = array();
		if ( ! empty( $seo_meta['secondary_keywords'] ) ) {
			if ( is_string( $seo_meta['secondary_keywords'] ) ) {
				// Parse comma-separated keywords.
				$tags = array_map( 'trim', explode( ',', $seo_meta['secondary_keywords'] ) );
			} elseif ( is_array( $seo_meta['secondary_keywords'] ) ) {
				$tags = $seo_meta['secondary_keywords'];
			}
		}

		// Build a clean 30-word excerpt from the generated content.
		$plain = wp_strip_all_tags( $content );
		$plain = preg_replace( '/\s+/', ' ', trim( $plain ) );
		$words = preg_split( '/\s+/', $plain, 32, PREG_SPLIT_NO_EMPTY );
		if ( count( $words ) > 30 ) {
			$words = array_slice( $words, 0, 30 );
			$excerpt = implode( ' ', $words ) . ' ...';
		} else {
			$excerpt = implode( ' ', $words );
		}

		// Prepare post data.
		$post_data = array(
			'post_title'    => $topic['title'],
			'post_content'  => $content,
			'post_excerpt'  => $excerpt,
			'post_status'   => 'draft',
			'post_author'   => $author_id,
			'post_name'     => $topic['slug'],
			'post_category' => array( $category_id ),
			'tags_input'    => $tags,
		);

		// Insert the post.
		$post_id = wp_insert_post( $post_data, true );

		if ( is_wp_error( $post_id ) ) {
			return $post_id;
		}

		// Add post meta.
		update_post_meta( $post_id, '_wbag_generated', '1' );
		update_post_meta( $post_id, '_wbag_topic_data', $topic );
		update_post_meta( $post_id, '_wbag_image_prompts', $image_prompts ?? array() );
		update_post_meta( $post_id, '_wbag_generated_at', current_time( 'mysql' ) );

		return $post_id;
	}

	/**
	 * Find or create a category.
	 *
	 * Checks if a category exists by name, creates it if not.
	 *
	 * @since 1.0.0
	 *
	 * @param string $name Category name.
	 * @return int|WP_Error Category ID on success, WP_Error on failure.
	 */
	private static function find_or_create_category( $name ) {
		if ( empty( $name ) ) {
			return new WP_Error(
				'empty_category_name',
				__( 'Category name cannot be empty.', 'wp-blog-agent' )
			);
		}

		// Try to find existing category.
		$category = get_term_by( 'name', $name, 'category' );

		if ( $category ) {
			return $category->term_id;
		}

		// Create new category.
		$result = wp_insert_term(
			$name,
			'category',
			array(
				'slug' => sanitize_title( $name ),
			)
		);

		if ( is_wp_error( $result ) ) {
			return $result;
		}

		return $result['term_id'];
	}

	/**
	 * Find internal links for a niche.
	 *
	 * Queries existing published posts related to the niche.
	 *
	 * @since 1.0.0
	 *
	 * @param string $niche Topic niche/category.
	 * @param int    $count Number of internal links to find.
	 * @return array Array of arrays with 'title', 'url', 'id'.
	 */
	private static function find_internal_links( $niche, $count = 3 ) {
		// Find category by name.
		$category = get_term_by( 'name', $niche, 'category' );

		if ( ! $category ) {
			return array();
		}

		// Query recent posts in this category.
		$args = array(
			'cat'            => $category->term_id,
			'posts_per_page' => $count,
			'post_status'    => 'publish',
			'post_type'      => 'post',
			'orderby'        => 'date',
			'order'          => 'DESC',
		);

		$posts = get_posts( $args );

		$links = array();
		foreach ( $posts as $post ) {
			$links[] = array(
				'title' => $post->post_title,
				'url'   => get_permalink( $post->ID ),
				'id'    => $post->ID,
			);
		}

		return $links;
	}

	/**
	 * Update topic status in the queue.
	 *
	 * Updates the status of a topic in wbag_topic_queue by matching slug.
	 *
	 * @since 1.0.0
	 *
	 * @param string $slug   Topic slug.
	 * @param string $status New status.
	 * @return bool|WP_Error True on success, WP_Error on failure.
	 */
	private static function update_topic_status( $slug, $status ) {
		global $wpdb;

		// Validate status.
		$valid_statuses = array( 'pending', 'approved', 'writing', 'published', 'failed' );
		if ( ! in_array( $status, $valid_statuses, true ) ) {
			return new WP_Error(
				'invalid_status',
				__( 'Invalid topic status.', 'wp-blog-agent' )
			);
		}

		// Update the topic status.
		$result = $wpdb->update(
			$wpdb->prefix . 'wbag_topic_queue',
			array( 'status' => $status ),
			array( 'slug' => $slug ),
			array( '%s' ),
			array( '%s' )
		);

		if ( false === $result ) {
			return new WP_Error(
				'topic_update_failed',
				__( 'Failed to update topic status.', 'wp-blog-agent' )
			);
		}

		return true;
	}

	/**
	 * Get recent draft posts.
	 *
	 * Returns recent posts created by this plugin.
	 *
	 * @since 1.0.0
	 *
	 * @param int $count Number of recent drafts to retrieve.
	 * @return array Array of post objects.
	 */
	public static function get_recent_drafts( $count = 10 ) {
		$args = array(
			'post_type'      => 'post',
			'post_status'    => 'draft',
			'posts_per_page' => $count,
			'orderby'        => 'date',
			'order'          => 'DESC',
			'meta_key'       => '_wbag_generated',
			'meta_value'     => '1',
		);

		return get_posts( $args );
	}
}
