<?php
/**
 * Admin page class.
 *
 * @package Pendid_AI_Studio
 */

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

/**
 * Handles the plugin admin page.
 */
class Pendid_AI_Studio_Admin {

	/**
	 * Admin page hook suffixes.
	 *
	 * @var array<int, string>
	 */
	private $page_hooks = array();

	/**
	 * Connection URL cached for the current admin-page request.
	 *
	 * @var string
	 */
	private $connect_url = '';

	/**
	 * Settings helper.
	 *
	 * @var Pendid_AI_Studio_Settings
	 */
	private $settings;

	/**
	 * API client.
	 *
	 * @var Pendid_AI_Studio_API_Client
	 */
	private $api_client;

	/**
	 * Sets dependencies.
	 *
	 * @param Pendid_AI_Studio_Settings   $settings   Settings helper.
	 * @param Pendid_AI_Studio_API_Client $api_client API client.
	 */
	public function __construct( Pendid_AI_Studio_Settings $settings, Pendid_AI_Studio_API_Client $api_client ) {
		$this->settings   = $settings;
		$this->api_client = $api_client;
	}

	/**
	 * Registers admin hooks.
	 *
	 * @return void
	 */
	public function run() {
		add_action( 'admin_init', array( $this, 'maybe_handle_connection_callback' ) );
		add_action( 'admin_menu', array( $this, 'register_menu_page' ) );
		add_action( 'admin_enqueue_scripts', array( $this, 'enqueue_assets' ) );
		add_action( 'admin_notices', array( $this, 'render_admin_notices' ) );
		add_action( 'admin_post_pendid_ai_studio_refresh_account', array( $this, 'handle_refresh_account' ) );
		add_action( 'admin_post_pendid_ai_studio_disconnect', array( $this, 'handle_disconnect' ) );
		add_action( 'admin_post_pendid_ai_studio_generate_image', array( $this, 'handle_generate_image' ) );
		add_action( 'admin_post_pendid_ai_studio_new_image', array( $this, 'handle_new_image' ) );
	}

	/**
	 * Registers the plugin menu and its pages.
	 *
	 * @return void
	 */
	public function register_menu_page() {
		$capability = 'manage_options';
		$menu_slug  = 'pendid-ai-studio';

		$this->page_hooks[] = add_menu_page(
			__( 'Pendid AI Studio', 'pendid-ai-studio' ),
			__( 'Pendid', 'pendid-ai-studio' ),
			$capability,
			$menu_slug,
			array( $this, 'render_dashboard_page' ),
			'dashicons-format-image',
			65
		);

		$this->page_hooks[] = add_submenu_page(
			$menu_slug,
			__( 'Pendid AI Studio Dashboard', 'pendid-ai-studio' ),
			__( 'Dashboard', 'pendid-ai-studio' ),
			$capability,
			$menu_slug,
			array( $this, 'render_dashboard_page' )
		);

		$this->page_hooks[] = add_submenu_page(
			$menu_slug,
			__( 'Create Image', 'pendid-ai-studio' ),
			__( 'Create Image', 'pendid-ai-studio' ),
			$capability,
			'pendid-ai-studio-create-image',
			array( $this, 'render_create_image_page' )
		);

		$this->page_hooks[] = add_submenu_page(
			$menu_slug,
			__( 'Pendid AI Studio Settings', 'pendid-ai-studio' ),
			__( 'Settings', 'pendid-ai-studio' ),
			$capability,
			'pendid-ai-studio-settings',
			array( $this, 'render_settings_page' )
		);

		$this->page_hooks = array_values( array_filter( $this->page_hooks, 'is_string' ) );
	}

	/**
	 * Enqueues assets only for Pendid AI Studio pages.
	 *
	 * @param string $hook_suffix Current admin page hook suffix.
	 * @return void
	 */
	public function enqueue_assets( $hook_suffix ) {
		if ( ! in_array( $hook_suffix, $this->page_hooks, true ) ) {
			return;
		}

		wp_enqueue_style(
			'pendid-ai-studio-admin',
			PENDID_AI_STUDIO_URL . 'assets/admin.css',
			array(),
			PENDID_AI_STUDIO_VERSION
		);

		wp_enqueue_script(
			'pendid-ai-studio-admin',
			PENDID_AI_STUDIO_URL . 'assets/admin.js',
			array(),
			PENDID_AI_STUDIO_VERSION,
			true
		);
	}

	/**
	 * Renders admin notices for plugin actions.
	 *
	 * @return void
	 */
	public function render_admin_notices() {
		if ( ! $this->is_plugin_admin_page() ) {
			return;
		}

		$message = sanitize_key( $this->get_scalar_input( INPUT_GET, 'pendid_message' ) );
		$error   = sanitize_key( $this->get_scalar_input( INPUT_GET, 'pendid_error' ) );

		if ( 'account_refreshed' === $message ) {
			?>
			<div class="notice notice-success is-dismissible">
				<p><?php echo esc_html__( 'Account status refreshed.', 'pendid-ai-studio' ); ?></p>
			</div>
			<?php
		}

		if ( 'connected' === $message ) {
			?>
			<div class="notice notice-success is-dismissible">
				<p><?php echo esc_html__( 'Connected to Pendid.', 'pendid-ai-studio' ); ?></p>
			</div>
			<?php
		}

		if ( 'disconnected' === $message ) {
			?>
			<div class="notice notice-success is-dismissible">
				<p><?php echo esc_html__( 'Disconnected from Pendid.', 'pendid-ai-studio' ); ?></p>
			</div>
			<?php
		}

		if ( 'disconnected_remote_failed' === $message ) {
			?>
			<div class="notice notice-warning is-dismissible">
				<p><?php echo esc_html__( 'Disconnected locally, but the remote token could not be revoked. You can reconnect safely.', 'pendid-ai-studio' ); ?></p>
			</div>
			<?php
		}

		if ( 'image_generated' === $message ) {
			?>
			<div class="notice notice-success is-dismissible">
				<p><?php echo esc_html__( 'Image generated and saved to the Media Library.', 'pendid-ai-studio' ); ?></p>
			</div>
			<?php
		}

		if ( 'account_refresh_failed' === $error ) {
			?>
			<div class="notice notice-error is-dismissible">
				<p><?php echo esc_html__( 'Account status could not be refreshed. Please try again.', 'pendid-ai-studio' ); ?></p>
			</div>
			<?php
		}

		if ( 'connection_cancelled' === $error ) {
			?>
			<div class="notice notice-info is-dismissible">
				<p><?php echo esc_html__( 'Connection was cancelled. No Pendid account was connected.', 'pendid-ai-studio' ); ?></p>
			</div>
			<?php
		}

		if ( 'connection_state_invalid' === $error ) {
			?>
			<div class="notice notice-error is-dismissible">
				<p><?php echo esc_html__( 'The connection request expired or could not be verified. Please start again.', 'pendid-ai-studio' ); ?></p>
			</div>
			<?php
		}

		if ( 'connection_failed' === $error ) {
			?>
			<div class="notice notice-error is-dismissible">
				<p><?php echo esc_html__( 'Connection could not be completed. Please try again.', 'pendid-ai-studio' ); ?></p>
			</div>
			<?php
		}

		if ( 'image_prompt_required' === $error ) {
			?>
			<div class="notice notice-error is-dismissible">
				<p><?php echo esc_html__( 'Describe the image before starting generation.', 'pendid-ai-studio' ); ?></p>
			</div>
			<?php
		}

		if ( 'connection_expired' === $error ) {
			$settings_url = admin_url( 'admin.php?page=pendid-ai-studio-settings' );
			?>
			<div class="notice notice-error is-dismissible">
				<p>
					<?php echo esc_html__( 'The connected Pendid token is no longer valid.', 'pendid-ai-studio' ); ?>
					<a href="<?php echo esc_url( $settings_url ); ?>"><?php echo esc_html__( 'Review connection settings', 'pendid-ai-studio' ); ?></a>
				</p>
			</div>
			<?php
		}

		if ( 'service_unavailable' === $error ) {
			?>
			<div class="notice notice-error is-dismissible">
				<p><?php echo esc_html__( 'Pendid Studio could not be reached. Your prompt is still available below; please try again.', 'pendid-ai-studio' ); ?></p>
			</div>
			<?php
		}

		if ( 'generation_unavailable' === $error ) {
			?>
			<div class="notice notice-error is-dismissible">
				<p><?php echo esc_html__( 'Image generation is temporarily unavailable. Your prompt has been preserved.', 'pendid-ai-studio' ); ?></p>
			</div>
			<?php
		}

		if ( 'image_generation_failed' === $error ) {
			?>
			<div class="notice notice-error is-dismissible">
				<p><?php echo esc_html__( 'Image generation failed. Your prompt has been preserved so you can try again.', 'pendid-ai-studio' ); ?></p>
			</div>
			<?php
		}

		if ( 'image_reference_invalid' === $error ) {
			?>
			<div class="notice notice-error is-dismissible">
				<p><?php echo esc_html__( 'The reference image must be a valid JPG, PNG, or WebP file within the allowed upload size.', 'pendid-ai-studio' ); ?></p>
			</div>
			<?php
		}

		if ( 'image_edit_source_missing' === $error ) {
			?>
			<div class="notice notice-error is-dismissible">
				<p><?php echo esc_html__( 'The image selected for editing is no longer available. Start a new image and try again.', 'pendid-ai-studio' ); ?></p>
			</div>
			<?php
		}

		if ( 'image_media_save_failed' === $error ) {
			?>
			<div class="notice notice-warning is-dismissible">
				<p><?php echo esc_html__( 'Image generated, but it could not be saved to the Media Library.', 'pendid-ai-studio' ); ?></p>
			</div>
			<?php
		}
	}

	/**
	 * Handles the Pendid connection callback code.
	 *
	 * @return void
	 */
	public function maybe_handle_connection_callback() {
		$state  = sanitize_text_field( $this->get_scalar_input( INPUT_GET, 'pendid_state' ) );
		$status = sanitize_key( $this->get_scalar_input( INPUT_GET, 'pendid_connect_status' ) );
		$code   = sanitize_text_field( $this->get_scalar_input( INPUT_GET, 'pendid_code' ) );

		if ( ! $this->is_plugin_admin_page() || ( '' === $code && '' === $status ) ) {
			return;
		}

		if ( ! current_user_can( 'manage_options' ) ) {
			wp_die( esc_html__( 'You do not have permission to perform this action.', 'pendid-ai-studio' ) );
		}

		/*
		 * This callback originates from Pendid Studio, so it cannot use a WordPress
		 * action nonce. The one-time state value is verified before any connection
		 * code is exchanged or stored.
		 */
		if ( ! $this->is_valid_connection_state( $state ) ) {
			$this->redirect_to_admin_page( 'pendid_error', 'connection_state_invalid' );
		}

		delete_transient( $this->get_connection_state_transient_key() );

		if ( 'cancelled' === $status ) {
			$this->redirect_to_admin_page( 'pendid_error', 'connection_cancelled' );
		}

		if ( '' === $code ) {
			$this->redirect_to_admin_page( 'pendid_error', 'connection_failed' );
		}

		$result = $this->api_client->exchange_connection_code( $code );

		if ( ! empty( $result['ok'] ) && ! empty( $result['token'] ) && is_scalar( $result['token'] ) ) {
			$account = isset( $result['account'] ) && is_array( $result['account'] ) ? $result['account'] : array();

			$this->settings->update_settings(
				array(
					'access_token'       => sanitize_text_field( (string) $result['token'] ),
					'account_email'      => $this->get_account_value( $account, array( 'account_email', 'email' ) ),
					'account_plan'       => $this->get_account_value( $account, array( 'account_plan', 'plan' ) ),
					'account_plan_title' => $this->get_account_value( $account, array( 'account_plan_title', 'plan_title', 'plantitle' ) ),
					'connected_at'       => current_time( 'mysql' ),
				)
			);

			$this->redirect_to_admin_page( 'pendid_message', 'connected' );
		}

		$this->redirect_to_admin_page( 'pendid_error', 'connection_failed' );
	}

