<?php

namespace XHTheme\AIToolbox;

defined('ABSPATH') || exit;

use WP_Post;

/**
 * Intelligent AI Module
 * @author xhtheme
 * @since 2025-03-18
 */
final class XHThemeAi
{
	const DASHBOARD_MESSAGES_OPTION = 'xhtheme_aitoolbox_dashboard_messages';

	private static $instance = null;
	private $cached_version = null;
	private $cached_updateTime = null;
	public $userAppiderror = '';
	public $userType = '';
	public $userName = '';
	public $userTypename = '';
	public $quota = null;
	public $userMember = null;

	public $options = [];

	private static $aiexcerptLoad = false;

	public static function getInstance()
	{
		if (self::$instance === null) {
			self::$instance = new self();
			self::$instance->init();
		}
		return self::$instance;
	}

	private function __construct() {}

	public function option($name, $default = '', $cache = true)
	{
		if (empty($this->options) || !$cache) {
			$this->options = get_option('xhtheme_ai_toolbox_settings', []);
		}
		if (isset($this->options[$name])) {
			return $this->options[$name];
		}
		return $default;
	}

	public function userTypeName($type)
	{
		switch ($type) {
			case 'member':
				return __('Member users', 'xhtheme-ai-toolbox');
			case 'trial':
				return __('Trial Member', 'xhtheme-ai-toolbox');
			case 'free':
				return __('Free Users', 'xhtheme-ai-toolbox');
		}
		return $type;
	}

	public function userData($types = '')
	{
		if (!$this->userType) {
			$this->getusers();
		}
		switch ($types) {
			case 'type':
				return $this->userType;
			case 'name':
				return $this->userName;
			case 'quota':
				return $this->quota;
			case 'error':
				return $this->userAppiderror;
		}
		return [
			'type' => $this->userType,
			'name' => $this->userName,
			'quota' => $this->quota,
			'error' => $this->userAppiderror
		];
	}

	public function resetRuntimeCache()
	{
		$this->cached_version = null;
		$this->cached_updateTime = null;
		$this->userAppiderror = '';
		$this->userType = '';
		$this->userName = '';
		$this->quota = null;
		$this->userMember = null;
	}

	/**
	 * 判断是否为会员用户
	 * @return bool
	 */
	public function isMember()
	{
		if (is_null($this->userMember)) {
			$this->userMember = in_array($this->userData('type'), ['member', 'trial']);
		}
		return $this->userMember;
	}

	public function getusers($loop = true)
	{
		// 错误处理
		$usererror = get_transient('xhtheme_aitoolbox_users_error');
		if ($usererror) {
			$usererror = json_decode($usererror, true);
			// 获取站点语言
			$current_language = get_locale();
			$language = $current_language ? $current_language : 'default';
			$this->userAppiderror = isset($usererror[$language]) ? $usererror[$language] : $usererror['default'];
			return;
		}

		$userData = [];
		if (get_transient('xhtheme_aitoolbox_users')) {
			$users = get_option('xhtheme_aitoolbox_users', '');
			$users = json_decode($users, true);
			if (!empty($users)) {
				$userData = $users;
			}
		}
		if (isset($userData['usertype'])) {
			$this->userType = sanitize_text_field($userData['usertype']);
			$this->userName = sanitize_text_field($userData['username']);
			$this->quota = isset($userData['quota']) && is_array($userData['quota']) ? (array) $userData['quota'] : false;
			$endtime = isset($userData['endtime']) ? $userData['endtime'] : 0;
			if (!is_numeric($endtime)) {
				$endtime = strtotime($endtime);
			}
			if ($this->userType == 'free' || $endtime > time()) {
				return;
			}
		}
		if (xh_option('appId')) {
			if ($this->fetchRemoteModelList() && $loop) {
				$this->getusers(false);
			}
		}
	}




	public function updateModeloption($chatLists, $forarr = '')
	{
		if (!$chatLists)
			return false;
		$adminNotice = true;
		$model = xh_option('modelType', 'auto');
		if ($model == 'auto')
			return false;
		foreach ($chatLists as $chat) {
			if ($chat['name'] == $model) {
				$adminNotice = false;
				break;
			}
		}

		if ($adminNotice) {
			// 更新配置
			xh_setoption('modelType', 'auto');
			/**
			 * 发送邮件通知管理员
			 * @param string $admin_email 管理员邮箱
			 */
			$admin_email = get_option('admin_email');
			if ($admin_email) {
				wp_mail(
					$admin_email,
					__('AI model list has been updated, your specified model is invalid and the system has switched to automatic mode', 'xhtheme-ai-toolbox'),
					__('Due to the update of the AI model list, the model you specified for specific functions has become invalid or changed. The system has automatically switched to automatic selection mode for you. If you need to specify a model, please go to the backend AI configuration page to reselect. Thank you for your support!', 'xhtheme-ai-toolbox')
				);
			}
		}
	}

	public function ai_postexcerpt($content)
	{
		if (!is_main_query()) {
			return $content;
		}


		// 防止重复
		if (self::$aiexcerptLoad) {
			return $content;
		}

		self::$aiexcerptLoad = true;

		// 在文章顶部显示摘要
		$aiExcerpt = xh_option('summaryStyle', 'simple');
		$excerptShow = (int) get_post_meta(get_the_ID(), '_excerptai', true);
		if ($aiExcerpt == 'none' || !$excerptShow) {
			return $content;
		}

		global $post;
		if ($excerptShow == 2) {
			$postExcerpt = get_post_meta($post->ID, '_xhai_excerpt', true);
			if (empty($postExcerpt)) {
				delete_post_meta($post->ID, '_excerptai');
				return $content;
			}
		} else {
			$postExcerpt = esc_html($post->post_excerpt);
			if (empty($postExcerpt)) {
				delete_post_meta($post->ID, '_excerptai');
				return $content;
			}
		}


		$newContent = '';
		$aiTitle = xh_option('summaryTitle', '');
		$aiSubtitle = xh_option('summarySubtitle', '');
		$aiDesc = xh_option('summaryDesc', '');
		$aiDataargs = [
			'title' => $aiTitle ? esc_html($aiTitle) : '',
			'subtitle' => $aiSubtitle ? esc_html($aiSubtitle) : '',
			'desc' => $aiDesc ? esc_html($aiDesc) : '',
			'style' => $aiExcerpt
		];
		if (apply_filters('xhtheme_ai_toolbox_postexcerpt_show', false, $aiExcerpt) && $aiExcerpt !== 'custom') {
			$newContent .= apply_filters('xhtheme_ai_toolbox_postexcerpt_before', '', $postExcerpt, $aiDataargs);
		} else {
			$newContent .= $this->aiExcerptHtml($postExcerpt, $aiDataargs);
		}
		$newContent .= $content;
		return $newContent;
	}

	public function aiExcerptHtml($postExcerpt, $aiargs)
	{
		// Aurora流光样式使用专用方法
		if ($aiargs['style'] === 'aurora') {
			return $this->auroraExcerptHtml($postExcerpt, $aiargs);
		}

		/**
		 * 组合模块
		 */
		$aititle = '';
		$aidesc = '';
		if (!empty($aiargs['title'])) {
			$aisvg = '<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" class="xh-svg" viewBox="0 0 16 16"><path d="M7.657 6.247c.11-.33.576-.33.686 0l.645 1.937a2.89 2.89 0 0 0 1.829 1.828l1.936.645c.33.11.33.576 0 .686l-1.937.645a2.89 2.89 0 0 0-1.828 1.829l-.645 1.936a.361.361 0 0 1-.686 0l-.645-1.937a2.89 2.89 0 0 0-1.828-1.828l-1.937-.645a.361.361 0 0 1 0-.686l1.937-.645a2.89 2.89 0 0 0 1.828-1.828l.645-1.937zM3.794 1.148a.217.217 0 0 1 .412 0l.387 1.162c.173.518.579.924 1.097 1.097l1.162.387a.217.217 0 0 1 0 .412l-1.162.387A1.734 1.734 0 0 0 4.593 5.69l-.387 1.162a.217.217 0 0 1-.412 0L3.407 5.69A1.734 1.734 0 0 0 2.31 4.593l-1.162-.387a.217.217 0 0 1 0-.412l1.162-.387A1.734 1.734 0 0 0 3.407 2.31l.387-1.162zM10.863.099a.145.145 0 0 1 .274 0l.258.774c.115.346.386.617.732.732l.774.258a.145.145 0 0 1 0 .274l-.774.258a1.156 1.156 0 0 0-.732.732l-.258.774a.145.145 0 0 1-.274 0l-.258-.774a1.156 1.156 0 0 0-.732-.732L9.1 2.137a.145.145 0 0 1 0-.274l.774-.258c.346-.115.617-.386.732-.732L10.863.1z"/></svg>';
			$aititle = sprintf(
				'<div class="eb-titlebox">
					<span class="eb-titicon">%s</span>
					<span class="eb-title">%s</span>
					<span class="eb-icon"><svg t="1742538455943" class="xh-svg" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="71517" width="24" height="24"><path d="M554.144375 443.52552083L655.7121875 53.33333333 200 559.25333333l237.6478125 55.68-101.52 390.24 455.664375-505.96875z" p-id="71518" fill="currentColor"></path></svg></span>
				</div>
				',
				$aisvg,
				sanitize_text_field($aiargs['title'])
			);
		}

		$aiexcerpt = sprintf(
			'<div class="eb-excerpt">%s</div>',
			$postExcerpt
		);

		if (!empty($aiargs['desc'])) {
			$aidesc = sprintf('<div class="eb-desc"><span>— %s</span></div>', $aiargs['desc']);
		}
		return sprintf(
			'<div class="eb-card eb-%s">
				<div class="eb-card-bgbox"></div>
				<div class="eb-card-body">
					%s
				</div>
			</div>',
			esc_attr($aiargs['style']),
			$aititle . $aiexcerpt . $aidesc
		);
	}

