<?php
if ( ! defined( 'ABSPATH' ) ) {
	exit;
}

if ( ! class_exists( 'SftcyWordaiBase' ) ) {

/**
 * Core admin class for WordAI Pro plugin.
 *
 * Handles:
 *  - Admin menu/submenus
 *  - Settings defaults (API, Content, Image)
 *  - Admin notices
 *  - License and popup rendering
 *  - Utility helpers for OpenAI integration
 *
 * @package SoftCoy\WordAI
 */
class SftcyWordaiBase {

	const DB_SCHEMA_VERSION        = '1.0.4';
	const DB_SCHEMA_VERSION_OPTION = 'sftcy_wordai_db_schema_version';

	/** @var bool */
	private static $initiated = false;
	public static $sc_wordai_support_requests_tbl = 'scwordai_support_requests';
	public static $sc_wordai_support_logs_tbl     = 'scwordai_support_logs';

	/**
	 * Constructor
	 */
	public function __construct() {
		if ( ! self::$initiated ) {
			self::initiate_hooks();
		}
	}

	/**
	 * Initialize all plugin hooks.
	 */
	private static function initiate_hooks() {
		add_action( 'admin_init', [ __CLASS__, 'maybe_update_database_schema' ], 1 );
		add_action( 'admin_init', [ __CLASS__, 'sftcy_wordai_deactivate_pro_plugin' ] );
		add_action( 'admin_init', [ __CLASS__, 'sc_wordai_check_post_type_excerpt_support' ] );
		add_action( 'admin_menu', [ __CLASS__, 'add_scwordai_submenus' ] );
		add_action( 'admin_footer', [ __CLASS__, 'sc_wordai_add_html_contents_at_admin_footer' ] );
		add_action( 'admin_notices', [ __CLASS__, 'scwordai_admin_notices' ], 5 );
		add_action( 'plugins_loaded', [ __CLASS__, 'scwordai_load_textdomain' ] );

		add_filter( 'post_row_actions', [ __CLASS__, 'sc_wordai_add_post_row_actions' ], 10, 2 );
		add_filter( 'page_row_actions', [ __CLASS__, 'sc_wordai_add_post_row_actions' ], 10, 2 );				

		self::$initiated = true;
	}

	/*──────────────────────────────────────────────
	| Activation & Checks
	──────────────────────────────────────────────*/

	/**
	 * On plugin activation.
	 */
	public static function activate() {
		self::check_preactivation_requirements();
		flush_rewrite_rules( true );

		/**
		 * ------------------------------------------------------------------
		 * Create / Update AI Agent DB Tables
		 * ------------------------------------------------------------------
		 * Called only on plugin activation.
		*/		
		SftcyWordaiOpenaiAgentInstall::create_or_update_tables();
		SftcyWordaiSupport::ensure_storage_ready();
		update_option( self::DB_SCHEMA_VERSION_OPTION, self::DB_SCHEMA_VERSION );

	}

	/**
	 * Keep custom tables current after normal plugin updates.
	 */
	public static function maybe_update_database_schema() {
		if ( ! current_user_can( 'manage_options' ) ) {
			return;
		}

		$stored_version = (string) get_option( self::DB_SCHEMA_VERSION_OPTION, '' );
		if ( version_compare( $stored_version, self::DB_SCHEMA_VERSION, '>=' ) ) {
			return;
		}

		SftcyWordaiOpenaiAgentInstall::create_or_update_tables();
		SftcyWordaiSupport::ensure_storage_ready();
		update_option( self::DB_SCHEMA_VERSION_OPTION, self::DB_SCHEMA_VERSION );
	}

	/**
	 * Ensure required PHP/WP versions and deactivate free plugin if active.
	 */
	public static function check_preactivation_requirements() {
		if ( version_compare( PHP_VERSION, SFTCY_WORDAI_MINIMUM_PHP_VERSION, '<' ) ) {
			wp_die( esc_html__( 'Minimum PHP Version required: ', 'wordai-pro' ) . SFTCY_WORDAI_MINIMUM_PHP_VERSION );
		}

		global $wp_version;
		if ( version_compare( $wp_version, SFTCY_WORDAI_MINIMUM_WP_VERSION, '<' ) ) {
			wp_die( esc_html__( 'Minimum WordPress Version required: ', 'wordai-pro' ) . SFTCY_WORDAI_MINIMUM_WP_VERSION );
		}
	}

	/**
	 * Deactivate WordAI Pro if it is active.
	 */
	public static function sftcy_wordai_deactivate_pro_plugin() {
		if ( ! function_exists( 'is_plugin_active' ) ) {
			include_once ABSPATH . 'wp-admin/includes/plugin.php';
		}
		if ( is_plugin_active( 'wordai-pro/wordai-pro.php' ) ) {
			deactivate_plugins( 'wordai/wordai.php' );
			wp_die(
				sprintf(
					'%s <a href="%s">%s</a>',
					__( 'WordAI free plugin has been deactivated because WordAI Pro is active on this site. Please keep only one WordAI variant active at a time.', 'wordai-pro' ),
					esc_url( admin_url( 'plugins.php' ) ),
					__( 'Return to Plugins page', 'wordai-pro' )
				)
			);
		}
	}



	/**
	 * Ensure that 'post' and 'page' post types support the 'excerpt' field.
	 *
	 * Some WordPress installations disable the excerpt box for pages by default.
	 * This method enables excerpt support for both posts and pages.
	 *
	 * Hook: admin_init
	 *
	 * @return void
	 */
	public static function sc_wordai_check_post_type_excerpt_support() {
		// Only allow admins
		if ( ! current_user_can( 'manage_options' ) ) {
			return;
		}

		// Enable excerpt for pages if missing
		if ( ! post_type_supports( 'page', 'excerpt' ) ) {
			add_post_type_support( 'page', 'excerpt' );
		}

		// Ensure excerpt support for posts as well
		if ( ! post_type_supports( 'post', 'excerpt' ) ) {
			add_post_type_support( 'post', 'excerpt' );
		}
	}


	/*──────────────────────────────────────────────
	| Localization
	──────────────────────────────────────────────*/

	/**
	 * Load translations.
	 */
	public static function scwordai_load_textdomain() {
		load_plugin_textdomain( 'wordai', false, dirname( plugin_basename( SFTCY_WORDAI_PLUGIN_FILE ) ) . '/languages/' );
	}

	/*──────────────────────────────────────────────
	| Admin Menus
	──────────────────────────────────────────────*/

	/**
	 * Register plugin menus and submenus.
	 */
	public static function add_scwordai_submenus() {
		$icon_image_url = plugins_url( '../admin/css/images/wordai-2026-menu-light-20x20.svg', __FILE__ );
		// Hover/current menu icon: plugins_url( '../admin/css/images/wordai-2026-menu-bright-20x20.svg', __FILE__ );
		// Dark menu icon variant: plugins_url( '../admin/css/images/wordai-2026-menu-dark-20x20.svg', __FILE__ );
		// Previous attempted new menu icon: plugins_url( '../admin/css/images/wordai-2026-icon.svg', __FILE__ );
		// Previous menu icon: plugins_url( '../admin/css/images/wordai-light-20x20.svg', __FILE__ );

		add_menu_page(
			__( 'WordAI - Auto Content Writing', 'wordai-pro' ),
			'WordAI',
			'manage_options',
			'word-ai-topmenu',
			'',
			$icon_image_url,
			6
		);

		add_submenu_page(
			'word-ai-topmenu',
			__( 'WordAI - API Settings', 'wordai-pro' ),
			__( 'API Settings', 'wordai-pro' ),
			'manage_options',
			'word-ai-topmenu',
			[ __CLASS__, 'add_scwordai_submenus_apisettings_callback' ]
		);

		add_submenu_page(
			'word-ai-topmenu',
			__( 'WordAI - Content Settings', 'wordai-pro' ),
			__( 'Content Settings', 'wordai-pro' ),
			'manage_options',
			'sc-wordai-content-settings',
			[ __CLASS__, 'add_scwordai_submenus_content_settings_callback' ]
		);

		add_submenu_page(
			'word-ai-topmenu',
			__( 'WordAI - Image Settings', 'wordai-pro' ),
			__( 'Image Settings', 'wordai-pro' ),
			'manage_options',
			'sc-wordai-image-settings',
			[ __CLASS__, 'add_scwordai_submenus_image_settings_callback' ]
		);

		add_submenu_page(
			'word-ai-topmenu',
			__( 'WordAI - SEO Scan', 'wordai-pro' ),
			__( 'SEO Scan', 'wordai-pro' ),
			'manage_options',
			'sc-wordai-seo-scan',
			[ __CLASS__, 'add_scwordai_submenus_seo_scan_callback' ]
		);

		add_submenu_page(
			'word-ai-topmenu',
			__( 'WordAI - Google Search Console', 'wordai' ),
			__( 'Search Console', 'wordai' ),
			'manage_options',
			'sc-wordai-search-console',
			[ __CLASS__, 'add_scwordai_submenus_search_console_callback' ]
		);

		add_submenu_page(
			'word-ai-topmenu',
			__( 'WordAI - AI Agent Settings', 'wordai-pro' ),
			__( 'AI Agent', 'wordai-pro' ),
			'manage_options',
			'sc-wordai-ai-agent-settings',
			[ __CLASS__, 'add_scwordai_submenus_ai_agent_settings_callback' ]
		);


		add_submenu_page(
			'word-ai-topmenu',
			__( 'WordAI - Support', 'wordai-pro' ),
			__( 'Support', 'wordai-pro' ),
			'manage_options',
			'sc-wordai-support',
			[ __CLASS__, 'add_scwordai_submenus_support_callback' ]
		);

		add_submenu_page(
			'word-ai-topmenu',
			__( 'WordAI - Get Pro', 'wordai-pro' ),
			__( 'Get Pro', 'wordai-pro' ),
			'manage_options',
			'wordai-get-pro',
			[ __CLASS__, 'add_scwordai_submenus_get_pro_callback' ]
		);
	}

	/**
	 * Include submenu pages.
	 */
	public static function add_scwordai_submenus_apisettings_callback() {
		if ( ! current_user_can( 'manage_options' ) ) {
			return;
		}
		include SFTCY_WORDAI_PLUGIN_DIR . 'admin/views/submenus-apisettings.php';
	}

	public static function add_scwordai_submenus_content_settings_callback() {
		if ( ! current_user_can( 'manage_options' ) ) {
			return;
		}
		include SFTCY_WORDAI_PLUGIN_DIR . 'admin/views/submenus-content-settings.php';
	}

	public static function add_scwordai_submenus_image_settings_callback() {
		if ( ! current_user_can( 'manage_options' ) ) {
			return;
		}
		include SFTCY_WORDAI_PLUGIN_DIR . 'admin/views/submenus-image-settings.php';
	}

	public static function add_scwordai_submenus_seo_scan_callback() {
		if ( ! current_user_can( 'manage_options' ) ) {
			return;
		}

		if ( class_exists( 'SftcyWordaiSeoScan' ) ) {
			SftcyWordaiSeoScan::render_page();
			return;
		}
	}

	public static function add_scwordai_submenus_search_console_callback() {
		if ( current_user_can( 'manage_options' ) && class_exists( 'SftcyWordaiSearchConsole' ) ) {
			SftcyWordaiSearchConsole::render_page();
		}
	}

	/**
	 * Callback: AI Agent Settings page.
	 */
	public static function add_scwordai_submenus_ai_agent_settings_callback() {
		include SFTCY_WORDAI_PLUGIN_DIR . 'admin/views/sc-wordai-ai-agent-tab-page.php';
	}

	public static function add_scwordai_submenus_support_callback() {
		if ( ! current_user_can( 'manage_options' ) ) {
			return;
		}

		$support_prefill_data = SftcyWordaiSupport::get_support_prefill_data();
		include SFTCY_WORDAI_PLUGIN_DIR . 'admin/views/support-callback-page.php';
	}


	public static function add_scwordai_submenus_get_pro_callback() {
		if ( ! current_user_can( 'manage_options' ) ) {
			return;
		}
		include SFTCY_WORDAI_PLUGIN_DIR . 'admin/views/go-pro-callback-page.php';
	}
	

	/**
	 * Content Settings Default params
	 *
	 * @return array
	 */
	public static function sc_wordai_api_content_settings_default_parameters() {
		$seo_defaults = class_exists( 'SftcyWordaiSeoStandards' )
			? SftcyWordaiSeoStandards::content_setting_defaults()
			: array(
				'sc-wordai-use-seo-content-structure' => 1,
				'sc-wordai-use-heading-structure'     => 1,
				'sc-wordai-use-seo-content-depth'     => 1,
			);

		return array_merge( [
			'sc-wordai-language-code'             => 'en-US',
			'sc-wordai-writing-style'             => 'descriptive',
			'sc-wordai-writing-tone'              => 'informative',
			'sc-wordai-title-length'              => '50n60',
			'sc-wordai-excerpt-words'             => 30,
			'sc-wordai-tags-number'               => 2,
			'wordai-suggested-title-number'       => 2,
			'sc-wordai-content-paragraphs'        => 3,
			'sc-wordai-insert-title'              => 1,
			'sc-wordai-insert-seo-title'          => 1,
			'sc-wordai-insert-seo-meta-description'=> 1,
			'sc-wordai-insert-seo-meta-focus-keyword'=> 1,
			'sc-wordai-insert-content'            => 1,
			'sc-wordai-insert-excerpt'            => 1,
			'sc-wordai-insert-tags'               => 1,

			'sc-wordai-twitter-site'              => '@yourbrand',
			'sc-wordai-twitter-creator'           => '@creatorname',
			'sc-wordai-pinterest-verification'    => '',
			'sc-wordai-enable-pinterest-richpins' => 1,
		], $seo_defaults );
	}

	public static function sc_wordai_openai_image_settings_default_parameters() {
		return [
			'sc-wordai-openai-image-model-slug'   => 'gpt-image-1.5',
			'sc-wordai-image-number'              => 2,
			'sc-wordai-dalle2-image-size'         => '1024x1024',
			'sc-wordai-dalle2-image-style'        => 'natural',
			'sc-wordai-dalle3-image-size'         => '1024x1024',
			'sc-wordai-dalle3-image-style'        => 'vivid',
			'sc-wordai-dalle3-image-hd-quality'   => 1,
			'sc-wordai-gptimage1-image-size'      => '1024x1024',
			'sc-wordai-gptimage1-image-hd-quality'=> 'auto',
			'sc-wordai-gptimage1-output-format'   => 'png',
			'sc-wordai-imagesave-togallery'       => 1,
			'sc-wordai-set-feature-image'         => 1,
		];
	}

	public static function sc_wordai_runtime_image_defaults() {
		return [
			'sc-wordai-image-number'        => 1,
			'sc-wordai-imagesave-togallery' => 0,
			'sc-wordai-set-feature-image'   => 0,
		];
	}

	public static function sc_wordai_should_verify_ssl() {
		$host = wp_parse_url( home_url(), PHP_URL_HOST );
		$host = is_string( $host ) ? strtolower( $host ) : '';

		if ( is_ssl() ) {
			return true;
		}

		return ! in_array( $host, [ 'localhost', '127.0.0.1', '::1' ], true );
	}

	public static function sc_wordai_get_default_ai_provider() {
		return 'openai';
	}

	/*──────────────────────────────────────────────
	| Get Current Settings
	──────────────────────────────────────────────*/



	/**
	 * Central registry of AI Providers (extend here later)
	 */
	public static function sc_wordai_get_ai_providers() {
		$providers = [
			'openai' => [
				'label'        => 'OpenAI',
				'capabilities' => [
					'content'    => true,
					'image'      => true,
					'chat'       => true,
					'embeddings' => true,
					'streaming'  => true,
				],
				'classes'      => [
					'content'   => 'SftcyWordaiOpenai',
					'image'     => 'SftcyWordaiOpenai',
					'embedding' => 'SftcyWordaiAgentOpenai',
				],
				'options'      => [
					'api'     => 'sftcy-wordai-openai-apisettings-data',
					'content' => 'sftcy-wordai-openai-content-settings-data',
					'image'   => 'sftcy-wordai-openai-image-settings-data',
				],
				'actions'      => [
					'api'     => [
						'save'  => 'sc_wordai_openai_apisettings_data',
						'reset' => 'sc_wordai_openai_apisettings_reset_data',
					],
					'content' => [
						'save'  => 'sc_wordai_openai_content_settings_data',
						'reset' => 'sc_wordai_openai_content_settings_reset_data',
					],
					'image'   => [
						'save'  => 'sc_wordai_openai_image_settings_data',
						'reset' => 'sc_wordai_openai_image_settings_reset_data',
					],
				],
				'api_key'      => [
					'data_key'      => 'wordai-openai-api-key-data',
					'mask_key'      => 'wordai-openai-api-key-mask',
					'mask_provider' => 'openai',
				],
				'defaults'     => [
					'api'     => [ 'class' => 'SftcyWordaiOpenai', 'method' => 'get_default_openai_settings' ],
					'content' => [ 'class' => __CLASS__, 'method' => 'sc_wordai_api_content_settings_default_parameters' ],
					'image'   => [ 'class' => __CLASS__, 'method' => 'sc_wordai_openai_image_settings_default_parameters' ],
				],
			],
			'google' => [
				'label'        => 'Google Gemini',
				'capabilities' => [
					'content'    => true,
					'image'      => true,
					'chat'       => true,
					'embeddings' => true,
					'streaming'  => false,
				],
				'classes'      => [
					'content'   => 'SftcyWordaiGoogleGeminiApi',
					'image'     => 'SftcyWordaiGoogleGeminiApi',
					'embedding' => 'SftcyWordaiAgentGemini',
				],
				'options'      => [
					'api'     => 'sftcy-wordai-google-gemini-apisettings-data',
					'content' => 'sftcy-wordai-google-gemini-content-settings-data',
					'image'   => 'sftcy-wordai-google-gemini-image-settings-data',
				],
				'actions'      => [
					'api'     => [
						'save'  => 'sc_wordai_google_gemini_apisettings_data',
						'reset' => 'sc_wordai_google_gemini_apisettings_reset_data',
					],
					'content' => [
						'save'  => 'sc_wordai_google_gemini_content_settings_data',
						'reset' => 'sc_wordai_google_gemini_content_settings_reset_data',
					],
					'image'   => [
						'save'  => 'sc_wordai_google_gemini_image_settings_data',
						'reset' => 'sc_wordai_google_gemini_image_settings_reset_data',
					],
				],
				'api_key'      => [
					'data_key'      => 'wordai-google-gemini-api-key-data',
					'mask_key'      => 'wordai-google-gemini-api-key-mask',
					'mask_provider' => 'google',
				],
				'defaults'     => [
					'api'     => [ 'class' => 'SftcyWordaiGoogleGeminiSettings', 'method' => 'get_default_gemini_settings' ],
					'content' => [ 'class' => __CLASS__, 'method' => 'sc_wordai_api_content_settings_default_parameters' ],
					'image'   => [ 'class' => 'SftcyWordaiGoogleGeminiSettings', 'method' => 'sc_wordai_google_gemini_default_image_settings' ],
				],
			],
			'anthropic' => [
				'label'        => 'Anthropic Claude',
				'capabilities' => [
					'content'    => true,
					'image'      => false,
					'chat'       => true,
					'embeddings' => true,
					'streaming'  => false,
				],
				'classes'      => [
					'content'   => 'SftcyWordaiAnthropicApi',
					'image'     => '',
					'embedding' => 'SftcyWordaiAgentAnthropic',
				],
				'options'      => [
					'api'     => 'sftcy-wordai-anthropic-apisettings-data',
					'content' => 'sftcy-wordai-anthropic-content-settings-data',
				],
				'actions'      => [
					'api'     => [
						'save'  => 'sc_wordai_anthropic_apisettings_data',
						'reset' => 'sc_wordai_anthropic_apisettings_reset_data',
					],
					'content' => [
						'save'  => 'sc_wordai_anthropic_content_settings_data',
						'reset' => 'sc_wordai_anthropic_content_settings_reset_data',
					],
				],
				'api_key'      => [
					'data_key'      => 'wordai-anthropic-api-key-data',
					'mask_key'      => 'wordai-anthropic-api-key-mask',
					'mask_provider' => 'anthropic',
				],
				'defaults'     => [
					'api'     => [ 'class' => 'SftcyWordaiAnthropicSettings', 'method' => 'get_default_anthropic_settings' ],
					'content' => [ 'class' => __CLASS__, 'method' => 'sc_wordai_api_content_settings_default_parameters' ],
					'image'   => [ 'class' => __CLASS__, 'method' => 'sc_wordai_runtime_image_defaults' ],
				],
			],
			'xai' => [
				'label'        => 'xAI Grok',
				'capabilities' => [
					'content'    => true,
					'image'      => true,
					'chat'       => true,
					'embeddings' => true,
					'streaming'  => false,
				],
				'classes'      => [
					'content'   => 'SftcyWordaiXaiApi',
					'image'     => 'SftcyWordaiXaiApi',
					'embedding' => 'SftcyWordaiAgentXai',
				],
				'options'      => [
					'api'     => 'sftcy-wordai-xai-apisettings-data',
					'content' => 'sftcy-wordai-xai-content-settings-data',
					'image'   => 'sftcy-wordai-xai-image-settings-data',
				],
				'actions'      => [
					'api'     => [
						'save'  => 'sc_wordai_xai_apisettings_data',
						'reset' => 'sc_wordai_xai_apisettings_reset_data',
					],
					'content' => [
						'save'  => 'sc_wordai_xai_content_settings_data',
						'reset' => 'sc_wordai_xai_content_settings_reset_data',
					],
					'image'   => [
						'save'  => 'sc_wordai_xai_image_settings_data',
						'reset' => 'sc_wordai_xai_image_settings_reset_data',
					],
				],
				'api_key'      => [
					'data_key'      => 'wordai-xai-api-key-data',
					'mask_key'      => 'wordai-xai-api-key-mask',
					'mask_provider' => 'xai',
				],
				'defaults'     => [
					'api'     => [ 'class' => 'SftcyWordaiXaiSettings', 'method' => 'get_default_xai_settings' ],
					'content' => [ 'class' => __CLASS__, 'method' => 'sc_wordai_api_content_settings_default_parameters' ],
					'image'   => [ 'class' => 'SftcyWordaiXaiSettings', 'method' => 'sc_wordai_xai_default_image_settings' ],
				],
			],
		];

		/**
		 * Allow addons/extensions to inject providers later
		 * add_filter('sc_wordai_ai_providers', function($providers){...});
		 */
		return apply_filters( 'sc_wordai_ai_providers', $providers );
	}

	public static function sc_wordai_render_provider_icon_set( $current_provider = '' ) {
		$current_provider = sanitize_key( (string) $current_provider );
		$icons = [
			'openai'    => self::sc_wordai_get_provider_icon_markup( 'openai' ),
			'google'    => self::sc_wordai_get_provider_icon_markup( 'google' ),
			'anthropic' => self::sc_wordai_get_provider_icon_markup( 'anthropic' ),
			'xai'       => self::sc_wordai_get_provider_icon_markup( 'xai' ),
		];
		?>
		<span class="sc-wordai-provider-current-icon" aria-hidden="true">
			<?php foreach ( $icons as $provider => $icon_markup ) : ?>
				<span class="sc-wordai-provider-current-icon__item sc-wordai-provider-current-icon__item--<?php echo esc_attr( $provider ); ?><?php echo $current_provider === $provider ? ' is-active' : ''; ?>" data-provider-icon="<?php echo esc_attr( $provider ); ?>">
					<?php echo $icon_markup; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped ?>
				</span>
			<?php endforeach; ?>
		</span>
		<?php
	}

	public static function sc_wordai_get_provider_icon_markup( $provider ) {
		$provider = sanitize_key( (string) $provider );

		if ( 'openai' === $provider ) {
			return '<img src="' . esc_url( SFTCY_WORDAI_PLUGIN_URL . 'admin/css/images/openai-logo.svg' ) . '" alt="" />';
		}

		if ( 'google' === $provider ) {
			return '<img src="' . esc_url( SFTCY_WORDAI_PLUGIN_URL . 'admin/css/images/gemini-logo.svg' ) . '" alt="" />';
		}

		if ( 'anthropic' === $provider ) {
			return '<i class="fa-solid fa-brain" aria-hidden="true"></i>';
		}

		if ( 'xai' === $provider ) {
			return '<i class="fa-solid fa-bolt" aria-hidden="true"></i>';
		}

		return '<i class="fa-solid fa-wand-magic-sparkles" aria-hidden="true"></i>';
	}

	public static function sc_wordai_get_provider_config( $provider = null ) {
		$providers = self::sc_wordai_get_ai_providers();
		$provider  = sanitize_key( (string) $provider );

		if ( $provider === '' ) {
			$provider = self::sc_wordai_get_current_ai_provider();
		}

		if ( $provider !== '' && isset( $providers[ $provider ] ) ) {
			return $providers[ $provider ];
		}

		$default_provider = self::sc_wordai_get_default_ai_provider();

		return $providers[ $default_provider ] ?? [];
	}

	public static function sc_wordai_is_valid_provider( $provider ) {
		$provider  = sanitize_key( (string) $provider );
		$providers = self::sc_wordai_get_ai_providers();
		return isset( $providers[ $provider ] );
	}

	public static function sc_wordai_get_provider_label( $provider ) {
		$provider  = sanitize_key( (string) $provider );
		$providers = self::sc_wordai_get_ai_providers();
		return $providers[ $provider ]['label'] ?? $provider;
	}

	public static function sc_wordai_provider_supports( $capability, $provider = null ) {
		$capability = sanitize_key( (string) $capability );
		$config     = self::sc_wordai_get_provider_config( $provider );

		return ! empty( $config['capabilities'][ $capability ] );
	}

	public static function sc_wordai_get_provider_class( $feature, $provider = null ) {
		$feature = sanitize_key( (string) $feature );
		$config  = self::sc_wordai_get_provider_config( $provider );

		return $config['classes'][ $feature ] ?? '';
	}

	public static function sc_wordai_get_provider_option_key( $setting_type, $provider = null ) {
		$setting_type = sanitize_key( (string) $setting_type );
		$config       = self::sc_wordai_get_provider_config( $provider );

		return $config['options'][ $setting_type ] ?? '';
	}

	public static function sc_wordai_get_provider_ajax_action( $setting_type, $provider = null, $operation = 'save' ) {
		$setting_type = sanitize_key( (string) $setting_type );
		$operation    = sanitize_key( (string) $operation );
		$config       = self::sc_wordai_get_provider_config( $provider );

		return $config['actions'][ $setting_type ][ $operation ] ?? '';
	}

	public static function sc_wordai_get_provider_api_key_field( $field, $provider = null ) {
		$field  = sanitize_key( (string) $field );
		$config = self::sc_wordai_get_provider_config( $provider );

		return $config['api_key'][ $field ] ?? '';
	}

	public static function sc_wordai_get_provider_default_settings( $setting_type, $provider = null ) {
		$setting_type = sanitize_key( (string) $setting_type );
		$config       = self::sc_wordai_get_provider_config( $provider );
		$callback     = $config['defaults'][ $setting_type ] ?? [];
		$class        = $callback['class'] ?? '';
		$method       = $callback['method'] ?? '';

		if ( $class && $method && is_callable( [ $class, $method ] ) ) {
			$defaults = call_user_func( [ $class, $method ] );
			return is_array( $defaults ) ? $defaults : [];
		}

		return [];
	}

		
	/**
	 * Render AI Provider selector (reusable in settings header, popups, metabox, etc.)
	 *
	 * ✅ Goals:
	 * - Single central HTML output for provider dropdown
	 * - Works everywhere with ONE JS handler
	 * - Keeps backward compatibility with your existing CSS/classes
	 * - Adds a stable selector class:  .sc-wordai-ai-provider-select
	 * - Adds optional context:          data-context="settings_header|suggest_title_popup|content_popup|..."
	 *
	 * @param array $args {
	 *   @type string $id          HTML id attribute. Default: 'sc-wordai-ai-provider'
	 *                             (Important: DO NOT leave empty, because label "for" should point to a real ID.)
	 *   @type string $name        HTML name attribute. Default: 'sc-wordai-ai-provider'
	 *   @type string $class       Extra CSS classes (appended). Default: 'sc-wordai-provider-select'
	 *   @type string $label       Label text. Default: __('AI Provider', 'wordai-pro')
	 *   @type bool   $show_label  Whether to show label. Default: true
	 *   @type string $context     Optional context string. Ex: 'settings_header', 'suggest_title_popup', 'content_popup'
	 * }
	 */
	public static function sc_wordai_render_provider_selector( $args = [] ) {

		$defaults = [
			'id'         => 'sc-wordai-ai-provider',                 // ✅ always has a stable default id
			'name'       => 'sc-wordai-ai-provider',                 // ✅ stable option name
			'class'      => 'sc-wordai-provider-select',             // keep your existing styling class
			'label'      => __( 'AI Provider', 'wordai-pro' ),
			'show_label' => true,
			'context'    => 'settings_header',                       // ✅ default context
		];

		$args = wp_parse_args( $args, $defaults );

		// Sanitize basic attrs
		$id      = sanitize_key( (string) $args['id'] );
		$name    = sanitize_key( (string) $args['name'] );
		$context = sanitize_key( (string) $args['context'] );

		$current_provider = self::sc_wordai_get_current_ai_provider();
		$providers        = self::sc_wordai_get_ai_providers();
		$current_label    = isset( $providers[ $current_provider ]['label'] ) ? $providers[ $current_provider ]['label'] : __( 'OpenAI', 'wordai-pro' );
		$menu_id          = $id . '-provider-menu';

		// Build class list safely (append stable JS hook class ALWAYS)
		// ✅ JS should bind to `.sc-wordai-ai-provider-select` everywhere
		$base_classes  = trim( (string) $args['class'] );
		$final_classes = trim( $base_classes . ' sc-wordai-ai-provider-select sc-wordai-provider-native-select' );

		// If id is somehow empty after sanitize, fallback to safe id
		if ( $id === '' ) {
			$id = 'sc-wordai-ai-provider';
		}

		?>
		<div class="sc-wordai-provider-picker">
			<?php if ( ! empty( $args['show_label'] ) ) : ?>
				<label class="sc-wordai-provider-label" for="<?php echo esc_attr( $id ); ?>">
					<i class="dashicons dashicons-share-alt"></i>
					<?php echo esc_html( $args['label'] ); ?>
				</label>
			<?php endif; ?>

			<div class="sc-wordai-select-wrapper" data-active-provider="<?php echo esc_attr( $current_provider ); ?>">
				<?php self::sc_wordai_render_provider_icon_set( $current_provider ); ?>
				<select
					id="<?php echo esc_attr( $id ); ?>"
					name="<?php echo esc_attr( $name ); ?>"
					class="<?php echo esc_attr( $final_classes ); ?>"
					aria-label="<?php echo esc_attr( $args['label'] ); ?>"
					data-provider="<?php echo esc_attr( $current_provider ); ?>"
					data-context="<?php echo esc_attr( $context ); ?>"
				>
					<?php foreach ( (array) $providers as $slug => $meta ) : ?>
						<?php
						$slug  = sanitize_key( (string) $slug );
						$label = $meta['label'] ?? $slug;
						?>
						<option value="<?php echo esc_attr( $slug ); ?>" <?php selected( $current_provider, $slug ); ?>>
							<?php echo esc_html( $label ); ?>
						</option>
					<?php endforeach; ?>
				</select>
				<button
					type="button"
					class="sc-wordai-provider-combobox"
					aria-haspopup="listbox"
					aria-expanded="false"
					aria-controls="<?php echo esc_attr( $menu_id ); ?>"
				>
					<span class="sc-wordai-provider-combobox-icon" aria-hidden="true"><?php echo self::sc_wordai_get_provider_icon_markup( $current_provider ); // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped ?></span>
					<span class="sc-wordai-provider-combobox-label"><?php echo esc_html( $current_label ); ?></span>
					<span class="sc-wordai-provider-combobox-caret" aria-hidden="true"></span>
				</button>
				<div class="sc-wordai-provider-options" id="<?php echo esc_attr( $menu_id ); ?>" role="listbox" aria-label="<?php echo esc_attr( $args['label'] ); ?>">
					<?php foreach ( (array) $providers as $slug => $meta ) : ?>
						<?php
						$slug  = sanitize_key( (string) $slug );
						$label = $meta['label'] ?? $slug;
						?>
						<button
							type="button"
							class="sc-wordai-provider-option<?php echo $current_provider === $slug ? ' is-active' : ''; ?>"
							role="option"
							aria-selected="<?php echo $current_provider === $slug ? 'true' : 'false'; ?>"
							data-provider-value="<?php echo esc_attr( $slug ); ?>"
						>
							<span class="sc-wordai-provider-option-icon" aria-hidden="true"><?php echo self::sc_wordai_get_provider_icon_markup( $slug ); // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped ?></span>
							<span class="sc-wordai-provider-option-label"><?php echo esc_html( $label ); ?></span>
						</button>
					<?php endforeach; ?>
				</div>
			</div>
		</div>
		<?php
	}


	/**
	 * ============================================================================
	 * Get Current AI Provider
	 * ----------------------------------------------------------------------------
	 * - Stored in option: sc-wordai-ai-provider
	 * - Default: openai
	 * ============================================================================
	 */
	public static function sc_wordai_get_current_ai_provider() {
		$default_provider = self::sc_wordai_get_default_ai_provider();
		$provider         = sanitize_key( (string) get_option( 'sc-wordai-ai-provider', $default_provider ) );

		// Safety: if something weird stored, fall back to openai
		if ( ! self::sc_wordai_is_valid_provider( $provider ) ) {
			$provider = $default_provider;
		}

		return $provider;
	}

	/**
	 * ============================================================================
	 * API Key Mask Formatter (Provider-Aware)
	 * ----------------------------------------------------------------------------
	 * - Masks real key for display in inputs
	 * - Shows example pattern when key is empty
	 * ============================================================================
	 *
	 * @param string $api_key  Raw API key from DB.
	 * @param string $provider 'openai' | 'google' | others later.
	 * @return string          Masked version or provider-specific placeholder.
	 */
	public static function wordai_api_key_mask_format( $api_key = '', $provider = 'openai' ) {

		// 1️⃣ Provider-specific placeholder patterns
		if ( empty( $api_key ) ) {
			switch ( $provider ) {
				case 'google':
					// Typical Gemini API key starts with AI... but we just hint shape
					return 'AIxx-xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx';
				case 'anthropic':
					return 'sk-ant-xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx';
				case 'xai':
					return 'xai-xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx';
				case 'openai':
				default:
					return 'sk-xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx';
			}
		}

		// 2️⃣ Generic mask for non-empty keys
		$len = strlen( $api_key );
		if ( $len <= 8 ) {
			// Very short / unexpected key: keep first 2, last 2, mask middle.
			if ( $len <= 4 ) {
				return str_repeat( 'x', $len );
			}
			$start = substr( $api_key, 0, 2 );
			$end   = substr( $api_key, -2 );
			$mid   = str_repeat( 'x', max( 0, $len - 4 ) );
			return $start . $mid . $end;
		}

		// Normal keys: keep first 4 + last 4, mask middle.
		$start = substr( $api_key, 0, 4 );
		$end   = substr( $api_key, -4 );
		$mid   = str_repeat( 'x', max( 0, $len - 8 ) );

		return $start . $mid . $end;
	}

	/**
	 * ============================================================================
	 * Get ALL API Settings (Provider-Aware)
	 * ----------------------------------------------------------------------------
	 * - Detects current AI provider (openai/google)
	 * - Loads correct saved settings:
	 *      • sftcy-wordai-openai-apisettings-data
	 *      • sftcy-wordai-google-gemini-apisettings-data
	 * - Merges with default settings for each provider
	 * - Returns a unified $data array used everywhere in the plugin
	 * ============================================================================
	 */
	public static function sc_wordai_get_current_api_settings() {

		// 1. Detect provider (default = openai)
		$provider = self::sc_wordai_get_current_ai_provider();
		$option_key = self::sc_wordai_get_provider_option_key( 'api', $provider );
		$saved      = $option_key ? get_option( $option_key ) : [];
		$saved      = $saved ? maybe_unserialize( $saved ) : array();
		$defaults   = self::sc_wordai_get_provider_default_settings( 'api', $provider );

		if ( ! is_array( $saved ) ) {
			$saved = array();
		}

		$api_key_field      = self::sc_wordai_get_provider_api_key_field( 'data_key', $provider );
		$api_mask_field     = self::sc_wordai_get_provider_api_key_field( 'mask_key', $provider );
		$mask_format_source = self::sc_wordai_get_provider_api_key_field( 'mask_provider', $provider );

		if ( $api_mask_field ) {
			$api_key = $api_key_field && isset( $saved[ $api_key_field ] ) ? $saved[ $api_key_field ] : '';
			$saved[ $api_mask_field ] = self::wordai_api_key_mask_format( $api_key, $mask_format_source ?: $provider );
		}

		// 3. Merge defaults + saved settings
		$merged = array_merge( $defaults, $saved );

		// 4. Also merge provider selection (needed everywhere)
		$merged['sc-wordai-ai-provider'] = $provider;

		if ( 'google' === $provider && class_exists( 'SftcyWordaiGoogleGeminiSettings' ) && method_exists( 'SftcyWordaiGoogleGeminiSettings', 'normalize_gemini_model_slug' ) ) {
			$merged['sc-wordai-gemini-model-slug'] = SftcyWordaiGoogleGeminiSettings::normalize_gemini_model_slug(
				$merged['sc-wordai-gemini-model-slug'] ?? ''
			);
		}

		if ( 'xai' === $provider && class_exists( 'SftcyWordaiXaiSettings' ) ) {
			$merged['sc-wordai-xai-model-slug'] = SftcyWordaiXaiSettings::normalize_xai_model_slug(
				$merged['sc-wordai-xai-model-slug'] ?? ''
			);
		}

		return $merged;
	}



	// public static function sc_wordai_get_current_content_settings() {
	// 	$default = self::sc_wordai_api_content_settings_default_parameters();
	// 	$options = maybe_unserialize( get_option( 'sftcy-wordai-openai-content-settings-data' ) );
	// 	$options = is_array( $options ) ? $options : [];

	// 	foreach ( $default as $k => $v ) {
	// 		$options[ $k ] = isset( $options[ $k ] ) ? sanitize_text_field( $options[ $k ] ) : $v;
	// 	}
	// 	return $options;
	// }

	/**
	 * ==============================================================================
	 *  Get ALL Content Settings (Provider-Aware)
	 * ------------------------------------------------------------------------------
	 *  - Detects current AI provider (openai / google)
	 *  - Loads correct saved settings:
	 *        • sftcy-wordai-openai-content-settings-data                (OpenAI)
	 *        • sftcy-wordai-google-gemini-content-settings-data  (Gemini)
	 *  - Merges with default content settings
	 *  - Returns unified $data array for UI + internal use
	 * ==============================================================================
	 */
	public static function sc_wordai_get_current_content_settings() {

		// 1️⃣ Detect active provider (default = openai)
		$provider = self::sc_wordai_get_current_ai_provider();
		$option_key = self::sc_wordai_get_provider_option_key( 'content', $provider );
		$saved      = $option_key ? get_option( $option_key ) : [];
		$saved      = $saved ? maybe_unserialize( $saved ) : [];

		if (!is_array($saved)) {
			$saved = [];
		}

		// 3️⃣ Load default parameters (same for OpenAI + Gemini unless provider overrides later)
		$defaults = self::sc_wordai_get_provider_default_settings( 'content', $provider );

		// 4️⃣ Merge defaults + saved settings
		$merged = array_merge($defaults, $saved);

		if ( class_exists( 'SftcyWordaiSeoStandards' ) ) {
			$merged = SftcyWordaiSeoStandards::sanitize_content_settings( $merged );
		}

		if ( class_exists( 'SftcyWordaiOpenai' ) ) {
			$title_lengths = SftcyWordaiOpenai::title_lengths();
			if ( empty( $merged['sc-wordai-title-length'] ) || ! isset( $title_lengths[ (string) $merged['sc-wordai-title-length'] ] ) ) {
				$merged['sc-wordai-title-length'] = '50n60';
			}

			$paragraphs = SftcyWordaiOpenai::content_paragraphs();
			if ( empty( $merged['sc-wordai-content-paragraphs'] ) || ! isset( $paragraphs[ (string) $merged['sc-wordai-content-paragraphs'] ] ) ) {
				$merged['sc-wordai-content-paragraphs'] = '3';
			}

			$excerpt_words = SftcyWordaiOpenai::excerpt_words();
			if ( empty( $merged['sc-wordai-excerpt-words'] ) || ! isset( $excerpt_words[ (string) $merged['sc-wordai-excerpt-words'] ] ) ) {
				$merged['sc-wordai-excerpt-words'] = 30;
			}
		}

		if ( class_exists( 'SftcyWordaiFeatures' ) ) {
			$merged = SftcyWordaiFeatures::wordai_apply_content_setting_limits( $merged );
		}

		// 5️⃣ Add provider info (UI logic)
		$merged['sc-wordai-ai-provider'] = $provider;

		return $merged;
	}


	// public static function sc_wordai_get_current_image_settings() {
	// 	$default = self::sc_wordai_openai_image_settings_default_parameters();
	// 	$options = maybe_unserialize( get_option( 'sftcy-wordai-openai-image-settings-data' ) );
	// 	$options = is_array( $options ) ? $options : [];

	// 	foreach ( $default as $k => $v ) {
	// 		if ( ! isset( $options[ $k ] ) ) {
	// 			$options[ $k ] = $v;
	// 		}
	// 	}
	// 	return $options;
	// }


	/**
	 * ============================================================
	 *  Get Current Image Settings (Provider-Aware)
	 *  ------------------------------------------------------------
	 *  - Detects active provider: openai / google / (future)
	 *  - Loads correct saved settings option
	 *  - Falls back to correct default parameters
	 *  - Ensures all keys exist
	 * ============================================================
	 */
	public static function sc_wordai_get_current_image_settings() {

		// 1️⃣ Detect active provider
		$provider = self::sc_wordai_get_current_ai_provider(); // openai | google | future
		$default  = self::sc_wordai_get_provider_default_settings( 'image', $provider );
		$option_key = self::sc_wordai_get_provider_option_key( 'image', $provider );
		$options    = $option_key ? maybe_unserialize( get_option( $option_key ) ) : [];

		// 3️⃣ Guarantee we have an array
		$options = is_array($options) ? $options : [];

		// 4️⃣ Ensure all missing keys get default values
		foreach ($default as $k => $v) {
			if (!isset($options[$k])) {
				$options[$k] = $v;
			}
		}

		if ( class_exists( 'SftcyWordaiFeatures' ) ) {
			$options = SftcyWordaiFeatures::wordai_apply_image_setting_limits( $options );
		}

		$allowed_openai_models = array( 'gpt-image-2', 'gpt-image-1.5', 'gpt-image-1', 'gpt-image-1-mini' );
		$openai_model          = isset( $options['sc-wordai-openai-image-model-slug'] ) ? sanitize_text_field( (string) $options['sc-wordai-openai-image-model-slug'] ) : '';

		if ( ! in_array( $openai_model, $allowed_openai_models, true ) ) {
			$options['sc-wordai-openai-image-model-slug'] = 'gpt-image-1.5';
		}

		$allowed_openai_formats = array( 'png', 'jpeg', 'webp' );
		$openai_format          = isset( $options['sc-wordai-gptimage1-output-format'] ) ? sanitize_key( (string) $options['sc-wordai-gptimage1-output-format'] ) : '';
		if ( ! in_array( $openai_format, $allowed_openai_formats, true ) ) {
			$options['sc-wordai-gptimage1-output-format'] = 'png';
		}

		if ( class_exists( 'SftcyWordaiGoogleGeminiSettings' ) && method_exists( 'SftcyWordaiGoogleGeminiSettings', 'normalize_gemini_image_model_slug' ) ) {
			$options['sc-wordai-gemini-image-model-slug'] = SftcyWordaiGoogleGeminiSettings::normalize_gemini_image_model_slug(
				$options['sc-wordai-gemini-image-model-slug'] ?? ''
			);
			if ( method_exists( 'SftcyWordaiGoogleGeminiSettings', 'normalize_gemini_image_mime_type' ) ) {
				$options['sc-wordai-gemini-image-mime'] = SftcyWordaiGoogleGeminiSettings::normalize_gemini_image_mime_type(
					$options['sc-wordai-gemini-image-mime'] ?? '',
					$options['sc-wordai-gemini-image-model-slug']
				);
			}
		}

		if ( class_exists( 'SftcyWordaiXaiSettings' ) ) {
			$options['sc-wordai-xai-image-model-slug'] = SftcyWordaiXaiSettings::normalize_xai_image_model_slug(
				$options['sc-wordai-xai-image-model-slug'] ?? ''
			);
			$options['sc-wordai-xai-image-aspect-ratio'] = SftcyWordaiXaiSettings::normalize_xai_image_aspect_ratio(
				$options['sc-wordai-xai-image-aspect-ratio'] ?? ''
			);
			$options['sc-wordai-xai-image-resolution'] = SftcyWordaiXaiSettings::normalize_xai_image_resolution(
				$options['sc-wordai-xai-image-resolution'] ?? ''
			);
		}

		// 5️⃣ Return fully normalized provider-aware settings
		return $options;
	}


	/**
	 * WordAI API License Key Mask Format
	 * @return - string - License Key Mask
	 */
	public static function license_key_mask_format( $license_key = '' ) {
		// Default - Placeholder display
		$license_key_mask = 'xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx';
		if ( ! empty( $license_key ) ) {
			$license_key_mask = str_split( $license_key, 2 );	
			array_walk( $license_key_mask, function( &$val, $index ) { $val = ( $index % 2 !== 0 )? str_repeat( '*', strlen( $val )) : $val; } );		
			$license_key_mask = implode('', $license_key_mask );		
		}
		return $license_key_mask;
	}


	/*──────────────────────────────────────────────
	| Utilities
	──────────────────────────────────────────────*/

	public static function wordai_check_output_buffering_status() {
		return ob_get_level() > 0;
	}

	public static function wordai_openai_api_key_mask_format( $api_key = '' ) {
		if ( empty( $api_key ) ) {
			return 'sk-xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx';
		}
		$parts = str_split( $api_key, 3 );
		array_walk( $parts, function ( &$v, $i ) {
			if ( $i % 2 !== 0 ) {
				$v = str_repeat( '*', strlen( $v ) );
			}
		} );
		return implode( '', $parts );
	}

	/**
	 * Get the correct Agent Embedding class name based on provider.
	 *
	 * @return string|null  Class name or null if not found.
	 */
	public static function sc_wordai_get_embedding_agent_class() {
		$provider = self::sc_wordai_get_current_ai_provider(); // 'openai' | 'google' | ...
		$class    = self::sc_wordai_get_provider_class( 'embedding', $provider );

		return ( $class && class_exists( $class ) ) ? $class : null;
	}


	/**
	 * ============================================================================
	 * Remove Markdown formatting safely while preserving paragraphs and newlines.
	 * 
	 * @param string $text Input text (AI response)
	 * @return string Cleaned plain text
	 * ============================================================================
	 */
	public static function sc_wordai_strip_markdown( $text ) {

		if ( empty( $text ) ) {
			return '';
		}

		$text = str_replace( array( "\r\n", "\r" ), "\n", (string) $text );

		// ----------------------------------------------
		// 1. Remove fenced code blocks: ``` ... ```
		// ----------------------------------------------
		$text = preg_replace( '/```[\s\S]*?```/', '', $text );

		// ----------------------------------------------
		// 2. Remove markdown headings (#, ##, ###)
		// ----------------------------------------------
		$text = preg_replace( '/^#{1,6}\s*/m', '', $text );

		// ----------------------------------------------
		// 3. Remove bold + italic ( **text**, *text*, __text__, _text_ )
		// ----------------------------------------------
		$text = preg_replace( '/(\*\*|__)([\s\S]*?)\1/', '$2', $text ); // bold
		$text = preg_replace( '/(^|[^\w])(\*|_)([^\n*_]+?)\2(?=[^\w]|$)/m', '$1$3', $text ); // italic

		// ----------------------------------------------
		// 4. Remove inline code `code`
		// ----------------------------------------------
		$text = preg_replace( '/`([^`]+)`/', '$1', $text );

		// ----------------------------------------------
		// 5. Convert markdown links [text](url) → text
		// ----------------------------------------------
		$text = preg_replace( '/\[(.*?)\]\((.*?)\)/', '$1', $text );

		// ----------------------------------------------
		// 6. Remove blockquotes "> "
		// ----------------------------------------------
		$text = preg_replace( '/^\s*>\s*/m', '', $text );

		// ----------------------------------------------
		// 7. Remove list markers (-, *, +, bullets)
		// ----------------------------------------------
		$text = preg_replace( '/^\s*(?:[-\*\+]|&bull;|&#8226;|&#x2022;|[•●○◦·])\s+/mu', '', $text );
		$text = preg_replace( '/^\s*(?:&bull;|&#8226;|&#x2022;|[•●○◦·])\s*$/mu', '', $text );

		// ----------------------------------------------
		// 8. Collapse too many blank lines
		// ----------------------------------------------
		$text = preg_replace( '/[ \t]+\n/', "\n", $text );
		$text = preg_replace( "/\n{3,}/", "\n\n", $text );

		// ----------------------------------------------
		// 9. Trim final result
		// ----------------------------------------------
		return trim( $text );
	}

	public static function sc_wordai_normalize_generated_content_html( $content ) {
		if ( empty( $content ) ) {
			return '';
		}

		$content = str_replace( array( "\r\n", "\r" ), "\n", (string) $content );
		$content = preg_replace( '/```(?:html)?\s*/i', '', $content );
		$content = str_replace( '```', '', $content );
		$content = preg_replace( '/<\s*script\b[^>]*>[\s\S]*?<\s*\/\s*script\s*>/i', '', $content );
		$content = preg_replace( '/<\s*style\b[^>]*>[\s\S]*?<\s*\/\s*style\s*>/i', '', $content );
		$content = preg_replace( '/<p(?!\s|>|\/|icture\b|re\b|aram\b|ath\b|olygon\b|olyline\b|rogress\b)([a-z])/i', '<p>$1', $content );
		$content = preg_replace( '/<\/p(?!\s|>)([a-z][a-z0-9-]*)>/i', '</p>$1', $content );
		$content = preg_replace( '/<li(?!\s|>|\/|nk\b)([a-z])/i', '<li>$1', $content );
		$content = preg_replace( '/<\/li(?!\s|>)([a-z][a-z0-9-]*)>/i', '</li>$1', $content );
		$content = preg_replace( '/<(p|div|span)[^>]*>\s*(?:&nbsp;|\x{00a0}|<br\s*\/?>|\s|&bull;|&#8226;|&#x2022;|[•●○◦·\-\*\+])*\s*<\/\1>/iu', '', $content );
		$content = preg_replace_callback(
			'/<li\b[^>]*>([\s\S]*?)<\/li>/i',
			function ( $matches ) {
				$inner = trim( $matches[1] );
				$plain = trim( html_entity_decode( wp_strip_all_tags( $inner ), ENT_QUOTES, get_bloginfo( 'charset' ) ) );
				if ( '' === $plain || preg_match( '/^(?:\s|&nbsp;|\x{00a0}|&bull;|&#8226;|&#x2022;|[•●○◦·\-\*\+])+$/iu', $plain ) ) {
					return "\n";
				}
				return "\n<p>" . $inner . "</p>\n";
			},
			$content
		);
		$content = preg_replace( '/<\/?(?:ul|ol)\b[^>]*>/i', "\n", $content );

		$content = preg_replace_callback(
			'/<h([1-6])([^>\s\/][^<>]*?)<\/h\1>/i',
			function ( $matches ) {
				$heading_text = trim( wp_strip_all_tags( $matches[2] ) );
				return '<h' . $matches[1] . '>' . esc_html( $heading_text ) . '</h' . $matches[1] . '>';
			},
			$content
		);

		$content = preg_replace_callback(
			'/<h([1-6])([a-z][a-z0-9-]*)(\s[^>]*)?>\s*(?:<br\s*\/?>\s*)*/i',
			function ( $matches ) {
				$words = array( $matches[2] );
				$attrs = isset( $matches[3] ) ? $matches[3] : '';

				if ( preg_match_all( '/\s+([a-z][a-z0-9-]*)(?:<)?\s*=/i', $attrs, $attr_matches ) ) {
					foreach ( $attr_matches[1] as $word ) {
						if ( ! preg_match( '/^h[1-6]$/i', $word ) ) {
							$words[] = $word;
						}
					}
				}

				$heading_text = ucwords( strtolower( trim( implode( ' ', $words ) ) ) );
				$heading_text = preg_replace( '/\bAi\b/', 'AI', $heading_text );

				return '<h' . $matches[1] . '>' . esc_html( $heading_text ) . '</h' . $matches[1] . ">\n";
			},
			$content
		);

		$content = preg_replace( '/<\/h[1-6][a-z0-9_-]+>/i', '', $content );
		$content = preg_replace( '/<\/h([1-6])>\s*(?:<br\s*\/?>\s*)+/i', "</h$1>\n", $content );
		$content = preg_replace( '/>\s*</', ">\n<", $content );
		$content = preg_replace( '/^\s*(?:&bull;|&#8226;|&#x2022;|[•●○◦·])\s*$/mu', '', $content );
		$content = preg_replace( "/\n{3,}/", "\n\n", $content );

		return trim( wp_kses_post( $content ) );
	}



	/**
	 * Render suggest-title popup HTML in footer.
	 */
	public static function sc_wordai_add_html_contents_at_admin_footer() {
		if ( ! current_user_can( 'manage_options' ) ) {
			return;
		}
		global $pagenow;
		if ( $pagenow === 'edit.php' ) {
			include SFTCY_WORDAI_PLUGIN_DIR . 'admin/views/suggest-titles-popup.php';
		}
	}

	/**
	 * Add "WordAI Title" row action.
	 */
	public static function sc_wordai_add_post_row_actions( $actions, $post ) {
		$supported = [ 'post', 'page', 'product' ];
		if ( in_array( $post->post_type, $supported, true ) ) {
			$new = [
				sprintf(
					'<a href="javascript:void(0)" class="sc-wordai-suggest-titles" data-scwordai-post-id="%d"><span class="sc-wordai-suggest-titles-row-icon"></span><span class="sc-wordai-suggest-titles-row-label">%s</span></a>',
					$post->ID,
					__( 'WordAI Title', 'wordai-pro' )
				),
			];
			return array_merge( $actions, $new );
		}
		return $actions;
	}

	/**
	 * Safe clickable link builder.
	 */
	public static function make_links_clickable( $input ) {
		if ( empty( $input ) || ! is_string( $input ) ) {
			return '';
		}
		$parts = explode( '|', $input, 2 );
		$url   = trim( $parts[0] );
		$text  = isset( $parts[1] ) && trim( $parts[1] ) !== '' ? trim( $parts[1] ) : $url;
		if ( ! filter_var( $url, FILTER_VALIDATE_URL ) ) {
			return esc_html( $input );
		}
		return wp_kses(
			sprintf( '<a href="%s" target="_blank" rel="noopener noreferrer">%s</a>', esc_url( $url ), esc_html( $text ) ),
			[ 'a' => [ 'href' => [], 'target' => [], 'rel' => [] ] ]
		);
	}

	/*──────────────────────────────────────────────
	| Notices
	──────────────────────────────────────────────*/

	/**
	 * ============================================================================
	 * Admin Notice → API Key Missing (OpenAI / Google Gemini)
	 * ----------------------------------------------------------------------------
	 * Shows a clean, modern notice with WordAI branding.
	 * Works for ANY provider based on saved "sc-wordai-ai-provider".
	 * ============================================================================
	 */
	public static function scwordai_admin_notices() {

		// Allowed pages to show this notice
		$allowed_pages = [
			'toplevel_page_word-ai-topmenu',
			'wordai_page_sc-wordai-content-settings',
			'wordai_page_sc-wordai-image-settings',
			'wordai_page_sc-wordai-seo-scan',
			'wordai_page_sc-wordai-search-console',
			'wordai_page_sc-wordai-ai-agent-settings',
			'wordai_page_sc-wordai-support',
			'wordai_page_wordai-get-pro',
		];

		$screen = get_current_screen();
		if ( ! $screen || ! in_array( $screen->id, $allowed_pages, true ) ) {
			return; // Do NOT show notice on other WP admin pages
		}

		// Load settings
		$settings  = self::sc_wordai_get_current_api_settings();
		$provider  = isset( $settings['sc-wordai-ai-provider'] ) ? $settings['sc-wordai-ai-provider'] : 'openai';
		$provider_label = self::sc_wordai_get_provider_label( $provider );
		$api_key_field  = self::sc_wordai_get_provider_api_key_field( 'data_key', $provider );

		// Provider-specific key check
		$missing_key = empty( $api_key_field ) || empty( $settings[ $api_key_field ] );
		$provider_setup_url = admin_url( 'admin.php?page=word-ai-topmenu' );

		if ( ! $missing_key ) {
			return; 
		}

		$logo_url       = esc_url( SFTCY_WORDAI_PLUGIN_URL . 'admin/css/images/wordai-2026-icon.svg' );
		$provider_label = esc_html( $provider_label );

		echo '
		<div class="sc-wordai-api-key-missing-notice sc-wordai-notice-warning">
			<div class="sc-wordai-api-key-missing-icon" aria-hidden="true">
				<img class="sc-wordai-api-key-notice-logo" src="' . $logo_url . '" alt="" />
			</div>
			<div class="sc-wordai-api-key-missing-content">
				<span class="sc-wordai-api-key-missing-eyebrow">' . esc_html__( 'Provider setup required', 'wordai' ) . '</span>
				<strong class="sc-wordai-api-key-missing-title">
					<i class="fa-solid fa-key sc-wordai-inline-icon" aria-hidden="true"></i>
					' . esc_html__( 'WordAI – API Key Required', 'wordai' ) . '
				</strong>
				<p class="sc-wordai-api-key-missing-message">
					' . sprintf(
						/* translators: %s: AI provider name. */
						esc_html__( 'A valid %s API key is required before WordAI can generate content, images, titles, or AI Agent responses with the selected provider.', 'wordai' ),
						'<strong>' . $provider_label . '</strong>'
					) . '
				</p>
			</div>
			<a class="sc-wordai-api-key-missing-action" href="' . esc_url( $provider_setup_url ) . '">
				' . esc_html__( 'Add API Key', 'wordai' ) . '
			</a>
		</div>';
	}





}

}
