<?php
/**
 * Generated draft parser service.
 *
 * @package SmartyPress_AI_Engine
 */

if ( ! defined( 'ABSPATH' ) ) {
	exit;
}

/**
 * Parses AI draft responses into post fields.
 */
class SmartyPress_AI_Content_Generator_Draft_Parser {

	/**
	 * Parse generated content into title, content, excerpt, and tags.
	 *
	 * @param string $generated_content AI response.
	 * @return array
	 */
	public function parse_generated_post_parts( $generated_content ) {
		$content = trim( (string) $generated_content );
		$parts   = array(
			'title'          => '',
			'content'        => '',
			'excerpt'        => '',
			'seo_keywords'   => array(),
			'seo_metadata'   => array(),
			'content_format' => 'legacy_markdown',
			'content_blocks' => array(),
		);

		$article = $this->parse_article_blocks_json( $content );

		if ( ! empty( $article ) ) {
			return $this->normalize_article_blocks_parts( $article );
		}

		$patterns = array(
			'title'        => '/===\s*TITLE_START\s*===\s*(.*?)\s*===\s*TITLE_END\s*===/is',
			'content'      => '/===\s*CONTENT_START\s*===\s*(.*?)\s*===\s*CONTENT_END\s*===/is',
			'excerpt'      => '/===\s*EXCERPT_START\s*===\s*(.*?)\s*===\s*EXCERPT_END\s*===/is',
			'seo_keywords' => '/===\s*SEO_KEYWORDS_START\s*===\s*(.*?)\s*===\s*SEO_KEYWORDS_END\s*===/is',
		);

		foreach ( $patterns as $key => $pattern ) {
			if ( preg_match( $pattern, $content, $matches ) ) {
				$parts[ $key ] = trim( $matches[1] );
			}
		}

		if ( '' === $parts['content'] ) {
			$parts['content'] = $this->extract_unmarked_generated_content( $content, $parts['title'] );
		}

		$parts['title']   = sanitize_text_field( $parts['title'] );
		$parts['excerpt'] = sanitize_textarea_field( $parts['excerpt'] );
		$parts['seo_keywords'] = $this->sanitize_string_list( $parts['seo_keywords'] );

		return $parts;
	}

	/**
	 * Parse structured article JSON from AI response.
	 *
	 * @param string $content AI response.
	 * @return array
	 */
	public function parse_article_blocks_json( $content ) {
		$content = trim( (string) $content );

		if ( '' === $content ) {
			return array();
		}

		$json = $content;

		if ( preg_match( '/===\s*ARTICLE_JSON_START\s*===\s*(.*?)\s*===\s*ARTICLE_JSON_END\s*===/is', $content, $matches ) ) {
			$json = trim( $matches[1] );
		} elseif ( preg_match( '/```(?:json)?\s*(.*?)```/is', $content, $matches ) ) {
			$json = trim( $matches[1] );
		} elseif ( 0 !== strpos( ltrim( $content ), '{' ) ) {
			$json = $this->extract_first_json_object( $content );
		}

		$data = json_decode( $json, true );

		if ( ! is_array( $data ) || ! isset( $data['content'] ) || ! is_array( $data['content'] ) ) {
			return array();
		}

		return $data;
	}

	/**
	 * Normalize structured article JSON into generated post parts.
	 *
	 * @param array $article Article JSON.
	 * @return array
	 */
	public function normalize_article_blocks_parts( $article ) {
		$content = is_array( $article['content'] ?? null ) ? $article['content'] : array();
		$blocks  = is_array( $content['blocks'] ?? null ) ? $content['blocks'] : array();
		$lead    = sanitize_textarea_field( $content['lead'] ?? '' );

		return array(
			'title'          => sanitize_text_field( $article['title'] ?? '' ),
			'content'        => $this->build_article_plain_preview( $lead, $blocks ),
			'excerpt'        => sanitize_textarea_field( $article['excerpt'] ?? '' ),
			'seo_keywords'   => $this->sanitize_string_list( $article['seo_keywords'] ?? array() ),
			'seo_metadata'   => $this->normalize_seo_metadata( $article['seo_metadata'] ?? array(), $article ),
			'content_format' => 'article_blocks',
			'content_blocks' => array(
				'title'        => sanitize_text_field( $article['title'] ?? '' ),
				'excerpt'      => sanitize_textarea_field( $article['excerpt'] ?? '' ),
				'seo_keywords' => $this->sanitize_string_list( $article['seo_keywords'] ?? array() ),
				'content'      => array(
					'lead'   => $lead,
					'toc'    => ! empty( $content['toc'] ),
					'blocks' => $blocks,
				),
			),
		);
	}