	/**
	 * Aurora流光样式专用HTML生成方法
	 * @param string $postExcerpt 摘要内容
	 * @param array $aiargs 样式参数
	 * @return string HTML内容
	 */
	public function auroraExcerptHtml($postExcerpt, $aiargs)
	{
		$finishedText = !empty($aiargs['subtitle']) ? sanitize_text_field($aiargs['subtitle']) : esc_html__('Summary Generated', 'xhtheme-ai-toolbox');
		$statusText = !empty($aiargs['title']) ? sanitize_text_field($aiargs['title']) : esc_html__('Generating Summary', 'xhtheme-ai-toolbox');
		$disclaimer = !empty($aiargs['desc']) ? sanitize_text_field($aiargs['desc']) : esc_html__('AI-generated summary · for reference only', 'xhtheme-ai-toolbox');
		$bgImg = sprintf(
			'<img class="eb-aurora-bg" src="%s" alt="" />',
			esc_url(plugin_dir_url(dirname(__FILE__)) . 'assets/images/aurora-bg.svg')
		);

		return sprintf(
			'<div class="eb-aurora-container" data-status="%s" data-finished="%s">
				<div class="eb-aurora-inner">
					%s
					<div class="eb-aurora-status">
						<div class="eb-aurora-tag">
							<div class="eb-aurora-pulse"></div>
							<span class="eb-aurora-status-text">%s</span>
						</div>
						<div class="eb-aurora-disclaimer">%s</div>
					</div>
					<div class="eb-aurora-content">
						<span class="eb-aurora-text" data-text="%s"></span><span class="eb-aurora-cursor"></span>
					</div>
				</div>
			</div>',
			esc_attr($statusText),
			esc_attr($finishedText),
			$bgImg,
			$statusText,
			$disclaimer,
			esc_attr($postExcerpt)
		);
	}

	public function syncUserArgs($request)
	{
		$response = ['success' => true, 'msg' => __('User arguments synced!', 'xhtheme-ai-toolbox'), 'data' => []];
		$userArgs = $request->get_param('userArgs');
		if (empty($userArgs) || !is_array($userArgs)) {
			$response['success'] = false;
			$response['msg'] = __('Invalid user arguments!', 'xhtheme-ai-toolbox');
			return rest_ensure_response($response);
		}

		$this->updateModelList($userArgs);
		return rest_ensure_response($response);
	}

	/**
	 * 从远程获取模型列表
	 * @return bool 是否成功获取并更新模型列表
	 */
	public function fetchRemoteModelList($cache = true)
	{
		if (get_transient('xhtheme_aitoolbox_apicheck')) {
			return false;
		}
		set_transient('xhtheme_aitoolbox_apicheck', 1, DAY_IN_SECONDS);
		$respapi = wp_remote_post(xh_apiurl(), [
			'headers' => [
				'Referer' => home_url()
			],
			'body' => [
				'type' => 'models',
				'pluginsver' => XHTHEME_AI_TOOLBOX_VERSION,
				'version' => $this->getVersion(),
				'apitoken' => xh_option('appId', '', $cache),
				'timestamp' => time()
			],
			'timeout' => 10,
			'sslverify' => false
		]);
		if (!is_wp_error($respapi)) {
			$body = wp_remote_retrieve_body($respapi);
			$response_data = json_decode($body, true);
			if (is_array($response_data) && isset($response_data['code']) && $response_data['code'] == 0) {
				$chatModels = $response_data['data']['modelList'];
				$this->updateModelList($response_data['data']);
				return $chatModels;
			}
			set_transient('xhtheme_aitoolbox_chatmodels_time', 1, 300);
			set_transient('xhtheme_aitoolbox_chatmodels_lasttime', time(), DAY_IN_SECONDS);
		} else {
			set_transient('xhtheme_aitoolbox_chatmodels_time', 1, 60);
		}
		return false;
	}

	public function updateModelList($userArgs)
	{
		update_option('xhtheme_aitoolbox_chatmodels', json_encode($userArgs['modelList'], JSON_UNESCAPED_UNICODE));
		update_option('xhtheme_aitoolbox_chatversion', $userArgs['version']);
		$this->updateDashboardMessages(isset($userArgs['dashboardMessages']) ? $userArgs['dashboardMessages'] : null);
		if (isset($userArgs['users']) && !empty($userArgs['users'])) {
			if (isset($userArgs['users']['error'])) {
				set_transient('xhtheme_aitoolbox_users_error', wp_json_encode($userArgs['users']['error']));
			} else {
				delete_transient('xhtheme_aitoolbox_users_error');
				update_option('xhtheme_aitoolbox_users', json_encode($userArgs['users'], JSON_UNESCAPED_UNICODE));
				set_transient('xhtheme_aitoolbox_users', 1, DAY_IN_SECONDS);
			}
		}
		$this->updateModeloption($userArgs['modelList']);
		set_transient('xhtheme_aitoolbox_chatmodels_time', 1, 300);
		set_transient('xhtheme_aitoolbox_chatmodels_lasttime', time(), DAY_IN_SECONDS);
		$this->resetRuntimeCache();
	}

	private function updateDashboardMessages($messages)
	{
		if (is_array($messages) && $this->hasDashboardMessages($messages)) {
			update_option(self::DASHBOARD_MESSAGES_OPTION, wp_json_encode($messages, JSON_UNESCAPED_UNICODE), false);
			return;
		}

		delete_option(self::DASHBOARD_MESSAGES_OPTION);
	}

	private function hasDashboardMessages($messages)
	{
		foreach ($messages as $messageGroup) {
			if (is_array($messageGroup) && !empty($messageGroup)) {
				return true;
			}
		}

		return false;
	}

	public function getDashboardMessages()
	{
		$messages = get_option(self::DASHBOARD_MESSAGES_OPTION, '');
		if (empty($messages)) {
			return [];
		}

		if (is_string($messages)) {
			$messages = json_decode($messages, true);
		}

		return is_array($messages) ? $messages : [];
	}

	public function getVersion()
	{
		if ($this->cached_version === null) {
			$this->cached_version = get_option('xhtheme_aitoolbox_chatversion', '1.0');
		}
		return $this->cached_version;
	}

	public function getModelTime()
	{
		if ($this->cached_updateTime === null) {
			$modelTime = get_transient('xhtheme_aitoolbox_chatmodels_lasttime');
			if (!empty($modelTime)) {
				$modelTime = gmdate('Y-m-d', $modelTime);
			} else {
				$modelTime = 'N/A';
			}
			$this->cached_updateTime = $modelTime;
		}
		return $this->cached_updateTime;
	}

	public function postupdate($request)
	{
		$response = ['success' => true, 'msg' => __('Content information retrieved!', 'xhtheme-ai-toolbox'), 'data' => []];
		if (!current_user_can('edit_posts')) {
			$response['success'] = false;
			$response['msg'] = __('You do not have permission to call the current interface!', 'xhtheme-ai-toolbox');
			return rest_ensure_response($response);
		}
		$params = $request->get_params();
		$postId = isset($params['postId']) ? absint($params['postId']) : 0;
		if (isset($params['description']) && !empty($params['description'])) {
			$response['data']['meta']['_xhai_excerpt'] = trim(wp_kses_post($params['description']));
			$response['data']['meta']['_excerptai'] = 2;
		}
		if (isset($params['tags']) && !empty($params['tags'])) {
			$response['data']['tags'] = [];
			$created_tags = [];

			// 动态获取标签 taxonomy
			$post = $postId ? get_post($postId) : null;
			$postTypedata = $post ? xh_postTypedata($post->post_type) : [];
			$tags_taxonomy = isset($postTypedata['tags']) ? $postTypedata['tags'] : 'post_tag';

			foreach ($params['tags'] as $key => $tagdata) {
				if (empty($tagdata) || !is_array($tagdata) || empty($tagdata['name']))
					continue;
				$tagName = sanitize_text_field($tagdata['name']);
				$tagExists = true;
				if ($tagdata['type'] == 'new' && !term_exists($tagName, $tags_taxonomy)) {
					$tagExists = false;
					$newtag = wp_insert_term($tagName, $tags_taxonomy, [
						'description' => $tagdata['description'],
						'slug' => $tagdata['slug']
					]);
					if (!is_wp_error($newtag)) {
						$response['data']['tags'][] = $newtag['term_id'];
						$created_tags[] = $tagName;
						if (isset($tagdata['title']) && !empty($tagdata['title'])) {
							add_term_meta($newtag['term_id'], '_seotitle', sanitize_text_field($tagdata['title']));
						}
					}
				}

				if ($tagExists) {
					$tagexist = term_exists($tagName, $tags_taxonomy);
					if (!empty($tagexist)) {
						$response['data']['tags'][] = $tagexist['term_id'];
					}
				}
			}

			// 增量更新标签缓存
			if (!empty($created_tags) && $post) {
				xh_update_tags_cache($post->post_type, null, $created_tags);
			}
		}
		if ($postId && isset($params['comment']) && !empty($params['comment'])) {
			$comment = XHComment::getInstance();
			$comment->pushComment($postId, $params['comment'], (int) $params['maxcomment'], (int) $params['maxdays']);
		}
		if (isset($params['postslug']) && !empty($params['postslug'])) {
			$response['data']['slug'] = sanitize_title($params['postslug']);
		}
		if (isset($params['postcategory']) && !empty($params['postcategory'])) {
			$response['data']['categories'] = [intval($params['postcategory'])];
		}

		if (isset($params['aiimage']) && !empty($params['aiimage'])) {
			$response['data']['meta']['_aiimage_cueword'] = trim(esc_attr($params['aiimage']));
			$response['data']['meta']['_aiimage_status'] = 1;
		}

		/**
		 * 扩展
		 */
		$newresponse = apply_filters('xhtheme_ai_toolbox_postupdate', $response, $params, $postId);
		return rest_ensure_response($newresponse);
	}