	/**
	 * Handles account status refresh requests.
	 *
	 * @return void
	 */
	public function handle_refresh_account() {
		if ( ! current_user_can( 'manage_options' ) ) {
			wp_die( esc_html__( 'You do not have permission to perform this action.', 'pendid-ai-studio' ) );
		}

		check_admin_referer( 'pendid_ai_studio_refresh_account', 'pendid_ai_studio_refresh_account_nonce' );

		$result = $this->api_client->get_account_status( $this->settings->get_access_token() );

		if ( ! empty( $result['ok'] ) && isset( $result['account'] ) && is_array( $result['account'] ) ) {
			$this->settings->update_settings(
				array(
					'account_email'      => $this->get_account_value( $result['account'], array( 'account_email', 'email' ) ),
					'account_plan'       => $this->get_account_value( $result['account'], array( 'account_plan', 'plan' ) ),
					'account_plan_title' => $this->get_account_value( $result['account'], array( 'account_plan_title', 'plan_title', 'plantitle' ) ),
				)
			);

			$this->redirect_to_admin_page( 'pendid_message', 'account_refreshed', 'pendid-ai-studio-settings' );
		}

		$this->redirect_to_admin_page( 'pendid_error', 'account_refresh_failed', 'pendid-ai-studio-settings' );
	}

	/**
	 * Handles local disconnect requests.
	 *
	 * @return void
	 */
	public function handle_disconnect() {
		if ( ! current_user_can( 'manage_options' ) ) {
			wp_die( esc_html__( 'You do not have permission to perform this action.', 'pendid-ai-studio' ) );
		}

		check_admin_referer( 'pendid_ai_studio_disconnect', 'pendid_ai_studio_disconnect_nonce' );

		$access_token  = $this->settings->get_access_token();
		$revoke_result = array( 'ok' => true );

		if ( '' !== $access_token ) {
			$revoke_result = $this->api_client->revoke_token( $access_token );
		}

		$this->settings->disconnect();

		if ( ! empty( $revoke_result['ok'] ) ) {
			$this->redirect_to_admin_page( 'pendid_message', 'disconnected' );
		}

		$this->redirect_to_admin_page( 'pendid_message', 'disconnected_remote_failed' );
	}

	/**
	 * Handles admin image generation requests.
	 *
	 * @return void
	 */
	public function handle_generate_image() {
		if ( ! current_user_can( 'manage_options' ) ) {
			wp_die( esc_html__( 'You do not have permission to perform this action.', 'pendid-ai-studio' ) );
		}

		check_admin_referer( 'pendid_ai_studio_generate_image', 'pendid_ai_studio_generate_image_nonce' );

		$mode         = sanitize_key( $this->get_scalar_input( INPUT_POST, 'pendid_mode', 'generate' ) );
		$mode         = in_array( $mode, array( 'generate', 'edit' ), true ) ? $mode : 'generate';
		$prompt_field = 'edit' === $mode ? 'pendid_edit_prompt' : 'pendid_prompt';
		$prompt       = trim( sanitize_textarea_field( $this->get_scalar_input( INPUT_POST, $prompt_field ) ) );
		$aspect_ratio = sanitize_text_field( $this->get_scalar_input( INPUT_POST, 'pendid_aspect_ratio', '1:1' ) );
		$purpose      = sanitize_key( $this->get_scalar_input( INPUT_POST, 'pendid_image_purpose', 'featured-image' ) );
		$tone         = sanitize_text_field( $this->get_scalar_input( INPUT_POST, 'pendid_image_tone', 'حرفه‌ای' ) );

		if ( ! in_array( $aspect_ratio, array( '1:1', '3:2', '2:3' ), true ) ) {
			$aspect_ratio = '1:1';
		}

		if ( ! array_key_exists( $purpose, $this->get_image_purposes() ) ) {
			$purpose = 'featured-image';
		}

		if ( ! array_key_exists( $tone, $this->get_image_tones() ) ) {
			$tone = 'حرفه‌ای';
		}

		$source_result = 'edit' === $mode ? $this->get_generation_result() : array();

		if ( 'generate' === $mode ) {
			$this->save_generation_draft( $prompt, $aspect_ratio, $purpose, $tone );
		}

		if ( '' === $prompt ) {
			$this->redirect_to_admin_page( 'pendid_error', 'image_prompt_required', 'pendid-ai-studio-create-image' );
		}

		if ( 'edit' === $mode && empty( $source_result['url'] ) ) {
			$this->redirect_to_admin_page( 'pendid_error', 'image_edit_source_missing', 'pendid-ai-studio-create-image' );
		}

		$reference_file = array();

		if ( 'generate' === $mode ) {
			$uploaded_reference = array();

			/*
			 * The admin nonce is verified above. Uploaded file arrays must not be passed
			 * through text sanitizers; every field is validated by get_reference_upload().
			 */
			// phpcs:disable WordPress.Security.NonceVerification.Missing, WordPress.Security.NonceVerification.Recommended, WordPress.Security.ValidatedSanitizedInput.InputNotSanitized
			if ( isset( $_FILES['pendid_reference_image'] ) && is_array( $_FILES['pendid_reference_image'] ) ) {
				$uploaded_reference = $_FILES['pendid_reference_image'];
			}
			// phpcs:enable WordPress.Security.NonceVerification.Missing, WordPress.Security.NonceVerification.Recommended, WordPress.Security.ValidatedSanitizedInput.InputNotSanitized

			$reference_file = $this->get_reference_upload( $uploaded_reference );

			if ( is_wp_error( $reference_file ) ) {
				$this->redirect_to_admin_page( 'pendid_error', 'image_reference_invalid', 'pendid-ai-studio-create-image' );
			}
		}

		$request_config = $this->get_generation_request_config( $purpose, $aspect_ratio );
		$request_args   = array(
			'mode'             => $mode,
			'prompt'           => $prompt,
			'aspect_ratio'     => $aspect_ratio,
			'image_type'       => $request_config['image_type'],
			'format'           => $request_config['format'],
			'tone'             => $tone,
			'reference_file'   => $reference_file,
			'source_image_url' => 'edit' === $mode && ! empty( $source_result['url'] ) ? $source_result['url'] : '',
			'source_r2_key'    => 'edit' === $mode && ! empty( $source_result['key'] ) ? $source_result['key'] : '',
		);
		$result         = $this->api_client->generate_image( $this->settings->get_access_token(), $request_args );

		if ( ! empty( $result['ok'] ) && isset( $result['image'] ) && is_array( $result['image'] ) ) {
			$image_data                     = $result['image'];
			$metadata_prompt                 = 'edit' === $mode && ! empty( $source_result['prompt'] ) ? $source_result['prompt'] : $prompt;
			$image_data['prompt']            = $metadata_prompt;
			$image_data['last_edit_prompt']  = 'edit' === $mode ? $prompt : '';
			$image_data['mode']              = $mode;
			$image_data['purpose']           = $purpose;
			$image_data['tone']              = $tone;
			$generation_result              = $this->sanitize_generation_result( $image_data );
			$attachment_result              = $this->save_image_to_media_library( $generation_result, $metadata_prompt );

			if ( ! is_wp_error( $attachment_result ) ) {
				$generation_result = array_merge( $generation_result, $attachment_result );
				set_transient( $this->get_generation_result_transient_key(), $generation_result, 12 * HOUR_IN_SECONDS );
				$this->redirect_to_admin_page( 'pendid_message', 'image_generated', 'pendid-ai-studio-create-image' );
			}

			set_transient( $this->get_generation_result_transient_key(), $generation_result, 12 * HOUR_IN_SECONDS );
			$this->redirect_to_admin_page( 'pendid_error', 'image_media_save_failed', 'pendid-ai-studio-create-image' );
		}

		$reason = isset( $result['reason'] ) && is_scalar( $result['reason'] )
			? sanitize_key( (string) $result['reason'] )
			: 'generation_failed';

		$this->redirect_to_admin_page(
			'pendid_error',
			$this->map_generation_failure_reason( $reason ),
			'pendid-ai-studio-create-image'
		);
	}

	/**
	 * Clears the current result and returns to a fresh generation workspace.
	 *
	 * @return void
	 */
	public function handle_new_image() {
		if ( ! current_user_can( 'manage_options' ) ) {
			wp_die( esc_html__( 'You do not have permission to perform this action.', 'pendid-ai-studio' ) );
		}

		check_admin_referer( 'pendid_ai_studio_new_image', 'pendid_ai_studio_new_image_nonce' );
		delete_transient( $this->get_generation_result_transient_key() );
		wp_safe_redirect( admin_url( 'admin.php?page=pendid-ai-studio-create-image' ) );
		exit;
	}

	/**
	 * Renders the dashboard page.
	 *
	 * @return void
	 */
	public function render_dashboard_page() {
		$this->require_admin_access();

		$is_connected      = $this->settings->is_connected();
		$settings          = $is_connected ? $this->settings->get_settings() : array();
		$generation_result = $is_connected ? $this->get_generation_result() : array();
		?>
		<div class="wrap pendid-ai-studio-wrap pendid-ai-studio-dashboard-page">
			<?php $this->render_page_header( __( 'Dashboard', 'pendid-ai-studio' ), __( 'Your Pendid connection, image workflow, and WordPress media status in one place.', 'pendid-ai-studio' ), $is_connected ); ?>

			<?php if ( ! $is_connected ) : ?>
				<?php $this->render_disconnected_onboarding(); ?>
			<?php else : ?>
				<section class="pendid-ai-studio-panel pendid-ai-studio-dashboard-hero">
					<div>
						<p class="pendid-ai-studio-eyebrow"><?php echo esc_html__( 'Ready to create', 'pendid-ai-studio' ); ?></p>
						<h2><?php echo esc_html__( 'Create website images without leaving WordPress', 'pendid-ai-studio' ); ?></h2>
						<p><?php echo esc_html__( 'Generate an image, preview it, and save it directly to the Media Library through one focused workflow.', 'pendid-ai-studio' ); ?></p>
						<div class="pendid-ai-studio-hero-actions">
							<a class="button button-primary button-hero" href="<?php echo esc_url( admin_url( 'admin.php?page=pendid-ai-studio-create-image' ) ); ?>">
								<span class="dashicons dashicons-format-image pendid-ai-studio-button-icon" aria-hidden="true"></span>
								<?php echo esc_html__( 'Create an image', 'pendid-ai-studio' ); ?>
							</a>
							<a class="button button-secondary button-hero" href="<?php echo esc_url( admin_url( 'upload.php' ) ); ?>">
								<?php echo esc_html__( 'Open Media Library', 'pendid-ai-studio' ); ?>
							</a>
						</div>
					</div>
					<div class="pendid-ai-studio-dashboard-hero-art" aria-hidden="true">
						<span class="dashicons dashicons-format-image"></span>
					</div>
				</section>

				<div class="pendid-ai-studio-dashboard-grid">
					<section class="pendid-ai-studio-panel pendid-ai-studio-dashboard-card">
						<div class="pendid-ai-studio-card-icon"><span class="dashicons dashicons-admin-users" aria-hidden="true"></span></div>
						<p class="pendid-ai-studio-eyebrow"><?php echo esc_html__( 'Connected account', 'pendid-ai-studio' ); ?></p>
						<h2><?php echo esc_html( ! empty( $settings['account_plan_title'] ) ? $settings['account_plan_title'] : __( 'Pendid account', 'pendid-ai-studio' ) ); ?></h2>
						<p><?php echo esc_html( ! empty( $settings['account_email'] ) ? $settings['account_email'] : '—' ); ?></p>
						<a href="<?php echo esc_url( admin_url( 'admin.php?page=pendid-ai-studio-settings' ) ); ?>"><?php echo esc_html__( 'View connection settings', 'pendid-ai-studio' ); ?></a>
					</section>

					<section class="pendid-ai-studio-panel pendid-ai-studio-dashboard-card">
						<div class="pendid-ai-studio-card-icon"><span class="dashicons dashicons-admin-media" aria-hidden="true"></span></div>
						<p class="pendid-ai-studio-eyebrow"><?php echo esc_html__( 'WordPress workflow', 'pendid-ai-studio' ); ?></p>
						<h2><?php echo esc_html__( 'Automatic Media Library saving', 'pendid-ai-studio' ); ?></h2>
						<p><?php echo esc_html__( 'Successful generations are downloaded to WordPress and become regular media attachments.', 'pendid-ai-studio' ); ?></p>
						<a href="<?php echo esc_url( admin_url( 'upload.php' ) ); ?>"><?php echo esc_html__( 'Browse media files', 'pendid-ai-studio' ); ?></a>
					</section>

					<section class="pendid-ai-studio-panel pendid-ai-studio-dashboard-card">
						<div class="pendid-ai-studio-card-icon"><span class="dashicons dashicons-shield" aria-hidden="true"></span></div>
						<p class="pendid-ai-studio-eyebrow"><?php echo esc_html__( 'Admin only', 'pendid-ai-studio' ); ?></p>
						<h2><?php echo esc_html__( 'No public-site scripts', 'pendid-ai-studio' ); ?></h2>
						<p><?php echo esc_html__( 'The current plugin experience stays inside WordPress admin and does not inject frontend assets.', 'pendid-ai-studio' ); ?></p>
					</section>
				</div>

				<?php if ( ! empty( $generation_result['url'] ) ) : ?>
					<?php $this->render_compact_recent_result( $generation_result ); ?>
				<?php endif; ?>
			<?php endif; ?>
		</div>
		<?php
	}