	/**
	 * Normalize structured SEO metadata.
	 *
	 * @param array $metadata Raw metadata.
	 * @param array $article Article JSON.
	 * @return array
	 */
	private function normalize_seo_metadata( $metadata, $article ) {
		$metadata = is_array( $metadata ) ? $metadata : array();
		$keywords = $this->sanitize_string_list( $metadata['focus_keywords'] ?? ( $article['seo_keywords'] ?? array() ) );

		return array(
			'seo_title'          => sanitize_text_field( $metadata['seo_title'] ?? ( $article['title'] ?? '' ) ),
			'meta_description'   => sanitize_textarea_field( $metadata['meta_description'] ?? ( $article['excerpt'] ?? '' ) ),
			'slug'               => sanitize_title( $metadata['slug'] ?? '' ),
			'focus_keywords'     => $keywords,
			'primary_keyword'    => sanitize_text_field( $metadata['primary_keyword'] ?? ( $keywords[0] ?? '' ) ),
			'secondary_keywords' => array_values( array_slice( $keywords, 1, 4 ) ),
		);
	}

	/**
	 * Fallback parser for responses without explicit markers.
	 *
	 * @param string $content AI response.
	 * @return array
	 */
	public function extract_unmarked_generated_content( $content, $title = '' ) {
		$content = trim( (string) $content );

		if ( '' === $content ) {
			return '';
		}

		$content = preg_replace( '/===\s*(?:TITLE|CONTENT|EXCERPT|SEO_KEYWORDS)_(?:START|END)\s*===/i', '', $content );
		$content = preg_replace( '/^\s*(?:title|заголовок)\s*:\s*.+$/imu', '', $content );
		$content = preg_replace( '/^\s*(?:excerpt|анонс|выдержка)\s*:\s*.+$/imu', '', $content );
		$content = preg_replace( '/^\s*(?:seo[_\s-]*keywords|seo\s*ключевые\s*слова)\s*:\s*.+$/imu', '', $content );

		if ( '' !== $title ) {
			$content = preg_replace( '/^\s*#?\s*' . preg_quote( $title, '/' ) . '\s*$/imu', '', $content, 1 );
		}

		return trim( $content );
	}

	/**
	 * Sanitize comma or newline separated string list.
	 *
	 * @param mixed $items Raw list.
	 * @return array
	 */
	public function sanitize_string_list( $items ) {
		if ( is_string( $items ) ) {
			$items = preg_split( '/\r\n|\r|\n|,/', $items );
		}

		if ( ! is_array( $items ) ) {
			return array();
		}

		$sanitized = array();

		foreach ( $items as $item ) {
			if ( ! is_scalar( $item ) ) {
				continue;
			}

			$value = sanitize_text_field( (string) $item );

			if ( '' !== $value ) {
				$sanitized[] = $value;
			}
		}

		return array_values( array_unique( $sanitized ) );
	}

	/**
	 * Extract the first balanced JSON object from a string.
	 *
	 * @param string $content Raw response.
	 * @return string
	 */
	private function extract_first_json_object( $content ) {
		$start = strpos( $content, '{' );

		if ( false === $start ) {
			return '';
		}

		$depth     = 0;
		$in_string = false;
		$escaped   = false;
		$length    = strlen( $content );

		for ( $i = $start; $i < $length; $i++ ) {
			$char = $content[ $i ];

			if ( $escaped ) {
				$escaped = false;
				continue;
			}

			if ( '\\' === $char ) {
				$escaped = true;
				continue;
			}

			if ( '"' === $char ) {
				$in_string = ! $in_string;
				continue;
			}

			if ( $in_string ) {
				continue;
			}

			if ( '{' === $char ) {
				$depth++;
			} elseif ( '}' === $char ) {
				$depth--;

				if ( 0 === $depth ) {
					return substr( $content, $start, $i - $start + 1 );
				}
			}
		}

		return '';
	}

	/**
	 * Build a small plain-text preview from article JSON.
	 *
	 * @param string $lead Lead text.
	 * @param array  $blocks Article blocks.
	 * @return string
	 */
	private function build_article_plain_preview( $lead, $blocks ) {
		$parts = array();

		if ( '' !== $lead ) {
			$parts[] = $lead;
		}

		foreach ( $blocks as $block ) {
			if ( ! is_array( $block ) ) {
				continue;
			}

			$text = $block['text'] ?? ( $block['content'] ?? '' );

			if ( is_scalar( $text ) && '' !== trim( (string) $text ) ) {
				$parts[] = wp_strip_all_tags( (string) $text );
			}
		}

		return trim( implode( "\n\n", array_slice( $parts, 0, 3 ) ) );
	}
}