	public function checktag($request)
	{
		$response = ['success' => true, 'message' => __('Tag status retrieved!', 'xhtheme-ai-toolbox'), 'data' => []];
		$tagName = $request->get_param('name');

		if (empty($tagName)) {
			$response['success'] = false;
			$response['message'] = __('Please enter a tag name!', 'xhtheme-ai-toolbox');
			return rest_ensure_response($response);
		}

		// 处理单个标签或多个标签
		if (is_array($tagName)) {
			// 多标签处理
			foreach ($tagName as $tag) {
				$tagExists = term_exists($tag, 'post_tag');
				$response['data'][] = [
					'name' => $tag,
					'exists' => !empty($tagExists)
				];
			}
		} else {
			// 单标签处理（保持向后兼容）
			$tagExists = term_exists($tagName, 'post_tag');
			$response['data']['exists'] = !empty($tagExists);
		}

		return rest_ensure_response($response);
	}

	public function add_postmeta()
	{
		$postMeta_args = [
			'_excerptai' => 'integer',
			'_xhaitool_aitasks' => 'boolean',
			'_xhaitool_aitasks_status' => 'boolean',
			'_aiimage_cueword' => 'string',
			'_aiimage_status' => 'integer',
			'_xhai_excerpt' => 'string'  // 添加自定义摘要字段
		];
		foreach ($postMeta_args as $metakey => $typevalue) {
			register_meta(
				'post',
				$metakey,
				array(
					'show_in_rest' => true,
					'type' => $typevalue,
					'single' => true,
					'auth_callback' => '__return_true'
				)
			);
		}
	}

	public function add_restinit()
	{
		$jsonData = [
			'postupdate' => 'postupdate',
			'sync-user-args' => 'syncUserArgs',
			'checktag' => 'checktag',
			'getimagevl' => 'restGetImagevl'
		];
		foreach ($jsonData as $restName => $callback) {
			register_rest_route(XHTHEME_AI_TOOLBOX_RESTNAME, '/' . $restName, [
				'methods' => 'POST',
				'callback' => [$this, $callback],
				'permission_callback' => function () {
					return current_user_can('edit_posts');
				}
			]);
		}
	}

	/**
	 * REST API: 获取图片临时上传信息
	 */
		public function restGetImagevl($request)
		{
			$content = $request->get_param('content');

		if (empty($content)) {
			return rest_ensure_response(['imagevl' => null]);
		}

			$result = xh_get_imagevl(wp_kses_post($content));
			return rest_ensure_response(['imagevl' => $result]);
		}

		private function get_fullpost_localize_data()
		{
			global $pagenow;

			$screen = function_exists('get_current_screen') ? get_current_screen() : null;
			$isNewPostScreen = is_admin()
				&& isset($pagenow)
				&& $pagenow === 'post-new.php'
				&& $screen
				&& isset($screen->post_type)
				&& $screen->post_type === 'post';

			$defaultStyles = [
				['value' => '', 'label' => __('Default Style', 'xhtheme-ai-toolbox')],
				['value' => 'blogger', 'label' => __('Blog Article', 'xhtheme-ai-toolbox')],
				['value' => 'tutorial', 'label' => __('Documentation Tutorial', 'xhtheme-ai-toolbox')],
				['value' => 'news', 'label' => __('News Report', 'xhtheme-ai-toolbox')],
				['value' => 'story', 'label' => __('Storytelling', 'xhtheme-ai-toolbox')],
				['value' => 'diary', 'label' => __('Diary Voice', 'xhtheme-ai-toolbox')],
				['value' => 'marketing', 'label' => __('Marketing Copy', 'xhtheme-ai-toolbox')],
				['value' => 'webnovel', 'label' => __('Power Fantasy', 'xhtheme-ai-toolbox')],
			];

			$styles = $defaultStyles;

			return [
				'nonce' => wp_create_nonce('xhaitoolbox_fullpost_nonce'),
				'ajaxActions' => [
					'titleSuggest' => 'xhaitoolbox_fullpost_title_suggestions',
					'imageStart' => 'xhaitoolbox_fullpost_image_start',
					'imageStatus' => 'xhaitoolbox_fullpost_image_status',
					'imageFinalize' => 'xhaitoolbox_fullpost_image_finalize',
				],
				'image' => $this->get_fullpost_image_settings(),
				'language' => $this->get_fullpost_language_settings(),
				'styles' => $styles,
				'autoOpenOnNewPost' => (bool) xh_option('aiWorkbenchAutoOpen', false),
				'isNewPost' => $isNewPostScreen,
			];
		}

		private function get_fullpost_language_settings()
		{
			$languageCode = (string) xh_post_language();
			$languageOption = (string) xh_option('languageType', 'auto');
			$languageLabel = $this->get_fullpost_language_label($languageCode);
			$adminLanguageCode = (string) get_user_locale(get_current_user_id());
			if ($adminLanguageCode === '') {
				$adminLanguageCode = (string) get_locale();
			}
			$adminLanguageLabel = $this->get_fullpost_language_label($adminLanguageCode);
			$isAutoDetected = $languageOption === 'auto';
			$isSmartAuto = $languageOption === 'webauto' || $languageCode === 'auto';

			if ($isSmartAuto) {
				return [
					'code' => 'auto',
					'label' => __('Auto Detect', 'xhtheme-ai-toolbox'),
					'adminCode' => $adminLanguageCode,
					'adminLabel' => $adminLanguageLabel,
					'notice' => __('The output language will be detected automatically based on plugin settings. To use a fixed language, adjust the output language option in the plugin settings panel.', 'xhtheme-ai-toolbox'),
					'reason' => __('The plugin language mode is currently set to automatic detection.', 'xhtheme-ai-toolbox'),
				];
			}

			return [
				'code' => $languageCode,
				'label' => $languageLabel,
				'adminCode' => $adminLanguageCode,
				'adminLabel' => $adminLanguageLabel,
				'notice' => $isAutoDetected
					? sprintf(
						/* translators: %s: detected language label. */
						__('The plugin language follows the post or site language. This result is %s.', 'xhtheme-ai-toolbox'),
						$languageLabel
					)
					: sprintf(
						/* translators: %s: configured language label. */
						__('The plugin language is fixed to %s.', 'xhtheme-ai-toolbox'),
						$languageLabel
					),
			];
		}

		private function get_fullpost_language_label($languageCode)
		{
			$languageCode = str_replace('-', '_', strtolower((string) $languageCode));

			$languageMap = [
				'zh_cn' => __('Simplified Chinese', 'xhtheme-ai-toolbox'),
				'zh_tw' => __('Traditional Chinese', 'xhtheme-ai-toolbox'),
				'en' => __('English', 'xhtheme-ai-toolbox'),
				'en_us' => __('English (United States)', 'xhtheme-ai-toolbox'),
				'en_gb' => __('English (United Kingdom)', 'xhtheme-ai-toolbox'),
				'ja' => __('Japanese', 'xhtheme-ai-toolbox'),
				'ja_jp' => __('Japanese', 'xhtheme-ai-toolbox'),
				'ko' => __('Korean', 'xhtheme-ai-toolbox'),
				'ko_kr' => __('Korean', 'xhtheme-ai-toolbox'),
				'fr' => __('French', 'xhtheme-ai-toolbox'),
				'fr_fr' => __('French', 'xhtheme-ai-toolbox'),
				'de' => __('German', 'xhtheme-ai-toolbox'),
				'de_de' => __('German', 'xhtheme-ai-toolbox'),
				'es' => __('Spanish', 'xhtheme-ai-toolbox'),
				'es_es' => __('Spanish', 'xhtheme-ai-toolbox'),
				'ru' => __('Russian', 'xhtheme-ai-toolbox'),
				'ru_ru' => __('Russian', 'xhtheme-ai-toolbox'),
				'pt' => __('Portuguese', 'xhtheme-ai-toolbox'),
				'pt_br' => __('Portuguese (Brazil)', 'xhtheme-ai-toolbox'),
				'it' => __('Italian', 'xhtheme-ai-toolbox'),
				'it_it' => __('Italian', 'xhtheme-ai-toolbox'),
				'ar' => __('Arabic', 'xhtheme-ai-toolbox'),
				'ar_sa' => __('Arabic', 'xhtheme-ai-toolbox'),
			];

			if (isset($languageMap[$languageCode])) {
				return $languageMap[$languageCode];
			}

			if (strpos($languageCode, 'zh_') === 0) {
				return __('Chinese', 'xhtheme-ai-toolbox');
			}

			if (strpos($languageCode, 'en_') === 0) {
				return __('English', 'xhtheme-ai-toolbox');
			}

			$languageCode = strtoupper(str_replace('_', '-', $languageCode));
			return $languageCode !== '' ? $languageCode : __('Current Language', 'xhtheme-ai-toolbox');
		}

		private function get_fullpost_image_settings()
		{
			$imagePattern = xh_option('imagePlatform', 'default');
			$imagePromptLevel = sanitize_key((string) xh_option('imagePromptLevel', 'safe'));

			if (!in_array($imagePattern, ['default', 'aliyun', 'cogview'], true)) {
				$imagePattern = 'default';
			}

			if (!in_array($imagePromptLevel, ['safe', 'aggressive'], true)) {
				$imagePromptLevel = 'safe';
			}

			return [
				'enabled' => (bool) xh_option('imageThumb', false),
				'platform' => $imagePattern,
				'size' => (string) xh_option('imageSize', '1280x768'),
				'style' => (string) xh_option('imageStyle', 'auto'),
				'promptLevel' => $imagePromptLevel,
				'pattern' => (string) xh_option('imagePattern', 'fill'),
				'mapnum' => (int) xh_option('imageMapnum', 1),
				'mark' => (bool) xh_option('imageMark', false),
				'compress' => (bool) xh_option('imageCompress', true),
				'modelCode' => (string) xh_option('imageModelCode', ''),
				'region' => (string) xh_option('imageAliyunRegion', 'beijing'),
				'placeholderUrl' => (string) apply_filters('xhaitoolbox_fullpost_placeholder_image', plugin_dir_url(dirname(__FILE__)) . 'assets/images/94a3b8.svg'),
			];
		}