	/**
	 * Renders the focused image creation page.
	 *
	 * @return void
	 */
	public function render_create_image_page() {
		$this->require_admin_access();

		$is_connected      = $this->settings->is_connected();
		$generation_result = $is_connected ? $this->get_generation_result() : array();
		$generation_draft  = $is_connected ? $this->get_generation_draft() : $this->get_default_generation_draft();
		$generation_error  = $this->get_requested_generation_error();
		$has_result        = ! empty( $generation_result['url'] );
		$tones             = $this->get_image_tones();
		$purposes          = $this->get_image_purposes();
		?>
		<div class="wrap pendid-ai-studio-wrap pendid-ai-studio-create-page">
			<?php $this->render_page_header( __( 'Create Image', 'pendid-ai-studio' ), __( 'Generate website-ready visuals, refine the result, and save every successful version to the Media Library.', 'pendid-ai-studio' ), $is_connected ); ?>

			<?php if ( ! $is_connected ) : ?>
				<?php $this->render_connection_required(); ?>
			<?php else : ?>
				<div class="pendid-ai-studio-create-workspace<?php echo $has_result ? ' has-result' : ''; ?>">
					<section class="pendid-ai-studio-panel pendid-ai-studio-preview-panel">
						<div class="pendid-ai-studio-workspace-heading">
							<div>
								<p class="pendid-ai-studio-eyebrow"><?php echo esc_html__( 'Result', 'pendid-ai-studio' ); ?></p>
								<h2><?php echo esc_html__( 'Image preview', 'pendid-ai-studio' ); ?></h2>
								<?php if ( $has_result ) : ?>
									<p><?php echo esc_html__( 'Your image is ready. Edit this result or start a new image.', 'pendid-ai-studio' ); ?></p>
								<?php endif; ?>
							</div>
							<?php if ( ! empty( $generation_result['attachment_url'] ) ) : ?>
								<span class="pendid-ai-studio-saved-badge"><span class="dashicons dashicons-yes-alt" aria-hidden="true"></span><?php echo esc_html__( 'Saved to Media Library', 'pendid-ai-studio' ); ?></span>
							<?php endif; ?>
						</div>

						<div class="pendid-ai-studio-preview-stage">
							<?php if ( $has_result ) : ?>
								<?php $preview_url = ! empty( $generation_result['attachment_url'] ) ? $generation_result['attachment_url'] : $generation_result['url']; ?>
								<?php $preview_alt = ! empty( $generation_result['prompt'] ) ? $generation_result['prompt'] : __( 'Generated image preview', 'pendid-ai-studio' ); ?>
								<img src="<?php echo esc_url( $preview_url ); ?>" alt="<?php echo esc_attr( $preview_alt ); ?>">
							<?php else : ?>
								<div class="pendid-ai-studio-preview-empty">
									<span class="pendid-ai-studio-preview-symbol"><span class="dashicons dashicons-format-image" aria-hidden="true"></span></span>
									<h3><?php echo esc_html__( 'Your generated image will appear here', 'pendid-ai-studio' ); ?></h3>
									<p><?php echo esc_html__( 'Choose the website purpose, image mood, optional reference, and format before starting generation.', 'pendid-ai-studio' ); ?></p>
								</div>
							<?php endif; ?>
						</div>

						<?php if ( $has_result ) : ?>
							<div class="pendid-ai-studio-preview-actions">
								<form method="post" action="<?php echo esc_url( admin_url( 'admin-post.php' ) ); ?>">
									<input type="hidden" name="action" value="pendid_ai_studio_new_image">
									<?php wp_nonce_field( 'pendid_ai_studio_new_image', 'pendid_ai_studio_new_image_nonce' ); ?>
									<button type="submit" class="button button-primary pendid-ai-studio-new-image-button"><span class="dashicons dashicons-plus-alt2" aria-hidden="true"></span><span><?php echo esc_html__( 'Create new image', 'pendid-ai-studio' ); ?></span></button>
								</form>
								<?php $open_url = ! empty( $generation_result['attachment_url'] ) ? $generation_result['attachment_url'] : $generation_result['url']; ?>
								<a class="button button-secondary" href="<?php echo esc_url( $open_url ); ?>" target="_blank" rel="noopener noreferrer"><?php echo esc_html__( 'Open image', 'pendid-ai-studio' ); ?></a>
							</div>
						<?php endif; ?>

						<div class="pendid-ai-studio-storage-notes">
							<div class="pendid-ai-studio-storage-note">
								<span class="dashicons dashicons-admin-media" aria-hidden="true"></span>
								<p><strong><?php echo esc_html__( 'Automatic WordPress saving', 'pendid-ai-studio' ); ?></strong><small><?php echo esc_html__( 'Every successful image is added to your Media Library automatically.', 'pendid-ai-studio' ); ?></small></p>
							</div>
							<div class="pendid-ai-studio-storage-note">
								<span class="dashicons dashicons-backup" aria-hidden="true"></span>
								<p><strong><?php echo esc_html__( 'Saved in your Pendid account', 'pendid-ai-studio' ); ?></strong><small><?php echo esc_html__( 'A copy is also kept in Pendid Studio, so your generated images remain available as a backup.', 'pendid-ai-studio' ); ?></small></p>
							</div>
						</div>
					</section>

					<aside class="pendid-ai-studio-panel pendid-ai-studio-controls-panel">
						<?php if ( $has_result ) : ?>
							<div class="pendid-ai-studio-workspace-heading">
								<div>
									<p class="pendid-ai-studio-eyebrow"><?php echo esc_html__( 'Next step', 'pendid-ai-studio' ); ?></p>
									<h2><?php echo esc_html__( 'Edit this image', 'pendid-ai-studio' ); ?></h2>
									<p><?php echo esc_html__( 'Describe one clear change. The edited version will be saved as a new Media Library item.', 'pendid-ai-studio' ); ?></p>
								</div>
							</div>

							<form id="pendid-ai-studio-edit-form" class="pendid-ai-studio-generation-form" method="post" action="<?php echo esc_url( admin_url( 'admin-post.php' ) ); ?>" data-pendid-generation-form data-pendid-loading-label="<?php echo esc_attr__( 'Editing and saving...', 'pendid-ai-studio' ); ?>">
								<input type="hidden" name="action" value="pendid_ai_studio_generate_image">
								<input type="hidden" name="pendid_mode" value="edit">
								<input type="hidden" name="pendid_aspect_ratio" value="<?php echo esc_attr( ! empty( $generation_result['aspect_ratio'] ) ? $generation_result['aspect_ratio'] : $generation_draft['aspect_ratio'] ); ?>">
								<input type="hidden" name="pendid_image_purpose" value="<?php echo esc_attr( ! empty( $generation_result['purpose'] ) ? $generation_result['purpose'] : $generation_draft['purpose'] ); ?>">
								<input type="hidden" name="pendid_image_tone" value="<?php echo esc_attr( ! empty( $generation_result['tone'] ) ? $generation_result['tone'] : $generation_draft['tone'] ); ?>">
								<?php wp_nonce_field( 'pendid_ai_studio_generate_image', 'pendid_ai_studio_generate_image_nonce' ); ?>

								<div class="pendid-ai-studio-field">
									<label for="pendid-edit-prompt"><?php echo esc_html__( 'What should change?', 'pendid-ai-studio' ); ?></label>
									<textarea id="pendid-edit-prompt" name="pendid_edit_prompt" rows="8" minlength="8" maxlength="1200" placeholder="<?php echo esc_attr__( 'For example: Make the background brighter, keep the main subject unchanged, remove the text, and use softer natural colors.', 'pendid-ai-studio' ); ?>" required><?php echo esc_textarea( ! empty( $generation_result['last_edit_prompt'] ) ? $generation_result['last_edit_prompt'] : '' ); ?></textarea>
									<p class="description"><?php echo esc_html__( 'For more reliable edits, request one focused change at a time.', 'pendid-ai-studio' ); ?></p>
								</div>

								<div class="pendid-ai-studio-edit-source-note">
									<span class="dashicons dashicons-images-alt2" aria-hidden="true"></span>
									<p><strong><?php echo esc_html__( 'The current result is the edit source', 'pendid-ai-studio' ); ?></strong><small><?php echo esc_html__( 'The original image remains in your Media Library. A successful edit creates another attachment.', 'pendid-ai-studio' ); ?></small></p>
								</div>

								<button type="submit" class="button button-primary button-hero pendid-ai-studio-generate-button" data-pendid-generate-button>
									<span class="dashicons dashicons-edit pendid-ai-studio-button-icon" data-pendid-generate-icon aria-hidden="true"></span>
									<span data-pendid-generate-label><?php echo esc_html__( 'Edit this image', 'pendid-ai-studio' ); ?></span>
									<span class="pendid-ai-studio-loading-spinner" data-pendid-generate-spinner hidden aria-hidden="true"></span>
								</button>
								<p class="pendid-ai-studio-generation-status" data-pendid-generation-status hidden aria-live="polite"><?php echo esc_html__( 'Editing the image and saving a new version to WordPress. Please keep this page open.', 'pendid-ai-studio' ); ?></p>
							</form>
						<?php else : ?>
							<div class="pendid-ai-studio-workspace-heading">
								<div>
									<p class="pendid-ai-studio-eyebrow"><?php echo esc_html__( 'Website image', 'pendid-ai-studio' ); ?></p>
									<h2><?php echo esc_html__( 'Generation settings', 'pendid-ai-studio' ); ?></h2>
								</div>
							</div>

							<form id="pendid-ai-studio-generation-form" class="pendid-ai-studio-generation-form" method="post" enctype="multipart/form-data" action="<?php echo esc_url( admin_url( 'admin-post.php' ) ); ?>" data-pendid-generation-form data-pendid-loading-label="<?php echo esc_attr__( 'Generating and saving...', 'pendid-ai-studio' ); ?>">
								<input type="hidden" name="action" value="pendid_ai_studio_generate_image">
								<input type="hidden" name="pendid_mode" value="generate">
								<?php wp_nonce_field( 'pendid_ai_studio_generate_image', 'pendid_ai_studio_generate_image_nonce' ); ?>

								<fieldset class="pendid-ai-studio-purpose-fieldset">
									<legend><?php echo esc_html__( 'Website image purpose', 'pendid-ai-studio' ); ?></legend>
									<div class="pendid-ai-studio-purpose-grid">
										<?php foreach ( $purposes as $purpose_id => $purpose_item ) : ?>
											<label class="pendid-ai-studio-purpose-option">
												<input type="radio" name="pendid_image_purpose" value="<?php echo esc_attr( $purpose_id ); ?>" <?php checked( $generation_draft['purpose'], $purpose_id ); ?>>
												<span><strong><?php echo esc_html( $purpose_item['title'] ); ?></strong><small><?php echo esc_html( $purpose_item['helper'] ); ?></small></span>
											</label>
										<?php endforeach; ?>
									</div>
								</fieldset>

								<fieldset class="pendid-ai-studio-ratio-fieldset">
									<legend><?php echo esc_html__( 'Image format', 'pendid-ai-studio' ); ?></legend>
									<div class="pendid-ai-studio-ratio-grid">
										<label class="pendid-ai-studio-ratio-option"><input type="radio" name="pendid_aspect_ratio" value="1:1" <?php checked( $generation_draft['aspect_ratio'], '1:1' ); ?>><span class="pendid-ai-studio-ratio-card"><span class="pendid-ai-studio-ratio-preview is-square" aria-hidden="true"></span><span><strong><?php echo esc_html__( 'Square', 'pendid-ai-studio' ); ?></strong><small>1:1</small></span></span></label>
										<label class="pendid-ai-studio-ratio-option"><input type="radio" name="pendid_aspect_ratio" value="3:2" <?php checked( $generation_draft['aspect_ratio'], '3:2' ); ?>><span class="pendid-ai-studio-ratio-card"><span class="pendid-ai-studio-ratio-preview is-landscape" aria-hidden="true"></span><span><strong><?php echo esc_html__( 'Landscape', 'pendid-ai-studio' ); ?></strong><small>3:2</small></span></span></label>
										<label class="pendid-ai-studio-ratio-option"><input type="radio" name="pendid_aspect_ratio" value="2:3" <?php checked( $generation_draft['aspect_ratio'], '2:3' ); ?>><span class="pendid-ai-studio-ratio-card"><span class="pendid-ai-studio-ratio-preview is-portrait" aria-hidden="true"></span><span><strong><?php echo esc_html__( 'Portrait', 'pendid-ai-studio' ); ?></strong><small>2:3</small></span></span></label>
									</div>
								</fieldset>

								<section class="pendid-ai-studio-tone-section">
									<div class="pendid-ai-studio-section-title-row">
										<div><strong><?php echo esc_html__( 'Image mood', 'pendid-ai-studio' ); ?></strong><small><?php echo esc_html__( 'Use a visual direction designed for website content.', 'pendid-ai-studio' ); ?></small></div>
										<button type="button" class="button button-link" data-pendid-modal-open="pendid-ai-studio-tone-modal"><?php echo esc_html__( 'Choose', 'pendid-ai-studio' ); ?></button>
									</div>
									<div class="pendid-ai-studio-tone-strip" data-pendid-tone-strip>
										<?php foreach ( array_slice( $tones, 0, 5, true ) as $tone_value => $tone_item ) : ?>
											<button type="button" class="pendid-ai-studio-tone-thumb<?php echo $generation_draft['tone'] === $tone_value ? ' is-active' : ''; ?>" data-pendid-modal-open="pendid-ai-studio-tone-modal" data-pendid-tone-value="<?php echo esc_attr( $tone_value ); ?>" aria-label="<?php echo esc_attr( $tone_item['title'] ); ?>">
												<?php $this->render_tone_visual( $tone_item, 'thumb' ); ?>
											</button>
										<?php endforeach; ?>
									</div>
									<p class="pendid-ai-studio-selected-tone"><?php echo esc_html__( 'Current selection:', 'pendid-ai-studio' ); ?> <strong data-pendid-selected-tone><?php echo esc_html( $tones[ $generation_draft['tone'] ]['title'] ); ?></strong></p>
								</section>

								<div class="pendid-ai-studio-field">
									<label for="pendid-prompt"><?php echo esc_html__( 'Describe the image', 'pendid-ai-studio' ); ?></label>
									<textarea id="pendid-prompt" name="pendid_prompt" rows="6" placeholder="<?php echo esc_attr__( 'For example: A clean editorial hero image for an article about modern home renovation, natural daylight, realistic photography, no text', 'pendid-ai-studio' ); ?>" aria-describedby="pendid-prompt-help" maxlength="1200" minlength="8" required><?php echo esc_textarea( $generation_draft['prompt'] ); ?></textarea>
									<p id="pendid-prompt-help" class="description"><?php echo esc_html__( 'Include the subject, environment, visual style, lighting, and mood your page needs.', 'pendid-ai-studio' ); ?></p>
								</div>

								<label class="pendid-ai-studio-reference-card" for="pendid-reference-image">
									<input id="pendid-reference-image" type="file" name="pendid_reference_image" accept="image/jpeg,image/png,image/webp" data-pendid-reference-input>
									<span class="pendid-ai-studio-reference-preview" data-pendid-reference-preview><span class="dashicons dashicons-format-image" aria-hidden="true"></span></span>
									<?php
									$reference_help = sprintf(
										/* translators: %s: Maximum reference image upload size in megabytes. */
										__( 'Optional JPG, PNG, or WebP. Maximum %s MB.', 'pendid-ai-studio' ),
										number_format_i18n( $this->get_reference_max_bytes() / MB_IN_BYTES, 0 )
									);
									?>
									<span class="pendid-ai-studio-reference-copy"><strong><?php echo esc_html__( 'Reference image', 'pendid-ai-studio' ); ?></strong><small><?php echo esc_html( $reference_help ); ?></small></span>
									<span class="button button-secondary"><?php echo esc_html__( 'Choose image', 'pendid-ai-studio' ); ?></span>
								</label>


								<button type="submit" class="button button-primary button-hero pendid-ai-studio-generate-button" data-pendid-generate-button><span class="dashicons dashicons-format-image pendid-ai-studio-button-icon" data-pendid-generate-icon aria-hidden="true"></span><span data-pendid-generate-label><?php echo esc_html__( 'Generate website image', 'pendid-ai-studio' ); ?></span><span class="pendid-ai-studio-loading-spinner" data-pendid-generate-spinner hidden aria-hidden="true"></span></button>
								<p class="pendid-ai-studio-generation-status" data-pendid-generation-status hidden aria-live="polite"><?php echo esc_html__( 'Generating your image and saving it to WordPress. Please keep this page open.', 'pendid-ai-studio' ); ?></p>
							</form>
						<?php endif; ?>
					</aside>
				</div>
				<?php if ( ! $has_result ) : ?>
					<?php $this->render_tone_modal( $tones, $generation_draft['tone'] ); ?>
				<?php endif; ?>
			<?php endif; ?>
			<?php $this->render_generation_access_modal( $generation_error ); ?>
		</div>
		<?php
	}

