<?php
/**
 * Admin handler.
 *
 * Registers admin menus, pages, and enqueues admin-specific assets.
 * Uses Inertia.js for rendering admin page components.
 *
 * @package Antimanual_Builder
 * @since   1.0.0
 */

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

/**
 * Class AMBLD_Admin_Admin
 *
 * Handles all WordPress admin functionality for the plugin.
 *
 * @since 1.0.0
 */
class AMBLD_Admin_Admin {

	/**
	 * Editor page handler.
	 *
	 * @since 1.0.0
	 * @var   AMBLD_Admin_Editor_Page
	 */
	private $editor_page;

	/**
	 * Settings page handler.
	 *
	 * @since 1.0.0
	 * @var   AMBLD_Admin_Settings_Page
	 */
	private $settings_page;

	/**
	 * Constructor. Sets up admin hooks.
	 *
	 * @since 1.0.0
	 */
	public function __construct() {
		$this->editor_page   = new AMBLD_Admin_Editor_Page();
		$this->settings_page = new AMBLD_Admin_Settings_Page();

		add_action( 'admin_menu', array( $this, 'register_menus' ) );
		add_action( 'admin_enqueue_scripts', array( $this, 'enqueue_menu_icon_styles' ) );
		add_action( 'admin_enqueue_scripts', array( $this, 'enqueue_admin_assets' ) );
		add_action( 'admin_enqueue_scripts', array( $this, 'enqueue_migrate_launcher' ) );
		add_action( 'enqueue_block_editor_assets', array( $this, 'enqueue_page_editor_assets' ) );
		add_action( 'edit_form_after_title', array( $this, 'render_classic_editor_button' ) );

		// Handle Inertia XHR requests early, before WP renders any HTML.
		add_action( 'admin_init', array( $this, 'handle_inertia_request' ), 1 );

		// Add builder link to native pages.
		add_filter( 'page_row_actions', array( $this, 'add_builder_row_action' ), 10, 2 );

		// Add "AM Builder" post state badge in the pages list.
		add_filter( 'display_post_states', array( $this, 'add_builder_post_state' ), 10, 2 );

		// Set Inertia asset version.
		AMBLD_Admin_Inertia::version( AMBLD_VERSION );

		// Defer shared props setup to admin_init (rest_url requires $wp_rewrite).
		add_action( 'admin_init', array( $this, 'setup_shared_props' ), 0 );

		// Suppress all admin notices on AM Builder pages.
		add_action( 'admin_init', array( $this, 'suppress_admin_notices' ) );
	}

	/**
	 * Remove all admin notices on AM Builder admin pages.
	 *
	 * Unhooks the standard notice action hooks so that third-party plugin
	 * notices, core update notices, and theme notices do not appear inside
	 * the builder's React-rendered UI.
	 *
	 * @since  1.0.0
	 * @return void
	 */
	public function suppress_admin_notices() {
		if ( ! $this->is_plugin_page() ) {
			return;
		}

		remove_all_actions( 'admin_notices' );
		remove_all_actions( 'all_admin_notices' );
		remove_all_actions( 'user_admin_notices' );
		remove_all_actions( 'network_admin_notices' );
	}

	/**
	 * Check whether the current screen belongs to AM Builder.
	 *
	 * @since  1.0.0
	 * @return bool
	 */
	private function is_plugin_page() {
		// phpcs:ignore WordPress.Security.NonceVerification.Recommended
		$page = isset( $_GET['page'] ) ? sanitize_key( wp_unslash( $_GET['page'] ) ) : '';

		$plugin_pages = array(
			'ambld-dashboard',
			'ambld-components',
			'ambld-templates',
			'ambld-html-import',
			'ambld-settings',
			'ambld-editor',
		);

		return in_array( $page, $plugin_pages, true );
	}