		private function get_fullpost_ajax_payload()
		{
			$payload = [];

			// phpcs:ignore WordPress.Security.NonceVerification.Missing, WordPress.Security.ValidatedSanitizedInput.InputNotSanitized -- Nonce is checked by AJAX handlers before reading payload; decoded values are sanitized by each handler.
			if (isset($_POST['payload'])) {
				$decoded = json_decode(wp_unslash($_POST['payload']), true);
				if (is_array($decoded)) {
					$payload = $decoded;
				}
			}

			return $payload;
		}

		public function ajax_fullpost_title_suggestions()
		{
			check_ajax_referer('xhaitoolbox_fullpost_nonce', '_ajax_nonce');

			if (!current_user_can('edit_posts')) {
				wp_send_json_error([
					'message' => __('The current user does not have permission to use Full Post AI.', 'xhtheme-ai-toolbox'),
				]);
			}

			$payload = $this->get_fullpost_ajax_payload();
			$title = isset($payload['title']) ? sanitize_text_field($payload['title']) : '';
			$content = isset($payload['content']) ? wp_strip_all_tags((string) $payload['content']) : '';
			$mode = isset($payload['mode']) ? sanitize_key($payload['mode']) : 'write';
			$condition = isset($payload['condition']) ? sanitize_text_field($payload['condition']) : '';
			$targetLanguage = isset($payload['targetLanguage']) ? sanitize_text_field($payload['targetLanguage']) : '';
			$rejectedTitles = [];
			if (isset($payload['rejectedTitles']) && is_array($payload['rejectedTitles'])) {
				$rejectedTitles = array_slice(
					array_values(
						array_filter(
							array_map('sanitize_text_field', $payload['rejectedTitles'])
						)
					),
					0,
					30
				);
			}

			$result = xh_api_request('fullpost-title', [
				'content' => $content,
				'posttitle' => $title,
				'language' => xh_post_language(),
				'args' => [
					'mode' => $mode,
					'condition' => $condition,
					'targetLang' => $targetLanguage,
					'rejectedTitles' => $rejectedTitles,
				],
			], null, 'aidata', 40);

			if (is_wp_error($result)) {
				wp_send_json_error([
					'message' => $result->get_error_message(),
					'error' => $result->get_error_data(),
				]);
			}

			$titles = [];
			if (is_array($result) && isset($result['titles']) && is_array($result['titles'])) {
				$titles = array_values(array_filter(array_map('sanitize_text_field', $result['titles'])));
			}
				if (!empty($rejectedTitles) && !empty($titles)) {
					$normalize_title = static function ($value) {
						$value = preg_replace('/\s+/u', '', (string) $value);
						return function_exists('mb_strtolower') ? mb_strtolower($value, 'UTF-8') : strtolower($value);
					};
					$rejectedMap = array_fill_keys(array_map($normalize_title, $rejectedTitles), true);
					$titles = array_values(array_filter($titles, static function ($item) use ($normalize_title, $rejectedMap) {
						return !isset($rejectedMap[$normalize_title($item)]);
				}));
			}

			if (empty($titles)) {
				wp_send_json_error([
					'message' => __('Failed to generate title suggestions. Please try again later.', 'xhtheme-ai-toolbox'),
				]);
			}

			wp_send_json_success([
				'titles' => array_slice($titles, 0, 5),
				'usesMock' => false,
			]);
		}

	private function get_fullpost_image_batch_transient_key($batchKey)
		{
			return 'xhaitoolbox_fullpost_image_batch_' . md5((string) $batchKey);
		}

		private function get_fullpost_image_job_transient_key($jobId)
		{
			return 'xhaitoolbox_fullpost_image_job_' . md5((string) $jobId);
		}

		private function get_fullpost_image_batch_slot_transient_key($batchKey, $placeholderIndex)
		{
			return 'xhaitoolbox_fullpost_image_batch_slot_' . md5((string) $batchKey . '|' . intval($placeholderIndex));
		}

		private function get_fullpost_image_batch($batchKey)
		{
			if (empty($batchKey)) {
				return null;
			}

			$batch = get_transient($this->get_fullpost_image_batch_transient_key($batchKey));
			return is_array($batch) ? $batch : null;
		}

		private function set_fullpost_image_batch($batchKey, $batch, $expiration = DAY_IN_SECONDS)
		{
			if (empty($batchKey) || !is_array($batch)) {
				return false;
			}

			$currentBatch = get_transient($this->get_fullpost_image_batch_transient_key($batchKey));
			$currentBatch = is_array($currentBatch) ? $currentBatch : [];
			$currentJobIds = isset($currentBatch['jobIds']) && is_array($currentBatch['jobIds']) ? $currentBatch['jobIds'] : [];
			$nextJobIds = isset($batch['jobIds']) && is_array($batch['jobIds']) ? $batch['jobIds'] : [];
			$mergedJobIds = array_values(array_unique(array_filter(array_merge(
				array_map('sanitize_text_field', $currentJobIds),
				array_map('sanitize_text_field', $nextJobIds)
			))));

			$mergedBatch = array_merge($currentBatch, $batch, [
				'batchKey' => sanitize_text_field((string) $batchKey),
				'jobIds' => $mergedJobIds,
				'expectedTotal' => max(
					intval($currentBatch['expectedTotal'] ?? 0),
					intval($batch['expectedTotal'] ?? 0)
				),
				'finalized' => !empty($currentBatch['finalized']) || !empty($batch['finalized']),
				'createdAt' => intval($currentBatch['createdAt'] ?? $batch['createdAt'] ?? time()),
				'updatedAt' => intval($batch['updatedAt'] ?? time()),
			]);

			return set_transient($this->get_fullpost_image_batch_transient_key($batchKey), $mergedBatch, $expiration);
		}

		private function get_fullpost_image_job($jobId)
		{
			if (empty($jobId)) {
				return null;
			}

			$job = get_transient($this->get_fullpost_image_job_transient_key($jobId));
			return is_array($job) ? $job : null;
		}

		private function set_fullpost_image_job($jobId, $job, $expiration = DAY_IN_SECONDS)
		{
			if (empty($jobId) || !is_array($job)) {
				return false;
			}

			return set_transient($this->get_fullpost_image_job_transient_key($jobId), $job, $expiration);
		}

		private function get_fullpost_image_batch_slot_job_id($batchKey, $placeholderIndex)
		{
			if (empty($batchKey) || intval($placeholderIndex) <= 0) {
				return '';
			}

			$jobId = get_transient($this->get_fullpost_image_batch_slot_transient_key($batchKey, $placeholderIndex));
			return is_string($jobId) ? sanitize_text_field($jobId) : '';
		}

		private function set_fullpost_image_batch_slot_job_id($batchKey, $placeholderIndex, $jobId, $expiration = DAY_IN_SECONDS)
		{
			$batchKey = sanitize_text_field((string) $batchKey);
			$placeholderIndex = intval($placeholderIndex);
			$jobId = sanitize_text_field((string) $jobId);
			if ($batchKey === '' || $placeholderIndex <= 0 || $jobId === '') {
				return false;
			}

			return set_transient(
				$this->get_fullpost_image_batch_slot_transient_key($batchKey, $placeholderIndex),
				$jobId,
				$expiration
			);
		}

		private function trigger_fullpost_image_cron()
		{
			if (function_exists('spawn_cron')) {
				spawn_cron(time());
				return;
			}

			wp_remote_post(site_url('/wp-cron.php?doing_wp_cron=' . rawurlencode((string) microtime(true))), [
				'timeout' => 0.01,
				'blocking' => false,
				'sslverify' => apply_filters('https_local_ssl_verify', false),
			]);
		}

		private function build_fullpost_image_worker_token($jobId)
		{
			return wp_hash('xhaitoolbox_fullpost_image_worker|' . sanitize_text_field((string) $jobId));
		}

		private function dispatch_fullpost_image_worker($jobId)
		{
			$jobId = sanitize_text_field((string) $jobId);
			if ($jobId === '') {
				return false;
			}

			$response = wp_remote_post(admin_url('admin-ajax.php'), [
				'timeout' => 1,
				'blocking' => false,
				'sslverify' => apply_filters('https_local_ssl_verify', false),
				'body' => [
					'action' => 'xhaitoolbox_fullpost_image_worker',
					'jobId' => $jobId,
					'token' => $this->build_fullpost_image_worker_token($jobId),
				],
			]);

			return !is_wp_error($response);
		}

		private function respond_fullpost_image_worker_ack($payload = [])
		{
			if (!headers_sent()) {
				nocache_headers();
				header('Content-Type: application/json; charset=' . get_option('blog_charset'));
				status_header(200);
			}

			echo wp_json_encode([
				'success' => true,
				'data' => is_array($payload) ? $payload : [],
			]);

			if (function_exists('fastcgi_finish_request')) {
				fastcgi_finish_request();
				return;
			}

			if (function_exists('litespeed_finish_request')) {
				litespeed_finish_request();
				return;
			}

			while (ob_get_level() > 0) {
				@ob_end_flush();
			}

			@flush();
		}

		private function schedule_fullpost_image_job($jobId, $delay = 0)
		{
			$jobId = sanitize_text_field((string) $jobId);
			if ($jobId === '') {
				return;
			}

			$hook = 'xhaitoolbox_fullpost_image_process_job';
			$timestamp = time() + max(0, intval($delay));
			$nextScheduled = wp_next_scheduled($hook, [$jobId]);

			if (!$nextScheduled) {
				wp_schedule_single_event($timestamp, $hook, [$jobId]);
			}

			$this->trigger_fullpost_image_cron();
		}

