<?php
/**
 * Role Assignments Admin Page
 *
 * Handles the Role Assignments admin page render and its AJAX save handler.
 *
 * @package Agency_Pulse_Admin_Menu
 * @since   1.0.0
 */

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

class Agency_Pulse_Admin_Menu_Role_Assignments {

	/**
	 * @var Agency_Pulse_Admin_Menu_Settings_Manager
	 */
	private $settings_manager;

	/**
	 * @param Agency_Pulse_Admin_Menu_Settings_Manager $settings_manager
	 */
	public function __construct( Agency_Pulse_Admin_Menu_Settings_Manager $settings_manager ) {
		$this->settings_manager = $settings_manager;
	}

	// -------------------------------------------------------------------------
	// Admin page rendering
	// -------------------------------------------------------------------------

	/**
	 * Render the Role Assignments admin page.
	 *
	 * Supplies the template with all named configurations, all registered
	 * WordPress roles, and the current role-to-config assignment map.
	 *
	 * @since 1.0.0
	 */
	public function render_page(): void {
		if ( ! current_user_can( Agency_Pulse_Admin_Menu_Constants::CAP_MANAGE_MENUS ) ) {
			wp_die( esc_html__( 'You do not have permission to access this page.', 'agency-pulse-admin-menu' ) );
		}

		$all_configs = $this->settings_manager->get_all_configs();
		$all_roles   = wp_roles()->get_names();
		$assignments = $this->settings_manager->get_role_assignments();

		include AGENCY_PULSE_ADMIN_MENU_DIR . 'templates/admin-role-assignments.php';
	}

	// -------------------------------------------------------------------------
	// AJAX handler
	// -------------------------------------------------------------------------

	/**
	 * AJAX: Save the role-to-config assignment map.
	 *
	 * Accepts a JSON-encoded object of role_slug => config_id pairs.
	 * Each entry is validated — role slug must be a real WordPress role, config ID
	 * must exist in the saved configurations. Invalid entries are silently dropped.
	 * An empty map is valid and means all roles see the unmodified WordPress menu.
	 *
	 * @since 1.0.0
	 */
	public function ajax_save_role_assignments(): void {
		check_ajax_referer( Agency_Pulse_Admin_Menu_Constants::AJAX_SAVE_ASSIGNMENTS, 'nonce' );
		if ( ! current_user_can( Agency_Pulse_Admin_Menu_Constants::CAP_MANAGE_MENUS ) ) {
			wp_send_json_error( array( 'message' => __( 'Insufficient permissions.', 'agency-pulse-admin-menu' ) ), 403 );
		}

		$raw_json = isset( $_POST['assignments'] ) ? wp_unslash( $_POST['assignments'] ) : ''; // phpcs:ignore WordPress.Security.ValidatedSanitizedInput
		$raw_map  = json_decode( $raw_json, true );

		if ( ! is_array( $raw_map ) ) {
			wp_send_json_error( array( 'message' => __( 'Invalid assignments data.', 'agency-pulse-admin-menu' ) ) );
		}

		$valid_role_slugs = array_keys( wp_roles()->get_names() );
		$all_configs      = $this->settings_manager->get_all_configs();
		$validated        = array();

		foreach ( $raw_map as $role_slug => $config_id ) {
			$role_slug = sanitize_key( (string) $role_slug );
			$config_id = sanitize_key( (string) $config_id );

			if ( ! in_array( $role_slug, $valid_role_slugs, true ) ) {
				continue;
			}
			if ( ! isset( $all_configs[ $config_id ] ) ) {
				continue;
			}

			$validated[ $role_slug ] = $config_id;
		}

		if ( $this->settings_manager->save_role_assignments( $validated ) ) {
			wp_send_json_success( array( 'message' => __( 'Assignments saved.', 'agency-pulse-admin-menu' ) ) );
		} else {
			wp_send_json_error( array( 'message' => __( 'Could not save assignments.', 'agency-pulse-admin-menu' ) ) );
		}
	}
}