	/**
	 * Renders the settings page.
	 *
	 * @return void
	 */
	public function render_settings_page() {
		$this->require_admin_access();

		$is_connected = $this->settings->is_connected();
		$settings     = $is_connected ? $this->settings->get_settings() : array();
		?>
		<div class="wrap pendid-ai-studio-wrap pendid-ai-studio-settings-page">
			<?php $this->render_page_header( __( 'Settings', 'pendid-ai-studio' ), __( 'Manage the connected Pendid account and review how generated files are handled in WordPress.', 'pendid-ai-studio' ), $is_connected ); ?>

			<?php if ( ! $is_connected ) : ?>
				<?php $this->render_connection_required(); ?>
			<?php else : ?>
				<div class="pendid-ai-studio-settings-grid">
					<section class="pendid-ai-studio-panel">
						<div class="pendid-ai-studio-panel-header">
							<p class="pendid-ai-studio-eyebrow"><?php echo esc_html__( 'Pendid account', 'pendid-ai-studio' ); ?></p>
							<h2><?php echo esc_html__( 'Connection details', 'pendid-ai-studio' ); ?></h2>
							<p><?php echo esc_html__( 'This site uses an internal plugin token. The token is never shown in the WordPress interface.', 'pendid-ai-studio' ); ?></p>
						</div>
						<div class="pendid-ai-studio-panel-body">
							<dl class="pendid-ai-studio-status-list">
								<div><dt><?php echo esc_html__( 'Email', 'pendid-ai-studio' ); ?></dt><dd><?php echo esc_html( ! empty( $settings['account_email'] ) ? $settings['account_email'] : '—' ); ?></dd></div>
								<div><dt><?php echo esc_html__( 'Plan', 'pendid-ai-studio' ); ?></dt><dd><?php echo esc_html( ! empty( $settings['account_plan_title'] ) ? $settings['account_plan_title'] : '—' ); ?></dd></div>
								<div><dt><?php echo esc_html__( 'Connected on', 'pendid-ai-studio' ); ?></dt><dd><?php echo esc_html( ! empty( $settings['connected_at'] ) ? $settings['connected_at'] : '—' ); ?></dd></div>
							</dl>

							<div class="pendid-ai-studio-settings-actions">
								<a class="button button-secondary" href="<?php echo esc_url( $this->api_client->get_manage_account_url() ); ?>" target="_blank" rel="noopener noreferrer"><?php echo esc_html__( 'Manage Pendid account', 'pendid-ai-studio' ); ?><span class="dashicons dashicons-external" aria-hidden="true"></span></a>
								<form method="post" action="<?php echo esc_url( admin_url( 'admin-post.php' ) ); ?>">
									<input type="hidden" name="action" value="pendid_ai_studio_refresh_account">
									<?php wp_nonce_field( 'pendid_ai_studio_refresh_account', 'pendid_ai_studio_refresh_account_nonce' ); ?>
									<button type="submit" class="button button-secondary"><?php echo esc_html__( 'Refresh account status', 'pendid-ai-studio' ); ?></button>
								</form>
							</div>
						</div>
					</section>

					<section class="pendid-ai-studio-panel">
						<div class="pendid-ai-studio-panel-header">
							<p class="pendid-ai-studio-eyebrow"><?php echo esc_html__( 'WordPress media', 'pendid-ai-studio' ); ?></p>
							<h2><?php echo esc_html__( 'Current save behavior', 'pendid-ai-studio' ); ?></h2>
						</div>
						<div class="pendid-ai-studio-panel-body">
							<div class="pendid-ai-studio-setting-row"><span class="dashicons dashicons-yes-alt" aria-hidden="true"></span><p><strong><?php echo esc_html__( 'Save automatically', 'pendid-ai-studio' ); ?></strong><small><?php echo esc_html__( 'Successful generated images are downloaded and added to the Media Library.', 'pendid-ai-studio' ); ?></small></p></div>
							<div class="pendid-ai-studio-setting-row"><span class="dashicons dashicons-shield" aria-hidden="true"></span><p><strong><?php echo esc_html__( 'Restricted media source', 'pendid-ai-studio' ); ?></strong><small><?php echo esc_html__( 'The plugin only accepts generated files returned from media.pendid.com.', 'pendid-ai-studio' ); ?></small></p></div>
						</div>
					</section>
				</div>

				<section class="pendid-ai-studio-panel pendid-ai-studio-danger-panel">
					<div>
						<h2><?php echo esc_html__( 'Disconnect this site', 'pendid-ai-studio' ); ?></h2>
						<p><?php echo esc_html__( 'Disconnecting clears the local connection and attempts to revoke the remote plugin token.', 'pendid-ai-studio' ); ?></p>
					</div>
					<form method="post" action="<?php echo esc_url( admin_url( 'admin-post.php' ) ); ?>">
						<input type="hidden" name="action" value="pendid_ai_studio_disconnect">
						<?php wp_nonce_field( 'pendid_ai_studio_disconnect', 'pendid_ai_studio_disconnect_nonce' ); ?>
						<button type="submit" class="button button-link-delete pendid-ai-studio-disconnect"><?php echo esc_html__( 'Disconnect site', 'pendid-ai-studio' ); ?></button>
					</form>
				</section>
			<?php endif; ?>
		</div>
		<?php
	}