		private function build_fullpost_image_batch_payload($batch, $jobs)
		{
			$jobs = is_array($jobs) ? $jobs : [];
			usort($jobs, function ($left, $right) {
				return intval($left['placeholderIndex'] ?? 0) <=> intval($right['placeholderIndex'] ?? 0);
			});

			$activeCount = 0;
			$completedCount = 0;
			$failedCount = 0;

			foreach ($jobs as $job) {
				$status = (string) ($job['status'] ?? 'queued');
				if (in_array($status, ['starting', 'queued', 'processing', 'polling'], true)) {
					$activeCount++;
				} elseif ($status === 'completed') {
					$completedCount++;
				} elseif ($status === 'error') {
					$failedCount++;
				}
			}

			$expectedTotal = max(0, intval($batch['expectedTotal'] ?? 0));
			$finalized = !empty($batch['finalized']);
			$resolvedCount = $completedCount + $failedCount;
			$status = 'processing';

			if ($finalized && $expectedTotal === 0) {
				$status = 'completed';
			} elseif ($activeCount > 0 || !$finalized || $resolvedCount < $expectedTotal) {
				$status = 'processing';
			} elseif ($failedCount > 0) {
				$status = 'error';
			} else {
				$status = 'completed';
			}

			$batch['status'] = $status;
			$batch['jobCount'] = count($jobs);
			$batch['activeCount'] = $activeCount;
			$batch['completedCount'] = $completedCount;
			$batch['failedCount'] = $failedCount;
			$batch['updatedAt'] = time();
			$batch['jobIds'] = array_values(array_unique(array_filter(array_merge(
				array_map('sanitize_text_field', isset($batch['jobIds']) && is_array($batch['jobIds']) ? $batch['jobIds'] : []),
				array_map(function ($job) {
				return isset($job['jobId']) ? sanitize_text_field((string) $job['jobId']) : '';
				}, $jobs)
			))));

			return [
				'batch' => $batch,
				'jobs' => $jobs,
			];
		}

		private function refresh_fullpost_image_batch($batchKey)
		{
			$batch = $this->get_fullpost_image_batch($batchKey);
			if (!is_array($batch)) {
				return null;
			}

			$jobs = [];
			$jobIds = isset($batch['jobIds']) && is_array($batch['jobIds']) ? $batch['jobIds'] : [];
			for ($index = 1; $index <= 5; $index++) {
				$slotJobId = $this->get_fullpost_image_batch_slot_job_id($batchKey, $index);
				if ($slotJobId !== '') {
					$jobIds[] = $slotJobId;
				}
			}
			$jobIds = array_values(array_unique(array_filter(array_map('sanitize_text_field', $jobIds))));
			foreach ($jobIds as $jobId) {
				$jobId = sanitize_text_field((string) $jobId);
				if ($jobId === '') {
					continue;
				}

				$job = $this->get_fullpost_image_job($jobId);
				if (is_array($job)) {
					$jobs[] = $job;
				}
			}

			$payload = $this->build_fullpost_image_batch_payload($batch, $jobs);

			return $payload;
		}

		private function find_fullpost_image_job_by_placeholder($batchKey, $placeholderUrl)
		{
			$batchPayload = $this->refresh_fullpost_image_batch($batchKey);
			if (!is_array($batchPayload) || empty($placeholderUrl)) {
				return null;
			}

			foreach ($batchPayload['jobs'] as $job) {
				if (($job['placeholderUrl'] ?? '') === $placeholderUrl) {
					return $job;
				}
			}

			return null;
		}

		private function format_fullpost_image_job_response($job)
		{
			return [
				'jobId' => isset($job['jobId']) ? sanitize_text_field((string) $job['jobId']) : '',
				'batchKey' => isset($job['batchKey']) ? sanitize_text_field((string) $job['batchKey']) : '',
				'status' => isset($job['status']) ? sanitize_key((string) $job['status']) : 'queued',
				'prompt' => isset($job['prompt']) ? sanitize_text_field((string) $job['prompt']) : '',
				'placeholderUrl' => isset($job['placeholderUrl']) ? esc_url_raw($job['placeholderUrl']) : '',
				'placeholderIndex' => intval($job['placeholderIndex'] ?? 0),
				'imageUrl' => isset($job['imageUrl']) ? esc_url_raw($job['imageUrl']) : '',
				'message' => isset($job['message']) ? sanitize_text_field((string) $job['message']) : '',
			];
		}

		private function update_fullpost_image_job($jobId, $updates = [])
		{
			$job = $this->get_fullpost_image_job($jobId);
			if (!is_array($job)) {
				return null;
			}

			$job = array_merge($job, $updates, [
				'updatedAt' => time(),
			]);
			$this->set_fullpost_image_job($jobId, $job);
			$this->refresh_fullpost_image_batch($job['batchKey'] ?? '');

			return $job;
		}

		public function ajax_fullpost_image_start()
		{
			check_ajax_referer('xhaitoolbox_fullpost_nonce', '_ajax_nonce');

			if (!current_user_can('edit_posts')) {
				wp_send_json_error([
					'message' => __('The current user does not have permission to use Full Post AI.', 'xhtheme-ai-toolbox'),
				]);
			}

			$imageSettings = $this->get_fullpost_image_settings();
			if (empty($imageSettings['enabled'])) {
				wp_send_json_error([
					'message' => __('AI image generation is not enabled for this plugin, so automatic images cannot be generated.', 'xhtheme-ai-toolbox'),
					'imageSettings' => $imageSettings,
				]);
			}

			$payload = $this->get_fullpost_ajax_payload();
			$batchKey = isset($payload['batchKey']) ? sanitize_text_field((string) $payload['batchKey']) : '';
			$prompt = isset($payload['prompt']) ? sanitize_text_field((string) $payload['prompt']) : '';
			$placeholderUrl = isset($payload['placeholderUrl']) ? esc_url_raw($payload['placeholderUrl']) : '';
			$placeholderIndex = max(1, min(5, intval($payload['placeholderIndex'] ?? 1)));
			$mode = isset($payload['mode']) ? sanitize_key((string) $payload['mode']) : 'write';
			$apitype = isset($payload['apitype']) ? sanitize_key((string) $payload['apitype']) : '';

			if ($batchKey === '') {
				$batchKey = 'xhai-fullpost-image-' . wp_generate_uuid4();
			}

			if ($prompt === '' || $placeholderUrl === '') {
				wp_send_json_error([
					'message' => __('Image prompt or placeholder data is missing, so the image task cannot be created.', 'xhtheme-ai-toolbox'),
				]);
			}

			$existingJob = $this->find_fullpost_image_job_by_placeholder($batchKey, $placeholderUrl);
			if (is_array($existingJob)) {
				wp_send_json_success($this->format_fullpost_image_job_response($existingJob));
			}

			$batch = $this->get_fullpost_image_batch($batchKey);
			if (!is_array($batch)) {
				$batch = [
					'batchKey' => $batchKey,
					'mode' => $mode,
					'createdAt' => time(),
					'updatedAt' => time(),
					'expectedTotal' => 0,
					'finalized' => false,
					'jobIds' => [],
					'status' => 'processing',
				];
			}

			$jobId = wp_generate_uuid4();
			$job = [
				'jobId' => $jobId,
				'batchKey' => $batchKey,
				'mode' => $mode,
				'status' => 'starting',
				'createdAt' => time(),
				'updatedAt' => time(),
				'prompt' => $prompt,
				'placeholderUrl' => $placeholderUrl,
				'placeholderIndex' => $placeholderIndex,
				'apitype' => $apitype,
				'imageSettings' => $imageSettings,
				'pattern' => $imageSettings['platform'],
				'taskId' => '',
				'imageUrl' => '',
				'message' => '',
				'attemptCount' => 0,
				'maxAttempts' => 6,
			];

			$batch['jobIds'][] = $jobId;
			$batch['updatedAt'] = time();
			$this->set_fullpost_image_job($jobId, $job);
			$this->set_fullpost_image_batch_slot_job_id($batchKey, $placeholderIndex, $jobId);
			$this->set_fullpost_image_batch($batchKey, $batch);

			$dispatched = $this->dispatch_fullpost_image_worker($jobId);
			if (!$dispatched) {
				$this->schedule_fullpost_image_job($jobId, 0);
			}

			wp_send_json_success($this->format_fullpost_image_job_response($job));
		}

		public function ajax_fullpost_image_worker()
		{
			$jobId = isset($_REQUEST['jobId']) ? sanitize_text_field(wp_unslash((string) $_REQUEST['jobId'])) : '';
			$token = isset($_REQUEST['token']) ? sanitize_text_field(wp_unslash((string) $_REQUEST['token'])) : '';

			if ($jobId === '' || $token === '' || !hash_equals($this->build_fullpost_image_worker_token($jobId), $token)) {
				if (!headers_sent()) {
					status_header(403);
					header('Content-Type: application/json; charset=' . get_option('blog_charset'));
				}
				echo wp_json_encode([
					'success' => false,
					'data' => [
						'message' => __('Image task verification failed.', 'xhtheme-ai-toolbox'),
					],
				]);
				exit;
			}

			@ignore_user_abort(true);
			@set_time_limit(180);

			$this->respond_fullpost_image_worker_ack([
				'accepted' => true,
				'jobId' => $jobId,
			]);

			$this->process_fullpost_image_job($jobId);
			exit;
		}

		public function ajax_fullpost_image_finalize()
		{
			check_ajax_referer('xhaitoolbox_fullpost_nonce', '_ajax_nonce');

			if (!current_user_can('edit_posts')) {
				wp_send_json_error([
					'message' => __('The current user does not have permission to use Full Post AI.', 'xhtheme-ai-toolbox'),
				]);
			}

			$payload = $this->get_fullpost_ajax_payload();
			$batchKey = isset($payload['batchKey']) ? sanitize_text_field((string) $payload['batchKey']) : '';
			$expectedTotal = max(0, min(5, intval($payload['expectedTotal'] ?? 0)));

			if ($batchKey === '') {
				wp_send_json_error([
					'message' => __('Missing image batch ID, so the image task cannot be confirmed.', 'xhtheme-ai-toolbox'),
				]);
			}

			$batch = $this->get_fullpost_image_batch($batchKey);
			if (!is_array($batch)) {
				wp_send_json_error([
					'message' => __('No matching image batch was found. Please regenerate the article.', 'xhtheme-ai-toolbox'),
				]);
			}

			$batch['expectedTotal'] = $expectedTotal;
			$batch['finalized'] = true;
			$batch['updatedAt'] = time();
			$this->set_fullpost_image_batch($batchKey, $batch);
			$batchPayload = $this->refresh_fullpost_image_batch($batchKey);

			wp_send_json_success([
				'batchKey' => $batchKey,
				'status' => $batchPayload['batch']['status'] ?? 'processing',
				'expectedTotal' => intval($batchPayload['batch']['expectedTotal'] ?? 0),
				'jobs' => array_map([$this, 'format_fullpost_image_job_response'], $batchPayload['jobs'] ?? []),
			]);
		}