	/**
	 * Setup shared Inertia props available to all admin pages.
	 *
	 * @since  1.0.0
	 * @return void
	 */
	public function setup_shared_props() {
		$ai_settings     = AMBLD_Antimanual_Ai_Provider::get_settings_payload();
		$design_defaults = get_option( 'ambld_design_defaults', array() );
		$custom_presets  = get_option( 'ambld_custom_presets', array() );

		AMBLD_Admin_Inertia::share( array(
			'restUrl'    => esc_url_raw( rest_url( 'ambld/v1/' ) ),
			'nonce'      => wp_create_nonce( 'wp_rest' ),
			'adminUrl'   => esc_url( admin_url() ),
			'pluginUrl'  => esc_url( AMBLD_PLUGIN_URL ),
			'version'    => AMBLD_VERSION,
			// Pro gating: unlocks Pro-only admin UI (e.g. HTML Import) and
			// supplies the upgrade CTA target when locked.
			'isPro'      => ambld_is_pro(),
			'upgradeUrl' => esc_url_raw( ambld_pro_upgrade_url() ),
			// esc_url_raw, not esc_url: these are JSON props consumed by React,
			// and esc_url's &#038; entity turns the query string into a fragment.
			'editorUrl'  => esc_url_raw( admin_url( 'admin.php?page=ambld-editor' ) ),
			'componentEditorUrl' => esc_url_raw( admin_url( 'admin.php?page=ambld-editor&entity_type=' . rawurlencode( AMBLD_Post_Type_Builder_Component::POST_TYPE ) ) ),
			'templateEditorUrl'  => esc_url_raw( admin_url( 'admin.php?page=ambld-editor&entity_type=' . rawurlencode( AMBLD_Post_Type_Builder_Template::POST_TYPE ) ) ),
			'antimanualKnowledgeBase' => AMBLD_Antimanual_Knowledge_Base::get_payload(),
			'aiSettings' => $ai_settings,
			'designDefaults' => $design_defaults,
			'customPresets'  => is_array( $custom_presets ) ? $custom_presets : array(),
			'migrationBehavior' => get_option( 'ambld_migration_behavior', 'duplicate' ),
			'aiBudget'          => AMBLD_API_Ai_Api::get_ai_budget(),
		) );
	}

	/**
	 * Handle Inertia XHR requests.
	 *
	 * Intercepts Inertia requests before WordPress renders any admin chrome,
	 * and returns JSON responses conforming to the Inertia protocol.
	 *
	 * @since  1.0.0
	 * @return void
	 */
	public function handle_inertia_request() {
		if ( ! AMBLD_Admin_Inertia::is_inertia_request() ) {
			return;
		}

		// phpcs:ignore WordPress.Security.NonceVerification.Recommended
		$page_slug = isset( $_GET['page'] ) ? sanitize_text_field( wp_unslash( $_GET['page'] ) ) : '';

		$page_map = array(
			'ambld-dashboard'  => 'Dashboard',
			'ambld-components' => 'Components',
			'ambld-templates'  => 'Templates',
			'ambld-html-import' => 'HtmlImport',
			'ambld-settings'   => 'Settings',
		);

		if ( ! isset( $page_map[ $page_slug ] ) ) {
			return;
		}

		$this->setup_shared_props();
		AMBLD_Admin_Inertia::render( $page_map[ $page_slug ] );
	}