	/**
	 * Renders the shared page header.
	 *
	 * @param string $title        Page title.
	 * @param string $description  Page description.
	 * @param bool   $is_connected Whether the site is connected.
	 * @return void
	 */
	private function render_page_header( $title, $description, $is_connected ) {
		?>
		<header class="pendid-ai-studio-page-header">
			<div class="pendid-ai-studio-brand">
				<span class="pendid-ai-studio-brand-mark">
					<img class="pendid-ai-studio-brand-logo" src="<?php echo esc_url( PENDID_AI_STUDIO_URL . 'assets/images/pendid-logo.png' ); ?>" alt="" width="48" height="48">
				</span>
				<div>
					<p class="pendid-ai-studio-product-name"><?php echo esc_html__( 'Pendid AI Studio', 'pendid-ai-studio' ); ?></p>
					<h1><?php echo esc_html( $title ); ?></h1>
					<p><?php echo esc_html( $description ); ?></p>
				</div>
			</div>
			<?php if ( $is_connected ) : ?>
				<span class="pendid-ai-studio-connection-badge"><span aria-hidden="true"></span><?php echo esc_html__( 'Connected', 'pendid-ai-studio' ); ?></span>
			<?php endif; ?>
		</header>
		<?php
	}

	/**
	 * Renders the full disconnected onboarding experience.
	 *
	 * @return void
	 */
	private function render_disconnected_onboarding() {
		?>
		<section class="pendid-ai-studio-panel pendid-ai-studio-onboarding">
			<div class="pendid-ai-studio-onboarding-content">
				<p class="pendid-ai-studio-eyebrow"><?php echo esc_html__( 'Get started', 'pendid-ai-studio' ); ?></p>
				<h2><?php echo esc_html__( 'Connect WordPress to your Pendid account', 'pendid-ai-studio' ); ?></h2>
				<p class="pendid-ai-studio-onboarding-description"><?php echo esc_html__( 'Continue to Pendid Studio and return automatically after the account connection is completed. No access token needs to be copied or pasted.', 'pendid-ai-studio' ); ?></p>
				<a class="button button-primary button-hero pendid-ai-studio-connect-button pendid-ai-studio-open-connect-modal" href="<?php echo esc_url( $this->get_connect_url() ); ?>" aria-haspopup="dialog" aria-controls="pendid-ai-studio-connect-dialog"><?php echo esc_html__( 'Review and connect', 'pendid-ai-studio' ); ?><span class="dashicons dashicons-external pendid-ai-studio-button-icon" aria-hidden="true"></span></a>
				<p class="pendid-ai-studio-connection-note"><span class="dashicons dashicons-lock" aria-hidden="true"></span><?php echo esc_html__( 'Your Pendid password is never entered or stored in WordPress.', 'pendid-ai-studio' ); ?></p>
			</div>
			<div class="pendid-ai-studio-onboarding-steps" aria-label="<?php echo esc_attr__( 'Connection steps', 'pendid-ai-studio' ); ?>">
				<div><span>1</span><p><strong><?php echo esc_html__( 'Review the connection', 'pendid-ai-studio' ); ?></strong><small><?php echo esc_html__( 'See what is shared with Pendid before leaving WordPress.', 'pendid-ai-studio' ); ?></small></p></div>
				<div><span>2</span><p><strong><?php echo esc_html__( 'Continue to Studio', 'pendid-ai-studio' ); ?></strong><small><?php echo esc_html__( 'Sign in when required, then review and approve the connection in Studio.', 'pendid-ai-studio' ); ?></small></p></div>
				<div><span>3</span><p><strong><?php echo esc_html__( 'Return to WordPress', 'pendid-ai-studio' ); ?></strong><small><?php echo esc_html__( 'You return to the dashboard and can begin creating images.', 'pendid-ai-studio' ); ?></small></p></div>
			</div>
		</section>

		<div class="pendid-ai-studio-benefits">
			<div><span class="dashicons dashicons-admin-network" aria-hidden="true"></span><p><strong><?php echo esc_html__( 'No manual tokens', 'pendid-ai-studio' ); ?></strong><small><?php echo esc_html__( 'Connection is completed through your Pendid account.', 'pendid-ai-studio' ); ?></small></p></div>
			<div><span class="dashicons dashicons-shield" aria-hidden="true"></span><p><strong><?php echo esc_html__( 'Admin-only tools', 'pendid-ai-studio' ); ?></strong><small><?php echo esc_html__( 'The plugin does not add scripts to your public website.', 'pendid-ai-studio' ); ?></small></p></div>
			<div><span class="dashicons dashicons-admin-media" aria-hidden="true"></span><p><strong><?php echo esc_html__( 'WordPress media', 'pendid-ai-studio' ); ?></strong><small><?php echo esc_html__( 'Use generated images like regular Media Library files.', 'pendid-ai-studio' ); ?></small></p></div>
		</div>
		<?php $this->render_connection_modal(); ?>
		<?php
	}

	/**
	 * Renders a compact connection-required panel.
	 *
	 * @return void
	 */
	private function render_connection_required() {
		?>
		<section class="pendid-ai-studio-panel pendid-ai-studio-connection-required">
			<span class="pendid-ai-studio-preview-symbol"><span class="dashicons dashicons-admin-network" aria-hidden="true"></span></span>
			<h2><?php echo esc_html__( 'Connect a Pendid account to continue', 'pendid-ai-studio' ); ?></h2>
			<p><?php echo esc_html__( 'Image creation and account settings become available after this WordPress site is connected to Pendid Studio.', 'pendid-ai-studio' ); ?></p>
			<a class="button button-primary button-hero pendid-ai-studio-open-connect-modal" href="<?php echo esc_url( $this->get_connect_url() ); ?>" aria-haspopup="dialog" aria-controls="pendid-ai-studio-connect-dialog"><?php echo esc_html__( 'Review and connect', 'pendid-ai-studio' ); ?><span class="dashicons dashicons-external pendid-ai-studio-button-icon" aria-hidden="true"></span></a>
		</section>
		<?php $this->render_connection_modal(); ?>
		<?php
	}

	/**
	 * Renders the connection review dialog before leaving WordPress.
	 *
	 * @return void
	 */
	private function render_connection_modal() {
		$site_name   = get_bloginfo( 'name' );
		$display_url = home_url();
		?>
		<div id="pendid-ai-studio-connect-modal" class="pendid-ai-studio-modal" hidden>
			<div class="pendid-ai-studio-modal-backdrop" data-pendid-modal-close></div>
			<section
				id="pendid-ai-studio-connect-dialog"
				class="pendid-ai-studio-modal-dialog"
				role="dialog"
				aria-modal="true"
				aria-labelledby="pendid-ai-studio-connect-title"
				aria-describedby="pendid-ai-studio-connect-description"
				tabindex="-1"
			>
				<button type="button" class="pendid-ai-studio-modal-close" data-pendid-modal-close aria-label="<?php echo esc_attr__( 'Close connection dialog', 'pendid-ai-studio' ); ?>">
					<span class="dashicons dashicons-no-alt" aria-hidden="true"></span>
				</button>

				<div class="pendid-ai-studio-modal-icon" aria-hidden="true">
					<span class="dashicons dashicons-admin-links"></span>
				</div>
				<p class="pendid-ai-studio-eyebrow"><?php echo esc_html__( 'Before you connect', 'pendid-ai-studio' ); ?></p>
				<h2 id="pendid-ai-studio-connect-title"><?php echo esc_html__( 'Connect this WordPress site to Pendid?', 'pendid-ai-studio' ); ?></h2>
				<p id="pendid-ai-studio-connect-description" class="pendid-ai-studio-modal-description"><?php echo esc_html__( 'You will continue to studio.pendid.com, sign in if needed, and review the connection again before approving it and returning to WordPress.', 'pendid-ai-studio' ); ?></p>

				<div class="pendid-ai-studio-modal-site">
					<span><?php echo esc_html__( 'Site being connected', 'pendid-ai-studio' ); ?></span>
					<strong><?php echo esc_html( $site_name ? $site_name : __( 'WordPress site', 'pendid-ai-studio' ) ); ?></strong>
					<code><?php echo esc_html( $display_url ); ?></code>
				</div>

				<ul class="pendid-ai-studio-modal-list">
					<li><span class="dashicons dashicons-yes-alt" aria-hidden="true"></span><?php echo esc_html__( 'The site URL and site name are sent to Pendid to identify this connection.', 'pendid-ai-studio' ); ?></li>
					<li><span class="dashicons dashicons-yes-alt" aria-hidden="true"></span><?php echo esc_html__( 'An internal plugin token is stored in WordPress and is never displayed in the interface.', 'pendid-ai-studio' ); ?></li>
					<li><span class="dashicons dashicons-yes-alt" aria-hidden="true"></span><?php echo esc_html__( 'Prompts and image format are sent only when an administrator chooses to generate an image.', 'pendid-ai-studio' ); ?></li>
					<li><span class="dashicons dashicons-yes-alt" aria-hidden="true"></span><?php echo esc_html__( 'No WordPress password, visitor data, or public-site tracking is sent.', 'pendid-ai-studio' ); ?></li>
				</ul>

				<p class="pendid-ai-studio-modal-legal">
					<?php echo esc_html__( 'By continuing, you authorize this site to communicate with the documented Pendid service.', 'pendid-ai-studio' ); ?>
					<a href="<?php echo esc_url( 'https://pendid.com/privacy-policy/' ); ?>" target="_blank" rel="noopener noreferrer"><?php echo esc_html__( 'Privacy Policy', 'pendid-ai-studio' ); ?></a>
					<span aria-hidden="true">·</span>
					<a href="<?php echo esc_url( 'https://pendid.com/terms/' ); ?>" target="_blank" rel="noopener noreferrer"><?php echo esc_html__( 'Terms', 'pendid-ai-studio' ); ?></a>
				</p>

				<div class="pendid-ai-studio-modal-actions">
					<button type="button" class="button button-secondary" data-pendid-modal-close><?php echo esc_html__( 'Cancel', 'pendid-ai-studio' ); ?></button>
					<a class="button button-primary button-hero" href="<?php echo esc_url( $this->get_connect_url() ); ?>">
						<?php echo esc_html__( 'Continue to Pendid Studio', 'pendid-ai-studio' ); ?>
						<span class="dashicons dashicons-external pendid-ai-studio-button-icon" aria-hidden="true"></span>
					</a>
				</div>
			</section>
		</div>
		<?php
	}