		public function ajax_fullpost_image_status()
		{
			check_ajax_referer('xhaitoolbox_fullpost_nonce', '_ajax_nonce');

			if (!current_user_can('edit_posts')) {
				wp_send_json_error([
					'message' => __('The current user does not have permission to use Full Post AI.', 'xhtheme-ai-toolbox'),
				]);
			}

			$payload = $this->get_fullpost_ajax_payload();
			$batchKey = isset($payload['batchKey']) ? sanitize_text_field((string) $payload['batchKey']) : '';

			if ($batchKey === '') {
				wp_send_json_error([
					'message' => __('Missing image batch ID.', 'xhtheme-ai-toolbox'),
				]);
			}

			$batchPayload = $this->refresh_fullpost_image_batch($batchKey);
			if (!is_array($batchPayload)) {
				wp_send_json_error([
					'message' => __('No matching image task was found. Please regenerate.', 'xhtheme-ai-toolbox'),
				]);
			}

			if (($batchPayload['batch']['status'] ?? '') === 'processing') {
				$this->trigger_fullpost_image_cron();
			}

			wp_send_json_success([
				'batchKey' => $batchKey,
				'status' => $batchPayload['batch']['status'] ?? 'processing',
				'expectedTotal' => intval($batchPayload['batch']['expectedTotal'] ?? 0),
				'finalized' => !empty($batchPayload['batch']['finalized']),
				'activeCount' => intval($batchPayload['batch']['activeCount'] ?? 0),
				'completedCount' => intval($batchPayload['batch']['completedCount'] ?? 0),
				'failedCount' => intval($batchPayload['batch']['failedCount'] ?? 0),
				'jobs' => array_map([$this, 'format_fullpost_image_job_response'], $batchPayload['jobs'] ?? []),
			]);
		}

		public function process_fullpost_image_job($jobId)
		{
			@ignore_user_abort(true);
			@set_time_limit(180);

			$jobId = sanitize_text_field((string) $jobId);
			if ($jobId === '') {
				return;
			}

			$job = $this->get_fullpost_image_job($jobId);
			if (!is_array($job) || in_array(($job['status'] ?? ''), ['completed', 'error'], true)) {
				return;
			}

			$imageSettings = isset($job['imageSettings']) && is_array($job['imageSettings'])
				? $job['imageSettings']
				: $this->get_fullpost_image_settings();
			$imageApi = XHAiimage::getInstance();

			if (empty($job['taskId'])) {
				$job = $this->update_fullpost_image_job($jobId, [
					'status' => 'processing',
					'message' => '',
				]);
				if (!is_array($job)) {
					return;
				}

				$imageResult = $imageApi->imageapi_create($job['prompt'], $imageSettings['platform'], [
					'size' => $imageSettings['size'],
					'style' => $imageSettings['style'],
					'mark' => $imageSettings['mark'],
					'scene' => 'fullpost-inline-image',
					'apitype' => $job['apitype'] ?? '',
					'pattern' => $imageSettings['pattern'],
					'mapnum' => $imageSettings['mapnum'],
				]);

				if (empty($imageResult['success'])) {
					$this->update_fullpost_image_job($jobId, [
						'status' => 'error',
						'message' => isset($imageResult['msg']) ? sanitize_text_field((string) $imageResult['msg']) : __('Automatic image task creation failed. Please try again later.', 'xhtheme-ai-toolbox'),
					]);
					return;
				}

				if (!empty($imageResult['notask']) && !empty($imageResult['imageUrl'])) {
					$this->update_fullpost_image_job($jobId, [
						'status' => 'completed',
						'imageUrl' => esc_url_raw($imageResult['imageUrl']),
						'message' => '',
						'completedAt' => time(),
					]);
					return;
				}

				$taskId = !empty($imageResult['task_id']) ? sanitize_text_field((string) $imageResult['task_id']) : '';
				if ($taskId === '') {
					$this->update_fullpost_image_job($jobId, [
						'status' => 'error',
						'message' => __('The image task was created but no task ID was returned. Please try again later.', 'xhtheme-ai-toolbox'),
					]);
					return;
				}

				$this->update_fullpost_image_job($jobId, [
					'status' => 'polling',
					'taskId' => $taskId,
					'message' => '',
					'attemptCount' => 0,
				]);

				$job = $this->get_fullpost_image_job($jobId);
				if (!is_array($job)) {
					return;
				}
			}

			$attemptCount = intval($job['attemptCount'] ?? 0);
			$maxAttempts = max(1, intval($job['maxAttempts'] ?? 6));

			while ($attemptCount < $maxAttempts) {
				sleep(10);

				$currentJob = $this->get_fullpost_image_job($jobId);
				if (!is_array($currentJob) || in_array(($currentJob['status'] ?? ''), ['completed', 'error'], true)) {
					return;
				}

				$attemptCount++;
				$this->update_fullpost_image_job($jobId, [
					'status' => 'polling',
					'message' => '',
					'attemptCount' => $attemptCount,
				]);

				$imageResult = $imageApi->imageapi_get($currentJob['taskId'], $currentJob['pattern'] ?? 'default');
				if (!empty($imageResult['success']) && !empty($imageResult['imageUrl'])) {
					$this->update_fullpost_image_job($jobId, [
						'status' => 'completed',
						'imageUrl' => esc_url_raw($imageResult['imageUrl']),
						'message' => '',
						'attemptCount' => $attemptCount,
						'completedAt' => time(),
					]);
					return;
				}

				if (isset($imageResult['type']) && (int) $imageResult['type'] === 2) {
					continue;
				}

				$this->update_fullpost_image_job($jobId, [
					'status' => 'error',
					'message' => isset($imageResult['msg']) ? sanitize_text_field((string) $imageResult['msg']) : __('Automatic image status query failed. Please try again later.', 'xhtheme-ai-toolbox'),
					'attemptCount' => $attemptCount,
				]);
				return;
			}

			$this->update_fullpost_image_job($jobId, [
				'status' => 'error',
				'message' => __('Image generation timed out. Please try again later.', 'xhtheme-ai-toolbox'),
				'attemptCount' => $attemptCount,
			]);
		}

		public function chatLists($type = 'admin')
		{
		$newChats = [];
		$chatModels = [];

		$chatModeldata = get_option('xhtheme_aitoolbox_chatmodels');
		if ($chatModeldata) {
			$dataModels = json_decode($chatModeldata, true);
			if ($dataModels && is_array($dataModels)) {
				$chatModels = $dataModels;
			}
		}
		if ((!$chatModels && !get_transient('xhtheme_aitoolbox_chatmodels_time')) || ($chatModels && !get_transient('xhtheme_aitoolbox_chatmodels_lasttime'))) {
			// 远程请求模型列表
			$chatModelData = $this->fetchRemoteModelList();
			if ($chatModelData && is_array($chatModelData)) {
				$chatModels = $chatModelData;
			} else {
				$chatModeldata = get_option('xhtheme_aitoolbox_chatmodels');
				if ($chatModeldata) {
					$dataModels = json_decode($chatModeldata, true);
					if ($dataModels && is_array($dataModels)) {
						$chatModels = $dataModels;
					}
				}
			}
		}

		// 当前后台语言
		$currentLang = get_locale();

		if ($type == 'localize') {
			$hasRemoteModels = !empty($chatModels) && is_array($chatModels);
			if (!$hasRemoteModels) {
				// 远程模型列表不可用时，保留一个本地自动模式作为兜底
				$newChats[] = [
					'value' => 'auto',
					'label' => __('Auto Mode', 'xhtheme-ai-toolbox'),
					'badge' => [
						'type' => 'hot',
						'text' => __('Best', 'xhtheme-ai-toolbox')
					]
				];
			}
			if ($hasRemoteModels) {
				foreach ($chatModels as $chat) {
					if (isset($chat['badge']['text_' . $currentLang])) {
						$chat['badge']['text'] = $chat['badge']['text_' . $currentLang];
						unset($chat['badge']['text_' . $currentLang]);
					}
					if (isset($chat['member']) && is_array($chat['member'])) {
						if (isset($chat['member']['popdata_' . $currentLang])) {
							$chat['member']['popdata'] = $chat['member']['popdata_' . $currentLang];
							unset($chat['member']['popdata_' . $currentLang]);
						}
					}
					$newChats[] = [
						'value' => $chat['name'],
						'label' => isset($chat['label_' . $currentLang]) && !empty($chat['label_' . $currentLang]) ? $chat['label_' . $currentLang] : $chat['label'],
						'badge' => isset($chat['badge']) && !empty($chat['badge']) ? $chat['badge'] : false,
						'member' => isset($chat['member']) && is_array($chat['member']) ? $chat['member'] : false
					];
				}
			}
			if (!empty($newChats)) {
				$dedupedChats = [];
				foreach ($newChats as $chat) {
					$chatValue = isset($chat['value']) ? (string) $chat['value'] : '';
					if ($chatValue === '' || isset($dedupedChats[$chatValue])) {
						continue;
					}
					$dedupedChats[$chatValue] = $chat;
				}
				$newChats = array_values($dedupedChats);
			}
		} elseif ($type == 'list') {
			//$newChats = $chatModels;
			$newChats = [];
			if (!empty($chatModels) && is_array($chatModels)) {
				foreach ($chatModels as $chat) {
					if (isset($chat['label_' . $currentLang])) {
						$chat['label'] = $chat['label_' . $currentLang];
					}
					$newChats[] = $chat;
				}
			}
		} else {
			$newChats = [];
			if (!empty($chatModels) && is_array($chatModels)) {
				foreach ($chatModels as $chat) {
					if (isset($chat['label_' . $currentLang])) {
						$chat['label'] = $chat['label_' . $currentLang];
					}
					$newChats[] = $chat;
				}
			}
		}
		return $newChats;
	}