	/**
	 * Register admin menu pages.
	 *
	 * @since  1.0.0
	 * @return void
	 */
	public function register_menus() {
		// Main menu page — Dashboard/Pages listing.
		add_menu_page(
			__( 'Antimanual Builder', 'antimanual-builder' ),
			__( 'AM Builder', 'antimanual-builder' ),
			'edit_pages',
			'ambld-dashboard',
			array( $this, 'render_admin_page' ),
			AMBLD_PLUGIN_URL . 'assets/images/logo.png',
			30
		);

		// Submenu: All Pages.
		add_submenu_page(
			'ambld-dashboard',
			__( 'All Pages', 'antimanual-builder' ),
			__( 'All Pages', 'antimanual-builder' ),
			'edit_pages',
			'ambld-dashboard',
			array( $this, 'render_admin_page' )
		);

		// Submenu: Component Library.
		add_submenu_page(
			'ambld-dashboard',
			__( 'Components', 'antimanual-builder' ),
			__( 'Components', 'antimanual-builder' ),
			'edit_pages',
			'ambld-components',
			array( $this, 'render_admin_page' )
		);

		// Submenu: HTML Import. Pro-only — kept visible with a "Pro" badge for
		// discovery; the page itself shows a locked upsell until Pro is active.
		$html_import_title = __( 'HTML Import', 'antimanual-builder' );
		if ( ! ambld_is_pro() ) {
			$html_import_title .= ' <span class="awaiting-mod ambld-pro-badge">' . esc_html__( 'Pro', 'antimanual-builder' ) . '</span>';
		}
		add_submenu_page(
			'ambld-dashboard',
			__( 'HTML Import', 'antimanual-builder' ),
			$html_import_title,
			'edit_pages',
			'ambld-html-import',
			array( $this, 'render_admin_page' )
		);

		// Submenu: Templates.
		add_submenu_page(
			'ambld-dashboard',
			__( 'Templates', 'antimanual-builder' ),
			__( 'Templates', 'antimanual-builder' ),
			'edit_pages',
			'ambld-templates',
			array( $this, 'render_admin_page' )
		);

		// Submenu: Settings.
		add_submenu_page(
			'ambld-dashboard',
			__( 'Settings', 'antimanual-builder' ),
			__( 'Settings', 'antimanual-builder' ),
			'manage_options',
			'ambld-settings',
			array( $this, 'render_admin_page' )
		);

		// Hidden: Editor page (full-screen, no admin chrome).
		add_submenu_page(
			'',
			__( 'Editor', 'antimanual-builder' ),
			__( 'Editor', 'antimanual-builder' ),
			'edit_pages',
			'ambld-editor',
			array( $this->editor_page, 'render' )
		);
	}

	/**
	 * Render an admin page using Inertia.
	 *
	 * Maps the current page slug to an Inertia component name
	 * and renders the initial page load with data-page attribute.
	 *
	 * @since  1.0.0
	 * @return void
	 */
	public function render_admin_page() {
		// phpcs:ignore WordPress.Security.NonceVerification.Recommended
		$page_slug = isset( $_GET['page'] ) ? sanitize_text_field( wp_unslash( $_GET['page'] ) ) : 'ambld-dashboard';

		$page_map = array(
			'ambld-dashboard'  => 'Dashboard',
			'ambld-components' => 'Components',
			'ambld-templates'  => 'Templates',
			'ambld-html-import' => 'HtmlImport',
			'ambld-settings'   => 'Settings',
		);

		$component = isset( $page_map[ $page_slug ] ) ? $page_map[ $page_slug ] : 'Dashboard';
		AMBLD_Admin_Inertia::render( $component );
	}


	/**
	 * Enqueue admin-specific assets.
	 *
	 * Only loads on Antimanual Builder admin pages (not the editor).
	 *
	 * @since  1.0.0
	 * @param  string $hook_suffix The current admin page hook suffix.
	 * @return void
	 */
	public function enqueue_admin_assets( $hook_suffix ) {
		// Only enqueue on our admin pages (skip the editor — it has its own assets).
		$admin_pages = array(
			'toplevel_page_ambld-dashboard',
			'am-builder_page_ambld-components',
			'am-builder_page_ambld-html-import',
			'am-builder_page_ambld-templates',
			'am-builder_page_ambld-settings',
		);

		if ( ! in_array( $hook_suffix, $admin_pages, true ) ) {
			return;
		}

		$asset_file = AMBLD_PLUGIN_DIR . 'build/admin.asset.php';
		$asset      = file_exists( $asset_file ) ? require $asset_file : array(
			'dependencies' => array(),
			'version'      => AMBLD_VERSION,
		);

		wp_enqueue_style(
			'ambld-admin',
			AMBLD_PLUGIN_URL . 'build/admin.css',
			array(),
			$asset['version']
		);

		wp_enqueue_script(
			'ambld-admin',
			AMBLD_PLUGIN_URL . 'build/admin.js',
			$asset['dependencies'],
			$asset['version'],
			true
		);
	}