	/**
	 * Renders a contextual Pendid account modal after an allowance or plan rejection.
	 *
	 * @param string $error Current generation error.
	 * @return void
	 */
	private function render_generation_access_modal( $error ) {
		if ( ! in_array( $error, array( 'image_allowance_exhausted', 'image_plan_required' ), true ) ) {
			return;
		}

		$is_exhausted = 'image_allowance_exhausted' === $error;
		$title        = $is_exhausted
			? __( 'Your current image allowance has been used', 'pendid-ai-studio' )
			: __( 'Image generation needs an active Pendid plan', 'pendid-ai-studio' );
		$description  = $is_exhausted
			? __( 'Pendid Studio did not approve another image because the available allowance for this account has been used.', 'pendid-ai-studio' )
			: __( 'The connected Pendid account does not currently have an active image allowance for this request.', 'pendid-ai-studio' );
		?>
		<div id="pendid-ai-studio-generation-access-modal" class="pendid-ai-studio-modal" hidden data-pendid-auto-open="true">
			<div class="pendid-ai-studio-modal-backdrop" data-pendid-modal-close></div>
			<section
				class="pendid-ai-studio-modal-dialog pendid-ai-studio-access-dialog"
				role="dialog"
				aria-modal="true"
				aria-labelledby="pendid-ai-studio-access-title"
				aria-describedby="pendid-ai-studio-access-description"
				tabindex="-1"
			>
				<button type="button" class="pendid-ai-studio-modal-close" data-pendid-modal-close aria-label="<?php echo esc_attr__( 'Close account dialog', 'pendid-ai-studio' ); ?>">
					<span class="dashicons dashicons-no-alt" aria-hidden="true"></span>
				</button>

				<div class="pendid-ai-studio-modal-icon pendid-ai-studio-access-icon" aria-hidden="true">
					<span class="dashicons dashicons-admin-users"></span>
				</div>
				<p class="pendid-ai-studio-eyebrow"><?php echo esc_html__( 'Pendid account', 'pendid-ai-studio' ); ?></p>
				<h2 id="pendid-ai-studio-access-title"><?php echo esc_html( $title ); ?></h2>
				<p id="pendid-ai-studio-access-description" class="pendid-ai-studio-modal-description"><?php echo esc_html( $description ); ?></p>

				<div class="pendid-ai-studio-access-note">
					<span class="dashicons dashicons-saved" aria-hidden="true"></span>
					<p><strong><?php echo esc_html__( 'Your work is safe', 'pendid-ai-studio' ); ?></strong><small><?php echo esc_html__( 'Your prompt and selected image format are still saved in this WordPress editor.', 'pendid-ai-studio' ); ?></small></p>
				</div>

				<ul class="pendid-ai-studio-modal-list">
					<li><span class="dashicons dashicons-yes-alt" aria-hidden="true"></span><span><?php echo esc_html__( 'No new image was generated or saved for this rejected request.', 'pendid-ai-studio' ); ?></span></li>
					<li><span class="dashicons dashicons-yes-alt" aria-hidden="true"></span><span><?php echo esc_html__( 'Account and plan changes are completed securely in Pendid Studio.', 'pendid-ai-studio' ); ?></span></li>
				</ul>

				<div class="pendid-ai-studio-modal-actions pendid-ai-studio-access-actions">
					<a class="button button-primary" href="<?php echo esc_url( $this->api_client->get_manage_account_url() ); ?>" target="_blank" rel="noopener noreferrer">
						<?php echo esc_html__( 'View Pendid plans', 'pendid-ai-studio' ); ?>
						<span class="dashicons dashicons-external pendid-ai-studio-button-icon" aria-hidden="true"></span>
					</a>
					<a class="button button-secondary" href="<?php echo esc_url( $this->api_client->get_account_url() ); ?>" target="_blank" rel="noopener noreferrer">
						<?php echo esc_html__( 'Open Pendid account', 'pendid-ai-studio' ); ?>
						<span class="dashicons dashicons-external" aria-hidden="true"></span>
					</a>
					<button type="button" class="button button-secondary" data-pendid-modal-close><?php echo esc_html__( 'Return to editor', 'pendid-ai-studio' ); ?></button>
				</div>
			</section>
		</div>
		<?php
	}

	/**
	 * Renders the last generated image on the dashboard.
	 *
	 * @param array<string, mixed> $generation_result Generated image data.
	 * @return void
	 */
	private function render_compact_recent_result( $generation_result ) {
		$preview_url = ! empty( $generation_result['attachment_url'] ) ? $generation_result['attachment_url'] : $generation_result['url'];
		?>
		<section class="pendid-ai-studio-panel pendid-ai-studio-recent-result">
			<?php $recent_alt = ! empty( $generation_result['prompt'] ) ? $generation_result['prompt'] : __( 'Most recently generated image', 'pendid-ai-studio' ); ?>
			<img src="<?php echo esc_url( $preview_url ); ?>" alt="<?php echo esc_attr( $recent_alt ); ?>">
			<div>
				<p class="pendid-ai-studio-eyebrow"><?php echo esc_html__( 'Recent result', 'pendid-ai-studio' ); ?></p>
				<h2><?php echo esc_html__( 'Your latest image is ready in WordPress', 'pendid-ai-studio' ); ?></h2>
				<p><?php echo esc_html__( 'Open the focused creation workspace to view the result or generate another image.', 'pendid-ai-studio' ); ?></p>
				<a class="button button-secondary" href="<?php echo esc_url( admin_url( 'admin.php?page=pendid-ai-studio-create-image' ) ); ?>"><?php echo esc_html__( 'Open Create Image', 'pendid-ai-studio' ); ?></a>
			</div>
		</section>
		<?php
	}

	/**
	 * Stops rendering when the current user lacks permission.
	 *
	 * @return void
	 */
	private function require_admin_access() {
		if ( ! current_user_can( 'manage_options' ) ) {
			wp_die( esc_html__( 'You do not have permission to access this page.', 'pendid-ai-studio' ) );
		}
	}

	/**
	 * Returns whether the current screen is one of this plugin's admin pages.
	 *
	 * @return bool
	 */
	private function is_plugin_admin_page() {
		$page = sanitize_key( $this->get_scalar_input( INPUT_GET, 'page' ) );

		return in_array(
			$page,
			array(
				'pendid-ai-studio',
				'pendid-ai-studio-create-image',
				'pendid-ai-studio-settings',
			),
			true
		);
	}

	/**
	 * Builds the Pendid Studio connect URL.
	 *
	 * @return string
	 */
	private function get_connect_url() {
		if ( '' !== $this->connect_url ) {
			return $this->connect_url;
		}

		$state = wp_generate_password( 64, false, false );

		set_transient(
			$this->get_connection_state_transient_key(),
			hash( 'sha256', $state ),
			15 * MINUTE_IN_SECONDS
		);

		$this->connect_url = add_query_arg(
			array(
				'redirect_url' => admin_url( 'admin.php?page=pendid-ai-studio' ),
				'admin_url'    => admin_url(),
				'site_url'     => home_url(),
				'label'        => get_bloginfo( 'name' ),
				'locale'       => determine_locale(),
				'state'        => $state,
			),
			'https://studio.pendid.com/wp-connect'
		);

		return $this->connect_url;
	}

	/**
	 * Returns the current administrator's connection-state transient key.
	 *
	 * @return string
	 */
	private function get_connection_state_transient_key() {
		return 'pendid_ai_studio_connect_state_' . get_current_user_id();
	}

	/**
	 * Validates a one-time state value returned from Pendid Studio.
	 *
	 * @param string $state Returned connection state.
	 * @return bool
	 */
	private function is_valid_connection_state( $state ) {
		if ( ! is_string( $state ) || '' === $state || strlen( $state ) > 128 ) {
			return false;
		}

		$expected_hash = get_transient( $this->get_connection_state_transient_key() );

		if ( ! is_string( $expected_hash ) || '' === $expected_hash ) {
			return false;
		}

		return hash_equals( $expected_hash, hash( 'sha256', $state ) );
	}

	/**
	 * Redirects to a plugin admin page with a safe status argument.
	 *
	 * @param string $key   Query argument key.
	 * @param string $value Query argument value.
	 * @param string $page  Plugin page slug.
	 * @return void
	 */
	private function redirect_to_admin_page( $key, $value, $page = 'pendid-ai-studio' ) {
		$key   = sanitize_key( $key );
		$value = sanitize_key( $value );
		$page  = sanitize_key( $page );

		$allowed_pages = array(
			'pendid-ai-studio',
			'pendid-ai-studio-create-image',
			'pendid-ai-studio-settings',
		);

		if ( ! in_array( $page, $allowed_pages, true ) ) {
			$page = 'pendid-ai-studio';
		}

		wp_safe_redirect(
			add_query_arg(
				array(
					'page' => $page,
					$key   => $value,
				),
				admin_url( 'admin.php' )
			)
		);
		exit;
	}

	/**
	 * Returns one scalar request value without relying on a mutable superglobal.
	 *
	 * Values returned by filter_input() are the original request values, so callers
	 * must apply the sanitizer appropriate for the field before using the result.
	 *
	 * @param int    $input_type One of INPUT_GET or INPUT_POST.
	 * @param string $name       Request field name.
	 * @param string $default    Default value when the field is absent or not scalar.
	 * @return string
	 */
	private function get_scalar_input( $input_type, $name, $default = '' ) {
		$value = filter_input( $input_type, $name, FILTER_UNSAFE_RAW, FILTER_REQUIRE_SCALAR );

		if ( false === $value || null === $value || ! is_scalar( $value ) ) {
			return $default;
		}

		return (string) $value;
	}

	/**
	 * Gets a scalar account field from a list of possible keys.
	 *
	 * @param array<string, mixed> $account Account data.
	 * @param array<int, string>   $keys    Possible field keys.
	 * @return string
	 */
	private function get_account_value( $account, $keys ) {
		foreach ( $keys as $key ) {
			if ( isset( $account[ $key ] ) && is_scalar( $account[ $key ] ) ) {
				return sanitize_text_field( (string) $account[ $key ] );
			}
		}

		return '';
	}

	/**
	 * Returns the current generation error from the request.
	 *
	 * @return string
	 */
	private function get_requested_generation_error() {
		$error = sanitize_key( $this->get_scalar_input( INPUT_GET, 'pendid_error' ) );

		return in_array( $error, array( 'image_allowance_exhausted', 'image_plan_required' ), true ) ? $error : '';
	}

	/**
	 * Maps a safe Pendid generation failure reason to a WordPress UI state.
	 *
	 * @param string $reason Pendid API reason.
	 * @return string
	 */
	private function map_generation_failure_reason( $reason ) {
		$reason = sanitize_key( $reason );

		if ( in_array( $reason, array( 'monthly_ai_limit_reached', 'ai_usage_exhausted' ), true ) ) {
			return 'image_allowance_exhausted';
		}

		if ( in_array( $reason, array( 'ai_plan_expired', 'ai_plan_required', 'plan_required', 'ai_not_available_for_plan' ), true ) ) {
			return 'image_plan_required';
		}

		if ( in_array( $reason, array( 'invalid_token', 'missing_authorization', 'invalid_authorization' ), true ) ) {
			return 'connection_expired';
		}

		if ( 'prompt_required' === $reason || 'description_required' === $reason ) {
			return 'image_prompt_required';
		}

		if ( in_array( $reason, array( 'invalid_input_image', 'input_image_too_large', 'input_image_fetch_failed' ), true ) ) {
			return 'image_reference_invalid';
		}

		if ( 'edit_image_required' === $reason ) {
			return 'image_edit_source_missing';
		}

		if ( 'service_unavailable' === $reason ) {
			return 'service_unavailable';
		}

		if ( 'generation_unavailable' === $reason ) {
			return 'generation_unavailable';
		}

		return 'image_generation_failed';
	}