	public function chatModels($type)
	{
		// 检测是否关闭标签摘要的生成
		if ($type == 'post') {
			$tagsOff = xh_option('tagEnabled', false);
			$description = xh_option('summaryEnabled', false);
			$comments = xh_option('commentEnabled', false);
			if (!$tagsOff && !$description && !$comments) {
				return 'none';
			}
		}
		$models = xh_option('modelType', 'auto');
		if ($models == 'auto')
			return $models;
		$chatLists = $this->chatLists('list');
		if (!$chatLists || !is_array($chatLists)) {
			return 'auto';
		}
		$retChat = '';
		foreach ($chatLists as $chat) {
			if ($chat['name'] == $models) {
				$retChat = $models;
				break;
			}
		}

		if (empty($retChat)) {
			$this->updateModeloption($chatLists, [$type]);
			$retChat = 'auto';
		}
		return $retChat;
	}

	public function add_enqueue_assets()
	{
		$screen = get_current_screen();
		if ($screen->id == 'widgets')
			return;
		$apiToken = xh_option('appId', '');
		//if(!$apiToken) return;
		$plugin_dir = plugin_dir_path(dirname(__FILE__));
		$plugin_url = plugin_dir_url(dirname(__FILE__));
		$postai_file = $plugin_dir . 'build/blocks.asset.php';
		$usetShow = $this->isMember();
		if (file_exists($postai_file)) {
			$assets = include $postai_file;
			wp_enqueue_script(
				'xhtheme-ai-toolbox-blocks',
				$plugin_url . 'build/blocks.js',
				$assets['dependencies'],
				$assets['version'],
				true
			);
			wp_enqueue_style(
				'xhtheme-ai-toolbox-blocks',
				$plugin_url . 'build/blocks.css',
				[],
				$assets['version']
			);

			wp_set_script_translations('xhtheme-ai-toolbox-blocks', 'xhtheme-ai-toolbox', plugin_dir_path(dirname(__FILE__)) . 'languages');

			$modelsPost = $this->chatModels('post');
				$localize = [
					'chatModels' => $this->chatLists('localize'),
					'userType' => $this->userData('type'),
					'userName' => $this->userData('name'),
				'models' => [
					'paragraph' => $this->chatModels('paragraph'),
					'post' => $modelsPost
				],
				'queue' => true,
				'args' => [],
				'paragraph' => xh_option('paragraphCapacity', ['optimize']),
				'version' => $this->getVersion(),
				'apiurl' => xh_apiurl(),
				'pluginUrl' => plugin_dir_url(dirname(__FILE__)),
				'apivar' => XHTHEME_AI_TOOLBOX_APIVERSION,
				'language' => xh_post_language(),
				//'imagerec'  => xh_option('imageRecognition',true),
				'imagerec' => true,
				'apitoken' => $apiToken,
				'ajaxUrl' => admin_url('admin-ajax.php'),
				'aitaskoption' => false,
				'aitaskoptionLink' => admin_url('admin.php?page=xhtheme-ai-automate'),
				'fullpost' => $this->get_fullpost_localize_data()
				];

			/**
			 * 判断自动化配置是否完成
			 */
			$localize['aitasks'] = xh_postType_config($screen->post_type, 'queue');
			if (xh_postType_config($screen->post_type, 'tasks')) {
				$localize['aitaskoption'] = true;
			}


			if ($modelsPost !== 'none') {
				$localize['args']['post'] = [];

				// 元数据补全
				$primaryMeta = [];
				$postTypedata = xh_postTypedata($screen->post_type);
				$postTypeTasks = $postTypedata && isset($postTypedata['tasks']) && is_array($postTypedata['tasks']) ? $postTypedata['tasks'] : [];
				if (xh_option('primarySlug', false) && in_array('slug', $postTypeTasks)) {
					$primaryMeta['postslug'] = true;
				}
				if (xh_option('primaryCategory', false) && in_array('category', $postTypeTasks)) {
					// 获取所有分类
					$categories = xh_postType_config($screen->post_type, 'categories');
					if ($categories) {
						$taxonomy = $categories;
						$categories = get_categories([
							'taxonomy' => $taxonomy,
							'hide_empty' => false,
							'orderby' => 'name',
							'order' => 'ASC'
						]);
						if (!empty($categories) && is_array($categories)) {
							$terms = [];
							$default_category = get_option('default_' . $taxonomy);
							if ($default_category) {
								$default_term = get_term($default_category, $taxonomy);
								$default_termid = $default_term ? $default_term->term_id : 0;
							} else {
								$default_termid = 0;
							}
							// 构建分类数组
							foreach ($categories as $category) {
								$terms[] = [
									'id' => $category->term_id,
									'name' => $category->name
								];
							}

							$primaryMeta['postterms'] = [
								'terms' => $terms,
								'default' => $default_termid
							];
						}
					}
				}

				// 话题
				if ($usetShow && xh_option('primaryThread', false) && in_array('thread', $postTypeTasks)) {
					$threadNumber = xh_option('primaryThreadNumber', 3);
					$threadTypes = xh_option('primaryThreadTypes', ['question', 'definition']);
					$threadPerspectives = xh_option('primaryThreadPerspectives', ['blogger', 'expert']);
					if ($threadNumber) {
						$primaryMeta['postthread'] = [
							'number' => $threadNumber,
							'types' => $threadTypes,
							'perspectives' => $threadPerspectives
						];
					}
				}
				if (!empty($primaryMeta) && is_array($primaryMeta)) {
					$localize['args']['post']['primary'] = $primaryMeta;
				}

				// 摘要			
				if (xh_option('summaryEnabled', false) && in_array('summary', $postTypeTasks)) {
					$localize['args']['post']['excerpt'] = [
						'length' => (int) xh_option('summaryMaxLength', 150),
						'model' => xh_option('summaryModel', 'summary')
					];
				}

				// 标签
				if (xh_option('tagEnabled', false) && in_array('tags', $postTypeTasks)) {
					$localize['args']['post']['tags'] = [
						'number' => [
							'min' => max(1, xh_option('tagMinCount', 0)),
							'max' => max(1, xh_option('tagMaxCount', 6))
						],
						'seotitle' => (int) xh_option('tagSeoTitle', false),
						'tags' => xh_get_tags($screen->post_type, null)
					];
					$expand = (bool) xh_option('tagExpandDefault', false);
					$localize['tagExpand'] = $expand;
				}

				// 评论	
				if ($usetShow && xh_option('commentEnabled', false) && in_array('comments', $postTypeTasks)) {
					$commentArgs = [
						'number' => 0,
						'loadnum' => 0,
						'day' => 0
					];
					$commentNumber = 1;
					$commentMinCount = max(1, xh_option('commentMinCount', 0));
					$commentMaxCount = max(1, xh_option('commentMaxCount', 0));
					if ($commentMaxCount > $commentMinCount) {
						$commentNumber = wp_rand($commentMinCount, $commentMaxCount);
					}
					$groupNumber = xh_option('commentGroup', 3);
					$commentArgs['allnumber'] = $commentNumber;
					if ($commentNumber > $groupNumber) {
						$commentArgs['number'] = $groupNumber;
						$commentArgs['loadnum'] = $commentNumber - $groupNumber;
					} else {
						$commentArgs['number'] = $commentNumber;
						$commentArgs['loadnum'] = 0;
					}
					$commentArgs['day'] = xh_option('commentMaxday', 1) ?: 1;

					$localize['args']['post']['comment'] = $commentArgs;
				}

				// 文生图
				if ($usetShow && xh_option('imageThumb', false) && in_array('aiimage', $postTypeTasks)) {
					$imagePromptLevel = sanitize_key((string) xh_option('imagePromptLevel', 'safe'));
					if (!in_array($imagePromptLevel, ['safe', 'aggressive'], true)) {
						$imagePromptLevel = 'safe';
					}
					$localize['args']['post']['aiimage'] = [
						'style' => xh_option('imageStyle', 'auto'),
						'size' => xh_option('imageSize', '1280x768'),
						'imagePromptLevel' => $imagePromptLevel,
					];
				}
			}
			wp_localize_script('xhtheme-ai-toolbox-blocks', 'xhthemeAiToolboxBlock', $localize);
		}
	}

	function rest_aitasks_field_saved($post, $request)
	{
		// 如果 REST 请求中包含该字段，就按正常流程保存
		if (isset($request['meta']['_xhaitool_aitasks'])) {
			return;
		}
		add_post_meta($post->ID, '_xhaitool_aitasks', 0, true);
	}

	function filter_insert_excerpt($text, $post)
	{
		if (!empty($text))
			return $text;
		$excerptShow = (int) get_post_meta($post->ID, '_excerptai', true);
		$ExcerptOption = xh_option('summaryExportFields', []);
		if ($excerptShow == 2 && in_array('postExcerpt', $ExcerptOption)) {
			$postExcerpt = get_post_meta($post->ID, '_xhai_excerpt', true);
			if (!empty($postExcerpt)) {
				return $postExcerpt;
			}
		}
		remove_filter('the_content', [$this, 'ai_postexcerpt'], 99);
		return $text;
	}

	function filter_display_excerpt($value, $post_id, $context)
	{
		if (!empty($value))
			return $value;
		$excerptShow = (int) get_post_meta($post_id, '_excerptai', true);
		$ExcerptOption = xh_option('summaryExportFields', []);
		if ($excerptShow == 2 && in_array('postExcerpt', $ExcerptOption)) {
			$postExcerpt = get_post_meta($post_id, '_xhai_excerpt', true);
			if (!empty($postExcerpt)) {
				return $postExcerpt;
			}
		}
		return $value;
	}