	/**
	 * Enqueue the migrate launcher on the Pages list and classic editor.
	 *
	 * These screens render "Edit with AM Builder" entry points for pages that
	 * still need migrating (flagged with data-amb-migrate). The launcher
	 * intercepts those clicks to show the copy/replace guide before navigating
	 * to the builder editor. The block editor uses its own launch button, so
	 * it is skipped here.
	 *
	 * @since  1.0.0
	 * @param  string $hook_suffix Current admin page hook.
	 * @return void
	 */
	public function enqueue_migrate_launcher( $hook_suffix ) {
		// Pages list (edit.php) and classic editor (post.php / post-new.php).
		if ( ! in_array( $hook_suffix, array( 'edit.php', 'post.php', 'post-new.php' ), true ) ) {
			return;
		}

		$screen = get_current_screen();
		if ( ! $screen || AMBLD_Page_Integration::POST_TYPE !== $screen->post_type ) {
			return;
		}

		// The block editor renders its own launch button (page-editor bundle).
		if ( method_exists( $screen, 'is_block_editor' ) && $screen->is_block_editor() ) {
			return;
		}

		$asset_file = AMBLD_PLUGIN_DIR . 'build/migrate-launch.asset.php';
		$asset      = file_exists( $asset_file ) ? require $asset_file : array(
			'dependencies' => array( 'wp-components', 'wp-dom-ready', 'wp-element', 'wp-i18n' ),
			'version'      => AMBLD_VERSION,
		);

		wp_enqueue_script(
			'ambld-migrate-launch',
			AMBLD_PLUGIN_URL . 'build/migrate-launch.js',
			$asset['dependencies'],
			$asset['version'],
			true
		);

		// The choice modal is built on @wordpress/components, which needs its
		// stylesheet — not guaranteed to be present on the Pages list screen.
		wp_enqueue_style( 'wp-components' );

		$style_file = AMBLD_PLUGIN_DIR . 'build/migrate-launch.css';
		if ( file_exists( $style_file ) ) {
			wp_enqueue_style(
				'ambld-migrate-launch',
				AMBLD_PLUGIN_URL . 'build/migrate-launch.css',
				array( 'wp-components' ),
				$asset['version']
			);
		}

		wp_add_inline_script(
			'ambld-migrate-launch',
			'window.ambMigrateLaunch = ' . wp_json_encode(
				array(
					'defaultBehavior' => get_option( 'ambld_migration_behavior', 'duplicate' ),
				)
			) . ';',
			'before'
		);
	}