	/**
	 * Returns the current user's generation draft transient key.
	 *
	 * @return string
	 */
	private function get_generation_draft_transient_key() {
		return 'pendid_ai_studio_generation_draft_' . get_current_user_id();
	}

	/**
	 * Returns default generation form values.
	 *
	 * @return array{prompt:string,aspect_ratio:string,purpose:string,tone:string}
	 */
	private function get_default_generation_draft() {
		return array(
			'prompt'       => '',
			'aspect_ratio' => '1:1',
			'purpose'      => 'featured-image',
			'tone'         => 'حرفه‌ای',
		);
	}

	/**
	 * Stores the submitted generation form so it survives redirects and errors.
	 *
	 * @param string $prompt       Submitted prompt.
	 * @param string $aspect_ratio Submitted aspect ratio.
	 * @param string $purpose      Website image purpose.
	 * @param string $tone         Selected image mood.
	 * @return void
	 */
	private function save_generation_draft( $prompt, $aspect_ratio, $purpose, $tone ) {
		$purposes = $this->get_image_purposes();
		$tones    = $this->get_image_tones();

		set_transient(
			$this->get_generation_draft_transient_key(),
			array(
				'prompt'       => sanitize_textarea_field( (string) $prompt ),
				'aspect_ratio' => in_array( $aspect_ratio, array( '1:1', '3:2', '2:3' ), true ) ? $aspect_ratio : '1:1',
				'purpose'      => array_key_exists( $purpose, $purposes ) ? $purpose : 'featured-image',
				'tone'         => array_key_exists( $tone, $tones ) ? $tone : 'حرفه‌ای',
			),
			12 * HOUR_IN_SECONDS
		);
	}

	/**
	 * Returns the saved generation form values.
	 *
	 * @return array{prompt:string,aspect_ratio:string,purpose:string,tone:string}
	 */
	private function get_generation_draft() {
		$draft    = get_transient( $this->get_generation_draft_transient_key() );
		$defaults = $this->get_default_generation_draft();

		if ( ! is_array( $draft ) ) {
			return $defaults;
		}

		$aspect_ratio = isset( $draft['aspect_ratio'] ) && is_scalar( $draft['aspect_ratio'] ) ? sanitize_text_field( (string) $draft['aspect_ratio'] ) : $defaults['aspect_ratio'];
		$purpose      = isset( $draft['purpose'] ) && is_scalar( $draft['purpose'] ) ? sanitize_key( (string) $draft['purpose'] ) : $defaults['purpose'];
		$tone         = isset( $draft['tone'] ) && is_scalar( $draft['tone'] ) ? sanitize_text_field( (string) $draft['tone'] ) : $defaults['tone'];

		return array(
			'prompt'       => isset( $draft['prompt'] ) && is_scalar( $draft['prompt'] ) ? sanitize_textarea_field( (string) $draft['prompt'] ) : '',
			'aspect_ratio' => in_array( $aspect_ratio, array( '1:1', '3:2', '2:3' ), true ) ? $aspect_ratio : $defaults['aspect_ratio'],
			'purpose'      => array_key_exists( $purpose, $this->get_image_purposes() ) ? $purpose : $defaults['purpose'],
			'tone'         => array_key_exists( $tone, $this->get_image_tones() ) ? $tone : $defaults['tone'],
		);
	}

	/**
	 * Returns the current user's generation result transient key.
	 *
	 * @return string
	 */
	private function get_generation_result_transient_key() {
		return 'pendid_ai_studio_generation_result_' . get_current_user_id();
	}

	/**
	 * Returns the last generated image result for this admin user.
	 *
	 * @return array<string, mixed>
	 */
	private function get_generation_result() {
		$result = get_transient( $this->get_generation_result_transient_key() );

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

		return $this->sanitize_generation_result( $result );
	}

	/**
	 * Sanitizes a generated image result for temporary display.
	 *
	 * @param array<string, mixed> $image Image result.
	 * @return array<string, mixed>
	 */
	private function sanitize_generation_result( $image ) {
		return array(
			'url'              => isset( $image['url'] ) && is_scalar( $image['url'] ) ? esc_url_raw( (string) $image['url'] ) : '',
			'key'              => isset( $image['key'] ) && is_scalar( $image['key'] ) ? sanitize_text_field( (string) $image['key'] ) : '',
			'filename'         => isset( $image['filename'] ) && is_scalar( $image['filename'] ) ? sanitize_file_name( (string) $image['filename'] ) : '',
			'content_type'     => isset( $image['content_type'] ) && is_scalar( $image['content_type'] ) ? sanitize_text_field( (string) $image['content_type'] ) : '',
			'aspect_ratio'     => isset( $image['aspect_ratio'] ) && is_scalar( $image['aspect_ratio'] ) ? sanitize_text_field( (string) $image['aspect_ratio'] ) : '',
			'mode'             => isset( $image['mode'] ) && is_scalar( $image['mode'] ) ? sanitize_key( (string) $image['mode'] ) : 'generate',
			'purpose'          => isset( $image['purpose'] ) && is_scalar( $image['purpose'] ) ? sanitize_key( (string) $image['purpose'] ) : 'featured-image',
			'tone'             => isset( $image['tone'] ) && is_scalar( $image['tone'] ) ? sanitize_text_field( (string) $image['tone'] ) : 'حرفه‌ای',
			'prompt'           => isset( $image['prompt'] ) && is_scalar( $image['prompt'] ) ? sanitize_textarea_field( (string) $image['prompt'] ) : '',
			'last_edit_prompt' => isset( $image['last_edit_prompt'] ) && is_scalar( $image['last_edit_prompt'] ) ? sanitize_textarea_field( (string) $image['last_edit_prompt'] ) : '',
			'attachment_id'    => isset( $image['attachment_id'] ) ? absint( $image['attachment_id'] ) : 0,
			'attachment_url'   => isset( $image['attachment_url'] ) && is_scalar( $image['attachment_url'] ) ? esc_url_raw( (string) $image['attachment_url'] ) : '',
			'edit_link'        => isset( $image['edit_link'] ) && is_scalar( $image['edit_link'] ) ? esc_url_raw( (string) $image['edit_link'] ) : '',
		);
	}

	/**
	 * Returns website-oriented image purposes.
	 *
	 * @return array<string, array<string, string>>
	 */
	private function get_image_purposes() {
		return array(
			'featured-image'  => array( 'title' => __( 'Featured image', 'pendid-ai-studio' ), 'helper' => __( 'Posts and editorial covers', 'pendid-ai-studio' ) ),
			'article-image'   => array( 'title' => __( 'Article image', 'pendid-ai-studio' ), 'helper' => __( 'Visuals inside blog content', 'pendid-ai-studio' ) ),
			'hero-banner'     => array( 'title' => __( 'Hero or banner', 'pendid-ai-studio' ), 'helper' => __( 'Headers, sliders, and campaigns', 'pendid-ai-studio' ) ),
			'landing-page'    => array( 'title' => __( 'Landing page', 'pendid-ai-studio' ), 'helper' => __( 'Focused page and service visuals', 'pendid-ai-studio' ) ),
			'product-service' => array( 'title' => __( 'Product or service', 'pendid-ai-studio' ), 'helper' => __( 'Commercial showcase images', 'pendid-ai-studio' ) ),
		);
	}

	/**
	 * Returns available image moods and their optional preview assets.
	 *
	 * @return array<string, array<string, string>>
	 */
	private function get_image_tones() {
		return array(
			'حرفه‌ای'  => array( 'id' => 'professional', 'title' => __( 'Professional', 'pendid-ai-studio' ), 'helper' => __( 'Structured, trustworthy, and brand ready', 'pendid-ai-studio' ), 'file' => 'tone-professional.webp' ),
			'فروش‌محور' => array( 'id' => 'sales', 'title' => __( 'Sales focused', 'pendid-ai-studio' ), 'helper' => __( 'Clear, promotional, and conversion oriented', 'pendid-ai-studio' ), 'file' => 'tone-sales.webp' ),
			'لوکس'      => array( 'id' => 'luxury', 'title' => __( 'Luxury', 'pendid-ai-studio' ), 'helper' => __( 'Premium, refined, and calm', 'pendid-ai-studio' ), 'file' => 'tone-luxury.webp' ),
			'مدرن'      => array( 'id' => 'modern', 'title' => __( 'Modern', 'pendid-ai-studio' ), 'helper' => __( 'Current, clean, and digital', 'pendid-ai-studio' ), 'file' => 'tone-modern.webp' ),
			'مینیمال'   => array( 'id' => 'minimal', 'title' => __( 'Minimal', 'pendid-ai-studio' ), 'helper' => __( 'Bright, uncluttered, and spacious', 'pendid-ai-studio' ), 'file' => 'tone-minimal.webp' ),
			'صمیمی'     => array( 'id' => 'friendly', 'title' => __( 'Friendly', 'pendid-ai-studio' ), 'helper' => __( 'Warm, human, and approachable', 'pendid-ai-studio' ), 'file' => 'tone-friendly.webp' ),
			'شاد'       => array( 'id' => 'happy', 'title' => __( 'Bright and playful', 'pendid-ai-studio' ), 'helper' => __( 'Colorful, energetic, and lightweight', 'pendid-ai-studio' ), 'file' => 'tone-happy.webp' ),
		);
	}

	/**
	 * Renders a tone preview or a graceful placeholder when the custom image is missing.
	 *
	 * @param array<string, string> $tone_item Tone definition.
	 * @param string                $context   Visual context.
	 * @return void
	 */
	private function render_tone_visual( $tone_item, $context = 'card' ) {
		$file = isset( $tone_item['file'] ) ? sanitize_file_name( $tone_item['file'] ) : '';
		$path = PENDID_AI_STUDIO_PATH . 'assets/images/tones/' . $file;
		$url  = PENDID_AI_STUDIO_URL . 'assets/images/tones/' . $file;

		if ( $file && file_exists( $path ) ) {
			?><img src="<?php echo esc_url( $url ); ?>" alt="" aria-hidden="true"><?php
			return;
		}
		?>
		<span class="pendid-ai-studio-tone-placeholder is-<?php echo esc_attr( $context ); ?>" aria-hidden="true"><span class="dashicons dashicons-art"></span></span>
		<?php
	}