	function filter_excerpt($text, $post)
	{
		add_filter('the_content', [$this, 'ai_postexcerpt'], 99, 1);
		if (is_single() && is_main_query()) {
			$aiExcerpt = xh_option('summaryStyle', 'simple');
			$excerptShow = (int) get_post_meta($post->ID, '_excerptai', true);
			if ($aiExcerpt !== 'none' && $excerptShow == 1) {
				$text = '';
			}
		}
		return $text;
	}

	// 在标签编辑页面添加字段 + 标题
	public function edit_tag_form_fields($term, $taxonomy)
	{
		if (!xh_option('tagSeoTitle', false)) {
			return;
		}
		if ($taxonomy != 'post_tag') {
			$taxonomy_obj = get_taxonomy($taxonomy);
			if ($taxonomy_obj && $taxonomy_obj->hierarchical) {
				return;
			}
		}
		if (apply_filters('xhtheme_ai_toolbox_tag_title_field', false, $taxonomy))
			return;
		$tagseotitle = get_term_meta($term->term_id, '_seotitle', true);
?>
		<tr class="form-field">
			<th colspan="2">
				<h2 style="margin: 1em 0 0.5em; font-size: 16px; color: #0073aa;">
					<?php esc_html_e('XHTheme AI Toolbox', 'xhtheme-ai-toolbox'); ?>
				</h2>
			</th>
		</tr>
		<tr class="form-field">
			<th scope="row"><label
					for="xhtheme_ai_toolbox_tag_title"><?php esc_html_e('Custom Title', 'xhtheme-ai-toolbox'); ?></label>
			</th>
			<td>
				<input name="xhtheme_ai_toolbox_tag_title" id="xhtheme_ai_toolbox_tag_title" type="text"
					value="<?php echo esc_attr($tagseotitle); ?>" class="regular-text" />
				<p class="description">
					<?php esc_html_e('Used to replace the HTML title ( &lt;title&gt; ) content of the tag page.', 'xhtheme-ai-toolbox'); ?>
				</p>
			</td>
		</tr>
		<tr class="form-field">
			<th colspan="2">
				<h2 style="margin: 1em 0 0.5em; font-size: 16px; color: #0073aa;">—— END ——</h2>
			</th>
		</tr>
	<?php
	}

	public function edit_term_save($term_id)
	{
		// phpcs:ignore WordPress.Security.NonceVerification.Missing -- Nonce verified by WordPress core in term edit
		if (isset($_POST['xhtheme_ai_toolbox_tag_title'])) {
			// phpcs:ignore WordPress.Security.NonceVerification.Missing -- Nonce verified by WordPress core in term edit
			update_term_meta($term_id, '_seotitle', sanitize_text_field(wp_unslash($_POST['xhtheme_ai_toolbox_tag_title'])));
		}
	}

	public function document_title_parts($title)
	{
		if (is_tax() || is_tag()) {
			$term = get_queried_object();
			// 改成 in_array
			if (in_array($term->taxonomy, ['post_tag', 'product_tag', 'sitetag'])) {
				$custom_title = get_term_meta($term->term_id, '_seotitle', true);
				if ($custom_title) {
					if ($title['title'] == $term->name) {
						$title['title'] = $custom_title;
					}
				}
			}
		}
		return $title;
	}


	/**
	 * 添加AI摘要编辑元框
	 */
	public function add_ai_excerpt_metabox()
	{
		// 获取支持摘要的所有文章类型        
		add_meta_box(
			'xhtheme_ai_excerpt_metabox',
			__('AI Excerpt', 'xhtheme-ai-toolbox'),
			[$this, 'render_ai_excerpt_metabox'],
			xh_postTypes(),
			'side',
			'default',
			[
				'__back_compat_meta_box' => true
			]
		);
	}

	/**
	 * 渲染AI摘要编辑元框
	 */
	public function render_ai_excerpt_metabox($post)
	{
		// 获取AI自定义摘要
		$ai_excerpt = get_post_meta($post->ID, '_xhai_excerpt', true);

		// 如果没有生成AI摘要，显示提示信息
		if (empty($ai_excerpt)) {
			echo '<p class="description">';
			esc_html_e('No AI excerpt has been generated yet.', 'xhtheme-ai-toolbox');
			echo '</p>';
			return;
		}

		// 添加nonce进行安全验证
		wp_nonce_field('xhtheme_ai_excerpt_metabox', 'xhtheme_ai_excerpt_nonce');

		// 显示编辑区域
	?>
		<div class="xhtheme-ai-excerpt-wrapper">
			<textarea name="xhtheme_xhai_excerpt" id="xhtheme_xhai_excerpt" class="large-text" rows="5"
				style="width: 100%;"><?php echo esc_textarea($ai_excerpt); ?></textarea>
			<p class="description">
				<?php esc_html_e('This AI-generated excerpt will be displayed at the beginning of your post if enabled.', 'xhtheme-ai-toolbox'); ?>
			</p>
		</div>
		<style>
			.xhtheme-ai-excerpt-wrapper {
				margin-top: 10px;
			}

			.xhtheme-ai-excerpt-controls {
				margin-bottom: 10px;
			}
		</style>
<?php
	}

	/**
	 * 保存AI摘要元框数据
	 */
	public function save_ai_excerpt_metabox($post_id, $post)
	{
		// 安全检查
		if (!isset($_POST['xhtheme_ai_excerpt_nonce']) || !wp_verify_nonce(sanitize_text_field(wp_unslash($_POST['xhtheme_ai_excerpt_nonce'])), 'xhtheme_ai_excerpt_metabox')) {
			return;
		}

		// 如果是自动保存，不处理
		if (defined('DOING_AUTOSAVE') && DOING_AUTOSAVE) {
			return;
		}

		// 检查权限
		if (!current_user_can('edit_post', $post_id)) {
			return;
		}

		// 保存AI自定义摘要内容
		if (isset($_POST['xhtheme_xhai_excerpt'])) {
			$ai_excerpt = wp_kses_post(wp_unslash($_POST['xhtheme_xhai_excerpt']));
			if (empty($ai_excerpt)) {
				delete_post_meta($post_id, '_xhai_excerpt');
				delete_post_meta($post_id, '_excerptai');
			} else {
				update_post_meta($post_id, '_xhai_excerpt', trim($ai_excerpt));
			}
		}
	}

	public function cronFetchRemoteModelList()
	{
		if (!wp_cache_add('modelist', 1, 'xhaitools', HOUR_IN_SECONDS)) return;
		delete_transient('xhtheme_aitoolbox_apicheck');
		$this->fetchRemoteModelList(false);
	}

		public function init()
		{
			// AI功能
			add_action('init', [$this, 'add_postmeta']);
			add_action('enqueue_block_editor_assets', [$this, 'add_enqueue_assets']);
			add_action('rest_api_init', [$this, 'add_restinit']);
			add_action('wp_ajax_xhaitoolbox_fullpost_title_suggestions', [$this, 'ajax_fullpost_title_suggestions']);
			add_action('wp_ajax_xhaitoolbox_fullpost_image_start', [$this, 'ajax_fullpost_image_start']);
			add_action('wp_ajax_xhaitoolbox_fullpost_image_status', [$this, 'ajax_fullpost_image_status']);
			add_action('wp_ajax_xhaitoolbox_fullpost_image_finalize', [$this, 'ajax_fullpost_image_finalize']);
			add_action('wp_ajax_xhaitoolbox_fullpost_image_worker', [$this, 'ajax_fullpost_image_worker']);
			add_action('wp_ajax_nopriv_xhaitoolbox_fullpost_image_worker', [$this, 'ajax_fullpost_image_worker']);
			add_action('xhaitoolbox_fullpost_image_process_job', [$this, 'process_fullpost_image_job'], 10, 1);
			add_action('rest_after_insert_post', [$this, 'rest_aitasks_field_saved'], 10, 2);
			add_filter('the_content', [$this, 'ai_postexcerpt'], 99, 1);
		add_filter('get_the_excerpt', [$this, 'filter_insert_excerpt'], 5, 2);
		add_filter('get_the_excerpt', [$this, 'filter_excerpt'], 99, 2);
		add_filter('post_excerpt', [$this, 'filter_display_excerpt'], 10, 3);

		// AI标签
		add_action('post_tag_edit_form_fields', [$this, 'edit_tag_form_fields'], 99, 2);
		add_action('product_tag_edit_form_fields', [$this, 'edit_tag_form_fields'], 99, 2);
		add_action('sitetag_edit_form_fields', [$this, 'edit_tag_form_fields'], 99, 2);
		add_action('edit_term', [$this, 'edit_term_save']);
		add_filter('document_title_parts', [$this, 'document_title_parts'], 50, 1);

		// 添加AI摘要编辑框
		add_action('add_meta_boxes', [$this, 'add_ai_excerpt_metabox']);
		add_action('save_post', [$this, 'save_ai_excerpt_metabox'], 10, 2);

		// 添加定时任务
		add_action('xhaitoolbox_twicedaily_cron', [$this, 'cronFetchRemoteModelList']);

		/**
		 * 摘要适配
		 */
		add_filter('zib_get_excerpt', [$this, 'zib_excerpt'], 10, 2);
	}


	/**
	 * 适配类代码
	 */
	public function zib_excerpt($excerpt, $post)
	{
		if (function_exists('zib_get_post_meta')) {
			$newexcerpt = trim(zib_get_post_meta($post->ID, 'description', true));
			if (!empty($newexcerpt)) {
				return $newexcerpt;
			}
		}
		$post_id     = $post->ID;
		$excerptShow = (int)get_post_meta($post_id, '_excerptai', true);
		$ExcerptOption = xh_option('summaryExportFields', []);
		if ($excerptShow == 2 && in_array('postExcerpt', $ExcerptOption)) {
			$postExcerpt = get_post_meta($post_id, '_xhai_excerpt', true);
			if (!empty($postExcerpt)) {
				return $postExcerpt;
			}
		}
		return $excerpt;
	}
}