	/**
	 * Enqueue consistent sizing for the custom admin menu icon.
	 *
	 * @since  1.0.0
	 * @return void
	 */
	public function enqueue_menu_icon_styles() {
		wp_register_style( 'ambld-admin-global', false, array(), AMBLD_VERSION );
		wp_enqueue_style( 'ambld-admin-global' );
		wp_add_inline_style(
			'ambld-admin-global',
			'#toplevel_page_ambld-dashboard .wp-menu-image img {
				width: 18px;
				height: 18px;
				padding-top: 8px;
				opacity: 1;
			}'
		);
	}

	/**
	 * Enqueue the Gutenberg page editor launcher.
	 *
	 * @since  1.0.0
	 * @return void
	 */
	public function enqueue_page_editor_assets() {
		$screen = get_current_screen();
		$post   = $this->get_current_admin_page_post();

		if ( ! $screen || ! $post || AMBLD_Page_Integration::POST_TYPE !== $screen->post_type ) {
			return;
		}

		if ( method_exists( $screen, 'is_block_editor' ) && ! $screen->is_block_editor() ) {
			return;
		}

		$action = $this->get_page_builder_action( $post );
		if ( 'none' === $action ) {
			return;
		}

		$asset_file = AMBLD_PLUGIN_DIR . 'build/page-editor.asset.php';
		$asset      = file_exists( $asset_file ) ? require $asset_file : array(
			'dependencies' => array(
				'wp-components',
				'wp-data',
				'wp-dom-ready',
				'wp-element',
				'wp-i18n',
			),
			'version'      => AMBLD_VERSION,
		);

		wp_enqueue_script(
			'ambld-page-editor',
			AMBLD_PLUGIN_URL . 'build/page-editor.js',
			$asset['dependencies'],
			$asset['version'],
			true
		);

		$style_file = AMBLD_PLUGIN_DIR . 'build/page-editor.css';
		if ( file_exists( $style_file ) ) {
			wp_enqueue_style(
				'ambld-page-editor',
				AMBLD_PLUGIN_URL . 'build/page-editor.css',
				array( 'wp-edit-blocks' ),
				$asset['version']
			);
		}

		wp_add_inline_script(
			'ambld-page-editor',
			'window.ambPageEditorConfig = ' . wp_json_encode(
				array(
					'editorBaseUrl'   => $this->get_builder_editor_url(),
					'action'          => $action,
					'defaultBehavior' => get_option( 'ambld_migration_behavior', 'duplicate' ),
				)
			) . ';',
			'before'
		);
	}

	/**
	 * Render a fallback button for the classic page editor.
	 *
	 * @since  1.0.0
	 * @param  WP_Post $post Current post.
	 * @return void
	 */
	public function render_classic_editor_button( $post ) {
		if ( ! ( $post instanceof \WP_Post ) || AMBLD_Page_Integration::POST_TYPE !== $post->post_type ) {
			return;
		}

		if ( function_exists( 'use_block_editor_for_post' ) && use_block_editor_for_post( $post ) ) {
			return;
		}

		if ( ! current_user_can( 'edit_post', $post->ID ) ) {
			return;
		}

		$action = $this->get_page_builder_action( $post );
		if ( 'none' === $action ) {
			return;
		}

		$url   = $this->get_builder_editor_url( $post->ID, $action );
		$label = esc_html__( 'Edit with AM Builder', 'antimanual-builder' );
		// Migratable pages: flag the link so the launcher intercepts the click
		// and shows the copy/replace guide before navigating.
		$migrate_attrs = 'migrate' === $action
			? sprintf( ' data-amb-migrate="1" data-amb-page-title="%s"', esc_attr( $post->post_title ) )
			: '';
		?>
		<div class="ambld-classic-editor-launch" style="margin: 16px 0 20px;">
			<a href="<?php echo esc_url( $url ); ?>" class="button button-primary button-large"<?php echo $migrate_attrs; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped -- pre-escaped above. ?>>
				<?php echo $label; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped ?>
			</a>
		</div>
		<?php
	}

	/**
	 * Render the builder Knowledge Base handoff screen.
	 *
	 * Redirects to Antimanual when available, otherwise shows a short
	 * dependency message and next step.
	 *
	 * @since  1.0.0
	 * @return void
	 */
	public function render_antimanual_knowledge_base_page() {
		if ( AMBLD_Antimanual_Knowledge_Base::is_available() ) {
			wp_safe_redirect( AMBLD_Antimanual_Knowledge_Base::get_admin_url() );
			exit;
		}

		$message    = AMBLD_Antimanual_Knowledge_Base::get_status_message();
		$action_url = AMBLD_Antimanual_Knowledge_Base::is_installed()
			? admin_url( 'admin.php?page=antimanual' )
			: admin_url( 'plugins.php' );
		$action_label = AMBLD_Antimanual_Knowledge_Base::is_installed()
			? __( 'Open Antimanual', 'antimanual-builder' )
			: __( 'Manage Plugins', 'antimanual-builder' );
		?>
		<div class="wrap">
			<h1><?php esc_html_e( 'Knowledge Base', 'antimanual-builder' ); ?></h1>
			<p><?php echo esc_html( $message ); ?></p>
			<p>
				<a href="<?php echo esc_url( $action_url ); ?>" class="button button-primary">
					<?php echo esc_html( $action_label ); ?>
				</a>
			</p>
		</div>
		<?php
	}

	/**
	 * Get the editor page handler.
	 *
	 * @since  1.0.0
	 * @return AMBLD_Admin_Editor_Page
	 */
	public function get_editor_page() {
		return $this->editor_page;
	}

	/**
	 * Add "Edit with AM Builder" link to row actions.
	 *
	 * @since  1.0.0
	 * @param  array   $actions Row actions.
	 * @param  WP_Post $post    Current post object.
	 * @return array
	 */
	public function add_builder_row_action( $actions, $post ) {
		if ( AMBLD_Page_Integration::POST_TYPE !== $post->post_type || ! current_user_can( 'edit_post', $post->ID ) ) {
			return $actions;
		}

		$action = $this->get_page_builder_action( $post );
		if ( 'none' === $action ) {
			return $actions;
		}

		$url = $this->get_builder_editor_url( $post->ID, $action );

		// Both entry points read "Edit with AM Builder". For pages that still
		// need migrating, the link is flagged with data-amb-migrate so the
		// launcher script intercepts the click and shows the copy/replace
		// guide BEFORE navigating to the editor.
		$label = esc_html__( 'Edit with AM Builder', 'antimanual-builder' );
		$migrate_attrs = 'migrate' === $action
			? sprintf( ' data-amb-migrate="1" data-amb-page-title="%s"', esc_attr( $post->post_title ) )
			: '';

		$actions['ambld_editor'] = sprintf(
				'<a href="%s" style="color: #6366f1; font-weight: 600;"%s>%s</a>',
				esc_url( $url ),
				$migrate_attrs, // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped -- pre-escaped above.
				$label
			);

		return $actions;
	}

	/**
	 * Add "AM Builder" post state to pages managed by the builder.
	 *
	 * @since  1.0.0
	 * @param  array   $post_states Existing post states.
	 * @param  WP_Post $post        Current post object.
	 * @return array
	 */
	public function add_builder_post_state( $post_states, $post ) {
		if ( AMBLD_Page_Integration::POST_TYPE !== $post->post_type ) {
			return $post_states;
		}

		if ( AMBLD_Page_Integration::is_builder_page( $post ) ) {
			$post_states['ambld_builder'] = esc_html__( 'AM Builder', 'antimanual-builder' );
		}

		return $post_states;
	}

	/**
	 * Build the admin URL for launching the AM Builder editor.
	 *
	 * @since  1.0.0
	 * @param  int $post_id Optional post ID.
	 * @return string
	 */
	private function get_builder_editor_url( $post_id = 0, $action = 'edit' ) {
		$url = admin_url( 'admin.php?page=ambld-editor' );

		if ( ! empty( $post_id ) ) {
			$url = add_query_arg( 'post_id', absint( $post_id ), $url );
		}

		if ( 'migrate' === $action ) {
			$url = add_query_arg( 'ambld_action', 'migrate', $url );
		}

		return $url;
	}

	/**
	 * Determine which builder action should be shown for a page.
	 *
	 * @since  1.0.0
	 * @param  WP_Post $post Page post object.
	 * @return string `edit`, `migrate`, or `none`.
	 */
	private function get_page_builder_action( $post ) {
		if ( ! ( $post instanceof \WP_Post ) ) {
			return 'none';
		}

		if ( AMBLD_Page_Integration::is_builder_page( $post ) ) {
			return 'edit';
		}

		if ( AMBLD_Page_Integration::has_migratable_content( $post ) ) {
			return 'migrate';
		}

		return 'none';
	}

	/**
	 * Resolve the current page post in the admin editor context.
	 *
	 * @since  1.0.0
	 * @return WP_Post|null
	 */
	private function get_current_admin_page_post() {
		global $post;

		if ( $post instanceof \WP_Post ) {
			return $post;
		}

		// phpcs:ignore WordPress.Security.NonceVerification.Recommended
		$post_id = isset( $_GET['post'] ) ? absint( $_GET['post'] ) : 0;
		if ( ! $post_id ) {
			return null;
		}

		$current_post = get_post( $post_id );

		return $current_post instanceof \WP_Post ? $current_post : null;
	}

}