	/**
	 * Renders the accessible image mood picker.
	 *
	 * @param array<string, array<string, string>> $tones         Available tones.
	 * @param string                               $selected_tone Current value.
	 * @return void
	 */
	private function render_tone_modal( $tones, $selected_tone ) {
		?>
		<div id="pendid-ai-studio-tone-modal" class="pendid-ai-studio-modal pendid-ai-studio-tone-modal" hidden>
			<div class="pendid-ai-studio-modal-backdrop" data-pendid-modal-close></div>
			<section class="pendid-ai-studio-modal-dialog pendid-ai-studio-tone-dialog" role="dialog" aria-modal="true" aria-labelledby="pendid-ai-studio-tone-title" tabindex="-1">
				<button type="button" class="pendid-ai-studio-modal-close" data-pendid-modal-close aria-label="<?php echo esc_attr__( 'Close image mood dialog', 'pendid-ai-studio' ); ?>"><span class="dashicons dashicons-no-alt" aria-hidden="true"></span></button>
				<p class="pendid-ai-studio-eyebrow"><?php echo esc_html__( 'Website visual direction', 'pendid-ai-studio' ); ?></p>
				<h2 id="pendid-ai-studio-tone-title"><?php echo esc_html__( 'Choose the image mood', 'pendid-ai-studio' ); ?></h2>
				<p class="pendid-ai-studio-modal-description"><?php echo esc_html__( 'The mood guides composition, color, and visual energy. Your written prompt remains the main instruction.', 'pendid-ai-studio' ); ?></p>
				<div class="pendid-ai-studio-tone-grid">
					<?php foreach ( $tones as $tone_value => $tone_item ) : ?>
						<label class="pendid-ai-studio-tone-card<?php echo $selected_tone === $tone_value ? ' is-active' : ''; ?>" data-pendid-tone-card data-pendid-tone-value="<?php echo esc_attr( $tone_value ); ?>">
							<input type="radio" name="pendid_image_tone" value="<?php echo esc_attr( $tone_value ); ?>" form="pendid-ai-studio-generation-form" <?php checked( $selected_tone, $tone_value ); ?> data-pendid-tone-input data-pendid-tone-title="<?php echo esc_attr( $tone_item['title'] ); ?>">
							<span class="pendid-ai-studio-tone-card-image"><?php $this->render_tone_visual( $tone_item, 'card' ); ?></span>
							<span class="pendid-ai-studio-tone-card-copy"><strong><?php echo esc_html( $tone_item['title'] ); ?></strong><small><?php echo esc_html( $tone_item['helper'] ); ?></small></span>
						</label>
					<?php endforeach; ?>
				</div>
			</section>
		</div>
		<?php
	}

	/**
	 * Maps the user-facing website purpose and ratio to Studio prompt-builder values.
	 *
	 * @param string $purpose      Website image purpose.
	 * @param string $aspect_ratio Selected ratio.
	 * @return array{image_type:string,format:string}
	 */
	private function get_generation_request_config( $purpose, $aspect_ratio ) {
		$config = array(
			'featured-image'  => array( 'image_type' => 'intro-cover', '1:1' => 'intro-square', '3:2' => 'article-cover', '2:3' => 'instagram-story' ),
			'article-image'   => array( 'image_type' => 'intro-cover', '1:1' => 'intro-square', '3:2' => 'article-cover', '2:3' => 'instagram-story' ),
			'hero-banner'     => array( 'image_type' => 'website-banner', '1:1' => 'instagram-post', '3:2' => 'site-hero', '2:3' => 'instagram-story' ),
			'landing-page'    => array( 'image_type' => 'website-banner', '1:1' => 'instagram-post', '3:2' => 'landing-banner', '2:3' => 'instagram-story' ),
			'product-service' => array( 'image_type' => 'product-image', '1:1' => 'product-square', '3:2' => 'product-wide', '2:3' => 'product-story' ),
		);
		$item   = isset( $config[ $purpose ] ) ? $config[ $purpose ] : $config['featured-image'];

		return array(
			'image_type' => $item['image_type'],
			'format'     => isset( $item[ $aspect_ratio ] ) ? $item[ $aspect_ratio ] : $item['1:1'],
		);
	}

	/**
	 * Returns the maximum reference upload size supported by this plugin request.
	 *
	 * @return int
	 */
	private function get_reference_max_bytes() {
		$wp_limit = (int) wp_max_upload_size();
		$max      = 8 * MB_IN_BYTES;

		return $wp_limit > 0 ? min( $wp_limit, $max ) : $max;
	}

	/**
	 * Validates the optional reference image without adding it to the Media Library.
	 *
	 * @param array<string, mixed> $file Uploaded file data from the verified admin request.
	 * @return array<string, mixed>|WP_Error
	 */
	private function get_reference_upload( $file ) {
		if ( empty( $file ) ) {
			return array();
		}

		$error = isset( $file['error'] ) ? (int) $file['error'] : UPLOAD_ERR_NO_FILE;

		if ( UPLOAD_ERR_NO_FILE === $error ) {
			return array();
		}

		if ( UPLOAD_ERR_OK !== $error ) {
			return new WP_Error( 'pendid_reference_upload_failed', __( 'Reference image upload failed.', 'pendid-ai-studio' ) );
		}

		$tmp_name = isset( $file['tmp_name'] ) && is_scalar( $file['tmp_name'] ) ? (string) $file['tmp_name'] : '';
		$name     = isset( $file['name'] ) && is_scalar( $file['name'] ) ? sanitize_file_name( (string) $file['name'] ) : 'reference-image';
		$size     = isset( $file['size'] ) ? (int) $file['size'] : 0;

		if ( ! $tmp_name || ! is_uploaded_file( $tmp_name ) || $size < 1 || $size > $this->get_reference_max_bytes() ) {
			return new WP_Error( 'pendid_reference_invalid_size', __( 'Reference image size is invalid.', 'pendid-ai-studio' ) );
		}

		$mime    = function_exists( 'wp_get_image_mime' ) ? wp_get_image_mime( $tmp_name ) : '';
		$allowed = array( 'image/jpeg', 'image/png', 'image/webp' );

		if ( ! in_array( $mime, $allowed, true ) ) {
			return new WP_Error( 'pendid_reference_invalid_type', __( 'Reference image type is invalid.', 'pendid-ai-studio' ) );
		}

		return array(
			'path' => $tmp_name,
			'name' => $name,
			'type' => $mime,
			'size' => $size,
		);
	}

	/**
	 * Saves a generated Pendid image to the WordPress Media Library.
	 *
	 * @param array<string, mixed> $image  Image result.
	 * @param string               $prompt User-submitted image description.
	 * @return array<string, mixed>|WP_Error
	 */
	private function save_image_to_media_library( $image, $prompt ) {
		$url = isset( $image['url'] ) && is_scalar( $image['url'] ) ? esc_url_raw( (string) $image['url'] ) : '';

		if ( ! $this->is_allowed_pendid_media_url( $url ) ) {
			return new WP_Error( 'pendid_invalid_media_url', __( 'Invalid generated image URL.', 'pendid-ai-studio' ) );
		}

		require_once ABSPATH . 'wp-admin/includes/file.php';
		require_once ABSPATH . 'wp-admin/includes/media.php';
		require_once ABSPATH . 'wp-admin/includes/image.php';

		$tmp = download_url( $url );

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

		$filename         = $this->build_prompt_filename( $prompt, $image );
		$attachment_title = $this->build_attachment_title( $prompt );
		$attachment_alt   = $this->build_attachment_alt( $prompt );

		$file_array = array(
			'name'     => $filename,
			'tmp_name' => $tmp,
		);

		if ( ! empty( $image['content_type'] ) ) {
			$file_array['type'] = sanitize_text_field( (string) $image['content_type'] );
		}

		$attachment_id = media_handle_sideload(
			$file_array,
			0,
			null,
			array(
				'post_title'   => $attachment_title,
				'post_content' => '',
				'post_excerpt' => '',
			)
		);

		if ( is_wp_error( $attachment_id ) ) {
			if ( file_exists( $tmp ) ) {
				wp_delete_file( $tmp );
			}

			return $attachment_id;
		}

		if ( '' !== $attachment_alt ) {
			update_post_meta( $attachment_id, '_wp_attachment_image_alt', $attachment_alt );
		}

		$attachment_url = wp_get_attachment_url( $attachment_id );
		$edit_link      = get_edit_post_link( $attachment_id, '' );

		return array(
			'attachment_id'  => absint( $attachment_id ),
			'attachment_url' => is_string( $attachment_url ) ? esc_url_raw( $attachment_url ) : '',
			'edit_link'      => is_string( $edit_link ) ? esc_url_raw( $edit_link ) : '',
		);
	}

	/**
	 * Determines whether a URL is an allowed Pendid media URL.
	 *
	 * @param string $url URL to validate.
	 * @return bool
	 */
	private function is_allowed_pendid_media_url( $url ) {
		if ( ! wp_http_validate_url( $url ) ) {
			return false;
		}

		$parts  = wp_parse_url( $url );
		$scheme = isset( $parts['scheme'] ) ? strtolower( $parts['scheme'] ) : '';
		$host   = isset( $parts['host'] ) ? strtolower( $parts['host'] ) : '';

		return in_array( $scheme, array( 'http', 'https' ), true ) && 'media.pendid.com' === $host;
	}

	/**
	 * Builds a clean prompt-based filename for the generated attachment.
	 *
	 * @param string               $prompt User-submitted image description.
	 * @param array<string, mixed> $image  Image result.
	 * @return string
	 */
	private function build_prompt_filename( $prompt, $image ) {
		$plain = trim( wp_strip_all_tags( (string) $prompt ) );
		$slug  = preg_replace( '/[^\p{L}\p{N}]+/u', '-', remove_accents( $plain ) );
		$slug  = is_string( $slug ) ? trim( $slug, '-' ) : '';

		if ( function_exists( 'mb_strtolower' ) ) {
			$slug = mb_strtolower( $slug, 'UTF-8' );
		} else {
			$slug = strtolower( $slug );
		}

		if ( function_exists( 'mb_substr' ) ) {
			$slug = mb_substr( $slug, 0, 70, 'UTF-8' );
		} else {
			$slug = substr( $slug, 0, 70 );
		}

		$slug = sanitize_file_name( $slug );

		if ( '' === $slug ) {
			$slug = 'pendid-image';
		}

		$extension = $this->get_extension_from_content_type( isset( $image['content_type'] ) ? $image['content_type'] : '' );

		return sanitize_file_name( $slug . '-' . gmdate( 'Ymd-His' ) . '.' . $extension );
	}

	/**
	 * Builds a concise WordPress attachment title from the prompt.
	 *
	 * @param string $prompt User-submitted image description.
	 * @return string
	 */
	private function build_attachment_title( $prompt ) {
		$title = trim( sanitize_text_field( (string) $prompt ) );
		$title = wp_html_excerpt( $title, 120, '' );

		return '' !== $title ? $title : __( 'Pendid AI image', 'pendid-ai-studio' );
	}

	/**
	 * Builds accessible image alternative text from the prompt.
	 *
	 * @param string $prompt User-submitted image description.
	 * @return string
	 */
	private function build_attachment_alt( $prompt ) {
		$alt = trim( sanitize_text_field( (string) $prompt ) );

		return wp_html_excerpt( $alt, 250, '' );
	}

	/**
	 * Gets a safe filename for a generated image URL.
	 *
	 * @param string               $url   Image URL.
	 * @param array<string, mixed> $image Image result.
	 * @return string
	 */
	private function get_filename_from_url( $url, $image ) {
		$path     = wp_parse_url( $url, PHP_URL_PATH );
		$filename = sanitize_file_name( basename( (string) $path ) );

		if ( $filename && false !== strpos( $filename, '.' ) ) {
			return $filename;
		}

		return 'pendid-image.' . $this->get_extension_from_content_type( isset( $image['content_type'] ) ? $image['content_type'] : '' );
	}

	/**
	 * Gets a file extension from a content type.
	 *
	 * @param string $content_type Content type.
	 * @return string
	 */
	private function get_extension_from_content_type( $content_type ) {
		$content_type = strtolower( (string) $content_type );

		if ( false !== strpos( $content_type, 'png' ) ) {
			return 'png';
		}

		if ( false !== strpos( $content_type, 'jpeg' ) || false !== strpos( $content_type, 'jpg' ) ) {
			return 'jpg';
		}

		if ( false !== strpos( $content_type, 'webp' ) ) {
			return 'webp';
		}

		return 'png';
	}
}
