<?php
/**
 * Shois Chat Button — REST API
 *
 * Registers all REST API endpoints under the shois-chat/v1 namespace.
 *
 * @package ShoisChatButton
 */

// Prevent direct access.
if ( ! defined( 'ABSPATH' ) ) {
	exit;
}

/**
 * Class SHCB_Rest_API
 *
 * Handles all REST API route registrations and callbacks.
 */
class SHCB_Rest_API {

	/**
	 * Initialize REST routes.
	 *
	 * @return void
	 */
	public static function init() {
		add_action( 'rest_api_init', array( __CLASS__, 'register_routes' ) );
	}

	/**
	 * Register all plugin REST routes.
	 *
	 * @return void
	 */
	public static function register_routes() {

		// ── Templates ──────────────────────────────────────────────
		register_rest_route(
			SHCB_REST_NAMESPACE,
			'/templates',
			array(
				array(
					'methods'             => 'GET',
					'callback'            => array( __CLASS__, 'get_templates' ),
					'permission_callback' => array( __CLASS__, 'check_admin_permission' ),
				),
				array(
					'methods'             => 'POST',
					'callback'            => array( __CLASS__, 'create_template' ),
					'permission_callback' => array( __CLASS__, 'check_admin_permission' ),
				),
			)
		);

		register_rest_route(
			SHCB_REST_NAMESPACE,
			'/templates/(?P<id>\d+)',
			array(
				array(
					'methods'             => 'GET',
					'callback'            => array( __CLASS__, 'get_template' ),
					'permission_callback' => array( __CLASS__, 'check_admin_permission' ),
				),
				array(
					'methods'             => 'PUT',
					'callback'            => array( __CLASS__, 'update_template' ),
					'permission_callback' => array( __CLASS__, 'check_admin_permission' ),
				),
				array(
					'methods'             => 'DELETE',
					'callback'            => array( __CLASS__, 'delete_template' ),
					'permission_callback' => array( __CLASS__, 'check_admin_permission' ),
				),
			)
		);

		register_rest_route(
			SHCB_REST_NAMESPACE,
			'/templates/(?P<id>\d+)/duplicate',
			array(
				'methods'             => 'POST',
				'callback'            => array( __CLASS__, 'duplicate_template' ),
				'permission_callback' => array( __CLASS__, 'check_admin_permission' ),
			)
		);

		// ── Agents ─────────────────────────────────────────────────
		register_rest_route(
			SHCB_REST_NAMESPACE,
			'/agents',
			array(
				array(
					'methods'             => 'GET',
					'callback'            => array( __CLASS__, 'get_agents' ),
					'permission_callback' => array( __CLASS__, 'check_admin_permission' ),
				),
				array(
					'methods'             => 'POST',
					'callback'            => array( __CLASS__, 'save_agents_batch' ),
					'permission_callback' => array( __CLASS__, 'check_admin_permission' ),
				),
			)
		);

		register_rest_route(
			SHCB_REST_NAMESPACE,
			'/agents/(?P<id>[a-zA-Z0-9\-]+)',
			array(
				array(
					'methods'             => 'PUT',
					'callback'            => array( __CLASS__, 'update_agent' ),
					'permission_callback' => array( __CLASS__, 'check_admin_permission' ),
				),
				array(
					'methods'             => 'DELETE',
					'callback'            => array( __CLASS__, 'delete_agent' ),
					'permission_callback' => array( __CLASS__, 'check_admin_permission' ),
				),
			)
		);

		// ── Settings ───────────────────────────────────────────────
		register_rest_route(
			SHCB_REST_NAMESPACE,
			'/settings',
			array(
				array(
					'methods'             => 'GET',
					'callback'            => array( __CLASS__, 'get_settings' ),
					'permission_callback' => array( __CLASS__, 'check_admin_permission' ),
				),
				array(
					'methods'             => 'POST',
					'callback'            => array( __CLASS__, 'update_settings' ),
					'permission_callback' => array( __CLASS__, 'check_admin_permission' ),
				),
			)
		);

		// ── Display Rules ──────────────────────────────────────────
		register_rest_route(
			SHCB_REST_NAMESPACE,
			'/rules',
			array(
				array(
					'methods'             => 'GET',
					'callback'            => array( __CLASS__, 'get_rules' ),
					'permission_callback' => array( __CLASS__, 'check_admin_permission' ),
				),
				array(
					'methods'             => 'POST',
					'callback'            => array( __CLASS__, 'create_rule' ),
					'permission_callback' => array( __CLASS__, 'check_admin_permission' ),
				),
			)
		);

		register_rest_route(
			SHCB_REST_NAMESPACE,
			'/rules/(?P<id>[a-zA-Z0-9\-]+)',
			array(
				array(
					'methods'             => 'PUT',
					'callback'            => array( __CLASS__, 'update_rule' ),
					'permission_callback' => array( __CLASS__, 'check_admin_permission' ),
				),
				array(
					'methods'             => 'DELETE',
					'callback'            => array( __CLASS__, 'delete_rule' ),
					'permission_callback' => array( __CLASS__, 'check_admin_permission' ),
				),
			)
		);

		// ── Analytics ──────────────────────────────────────────────
		register_rest_route(
			SHCB_REST_NAMESPACE,
			'/analytics',
			array(
				'methods'             => 'GET',
				'callback'            => array( __CLASS__, 'get_analytics' ),
				'permission_callback' => array( __CLASS__, 'check_admin_permission' ),
			)
		);

		register_rest_route(
			SHCB_REST_NAMESPACE,
			'/analytics/track',
			array(
				'methods'             => 'POST',
				'callback'            => array( __CLASS__, 'track_event' ),
				'permission_callback' => '__return_true', // Public endpoint, rate-limited.
			)
		);

		// ── Platforms ──────────────────────────────────────────────
		register_rest_route(
			SHCB_REST_NAMESPACE,
			'/platforms',
			array(
				'methods'             => 'GET',
				'callback'            => array( __CLASS__, 'get_platforms' ),
				'permission_callback' => array( __CLASS__, 'check_admin_permission' ),
			)
		);

		// ── Export / Import ────────────────────────────────────────
		register_rest_route(
			SHCB_REST_NAMESPACE,
			'/export',
			array(
				'methods'             => 'GET',
				'callback'            => array( __CLASS__, 'export_config' ),
				'permission_callback' => array( __CLASS__, 'check_admin_permission' ),
			)
		);

		register_rest_route(
			SHCB_REST_NAMESPACE,
			'/import',
			array(
				'methods'             => 'POST',
				'callback'            => array( __CLASS__, 'import_config' ),
				'permission_callback' => array( __CLASS__, 'check_admin_permission' ),
			)
		);

		// ── Recommendations ──────────────────────────────────────────
		register_rest_route(
			SHCB_REST_NAMESPACE,
			'/recommendations',
			array(
				'methods'             => 'GET',
				'callback'            => array( __CLASS__, 'get_recommendations' ),
				'permission_callback' => array( __CLASS__, 'check_plugin_install_permission' ),
			)
		);

		register_rest_route(
			SHCB_REST_NAMESPACE,
			'/recommendations/action',
			array(
				'methods'             => 'POST',
				'callback'            => array( __CLASS__, 'handle_recommendation_action' ),
				'permission_callback' => array( __CLASS__, 'check_plugin_install_permission' ),
			)
		);
	}

	// ─────────────────────────────────────────────────────────────────
	// Permission Callback
	// ─────────────────────────────────────────────────────────────────

	/**
	 * Check if the current user has admin capabilities.
	 *
	 * @return bool|\WP_Error
	 */
	public static function check_admin_permission() {
		if ( ! current_user_can( 'manage_options' ) ) {
			return new \WP_Error(
				'shcb_rest_forbidden',
				esc_html__( 'You do not have permission to access this resource.', 'shois-chat-button' ),
				array( 'status' => 403 )
			);
		}
		return true;
	}

	/**
	 * Check if the current user has plugin installation capabilities.
	 *
	 * @return bool|\WP_Error
	 */
	public static function check_plugin_install_permission() {
		if ( ! current_user_can( 'activate_plugins' ) ) {
			return new \WP_Error(
				'shcb_rest_forbidden',
				esc_html__( 'You do not have permission to manage plugins.', 'shois-chat-button' ),
				array( 'status' => 403 )
			);
		}
		return true;
	}

	// ─────────────────────────────────────────────────────────────────
	// Template Endpoints (scaffolded)
	// ─────────────────────────────────────────────────────────────────

	/**
	 * Get all templates.
	 *
	 * @param \WP_REST_Request $request The request object.
	 * @return \WP_REST_Response
	 */
	public static function get_templates( $request ) {
		$templates = SHCB_Template_CPT::get_all_templates();
		$data      = array();

		foreach ( $templates as $template ) {
			$data[] = self::prepare_template_response( $template );
		}

		return rest_ensure_response( $data );
	}

	/**
	 * Get a single template.
	 *
	 * @param \WP_REST_Request $request The request object.
	 * @return \WP_REST_Response|\WP_Error
	 */
	public static function get_template( $request ) {
		$id       = absint( $request->get_param( 'id' ) );
		$template = get_post( $id );

		if ( ! $template || SHCB_Template_CPT::POST_TYPE !== $template->post_type ) {
			return new \WP_Error(
				'shcb_template_not_found',
				esc_html__( 'Template not found.', 'shois-chat-button' ),
				array( 'status' => 404 )
			);
		}

		return rest_ensure_response( self::prepare_template_response( $template ) );
	}

	/**
	 * Create a new template.
	 *
	 * @param \WP_REST_Request $request The request object.
	 * @return \WP_REST_Response|\WP_Error
	 */
	public static function create_template( $request ) {
		$title   = sanitize_text_field( $request->get_param( 'title' ) );
		$content = wp_json_encode( $request->get_param( 'config' ) );
		$type    = sanitize_key( $request->get_param( 'type' ) );

		if ( empty( $title ) ) {
			$title = esc_html__( 'Untitled Template', 'shois-chat-button' );
		}

		$post_id = wp_insert_post(
			array(
				'post_type'    => SHCB_Template_CPT::POST_TYPE,
				'post_title'   => $title,
				'post_content' => $content ? $content : '{}',
				'post_status'  => 'draft',
			),
			true
		);

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

		if ( ! empty( $type ) ) {
			update_post_meta( $post_id, SHCB_Template_CPT::META_TYPE, $type );
		}

		update_post_meta( $post_id, SHCB_Template_CPT::META_SCHEMA_VERSION, SHCB_SCHEMA_VERSION );

		$template = get_post( $post_id );

		return rest_ensure_response( self::prepare_template_response( $template ) );
	}

	/**
	 * Update an existing template.
	 *
	 * @param \WP_REST_Request $request The request object.
	 * @return \WP_REST_Response|\WP_Error
	 */
	public static function update_template( $request ) {
		$id       = absint( $request->get_param( 'id' ) );
		$template = get_post( $id );

		if ( ! $template || SHCB_Template_CPT::POST_TYPE !== $template->post_type ) {
			return new \WP_Error(
				'shcb_template_not_found',
				esc_html__( 'Template not found.', 'shois-chat-button' ),
				array( 'status' => 404 )
			);
		}

		$update_args = array( 'ID' => $id );

		$title = $request->get_param( 'title' );
		if ( null !== $title ) {
			$update_args['post_title'] = sanitize_text_field( $title );
		}

		$config = $request->get_param( 'config' );
		if ( null !== $config ) {
			$update_args['post_content'] = wp_json_encode( $config );
		}

		$status = $request->get_param( 'status' );
		if ( null !== $status ) {
			$update_args['post_status'] = sanitize_key( $status );
		}

		$result = wp_update_post( $update_args, true );

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

		$type = $request->get_param( 'type' );
		if ( null !== $type ) {
			update_post_meta( $id, SHCB_Template_CPT::META_TYPE, sanitize_key( $type ) );
		}

		$template = get_post( $id );

		return rest_ensure_response( self::prepare_template_response( $template ) );
	}

	/**
	 * Delete a template.
	 *
	 * @param \WP_REST_Request $request The request object.
	 * @return \WP_REST_Response|\WP_Error
	 */
	public static function delete_template( $request ) {
		$id       = absint( $request->get_param( 'id' ) );
		$template = get_post( $id );

		if ( ! $template || SHCB_Template_CPT::POST_TYPE !== $template->post_type ) {
			return new \WP_Error(
				'shcb_template_not_found',
				esc_html__( 'Template not found.', 'shois-chat-button' ),
				array( 'status' => 404 )
			);
		}

		$deleted = wp_delete_post( $id, true );

		if ( ! $deleted ) {
			return new \WP_Error(
				'shcb_delete_failed',
				esc_html__( 'Failed to delete template.', 'shois-chat-button' ),
				array( 'status' => 500 )
			);
		}

		return rest_ensure_response( array( 'deleted' => true, 'id' => $id ) );
	}

	/**
	 * Duplicate a template.
	 *
	 * @param \WP_REST_Request $request The request object.
	 * @return \WP_REST_Response|\WP_Error
	 */
	public static function duplicate_template( $request ) {
		$id       = absint( $request->get_param( 'id' ) );
		$template = get_post( $id );

		if ( ! $template || SHCB_Template_CPT::POST_TYPE !== $template->post_type ) {
			return new \WP_Error(
				'shcb_template_not_found',
				esc_html__( 'Template not found.', 'shois-chat-button' ),
				array( 'status' => 404 )
			);
		}

		/* translators: %s: original template name */
		$new_title = sprintf( esc_html__( '%s (Copy)', 'shois-chat-button' ), $template->post_title );

		$new_id = wp_insert_post(
			array(
				'post_type'    => SHCB_Template_CPT::POST_TYPE,
				'post_title'   => $new_title,
				'post_content' => $template->post_content,
				'post_status'  => 'draft',
			),
			true
		);

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

		// Copy all meta.
		$meta = get_post_meta( $id );
		if ( $meta ) {
			foreach ( $meta as $key => $values ) {
				if ( strpos( $key, '_shcb_' ) === 0 ) {
					foreach ( $values as $value ) {
						update_post_meta( $new_id, $key, maybe_unserialize( $value ) );
					}
				}
			}
		}

		// Reset default flag on copy.
		update_post_meta( $new_id, SHCB_Template_CPT::META_IS_DEFAULT, false );

		$new_template = get_post( $new_id );

		return rest_ensure_response( self::prepare_template_response( $new_template ) );
	}

	// ─────────────────────────────────────────────────────────────────
	// Agent Endpoints (scaffolded)
	// ─────────────────────────────────────────────────────────────────

	/**
	 * Get all agents.
	 *
	 * @param \WP_REST_Request $request The request object.
	 * @return \WP_REST_Response
	 */
	public static function get_agents( $request ) {
		$agents = get_option( 'shcb_agents', array() );
		return rest_ensure_response( $agents );
	}

	/**
	 * Save all agents (batch replace).
	 *
	 * Accepts { agents: [...] } and replaces the full array.
	 *
	 * @param \WP_REST_Request $request The request object.
	 * @return \WP_REST_Response
	 */
	public static function save_agents_batch( $request ) {
		$params = $request->get_json_params();
		$agents_raw = isset( $params['agents'] ) ? $params['agents'] : array();

		if ( ! is_array( $agents_raw ) ) {
			return new \WP_Error(
				'shcb_invalid_data',
				esc_html__( 'Invalid agents data.', 'shois-chat-button' ),
				array( 'status' => 400 )
			);
		}

		// --- Freemius PRO Limit Enforcement ---
		if ( function_exists( 'scb_fs' ) && ! scb_fs()->can_use_premium_code__premium_only() ) {
			// Limit to 1 agent
			if ( count( $agents_raw ) > 1 ) {
				$agents_raw = array_slice( $agents_raw, 0, 1 );
			}
			// Limit to 1 platform per agent
			if ( ! empty( $agents_raw[0]['platforms'] ) && count( $agents_raw[0]['platforms'] ) > 1 ) {
				$agents_raw[0]['platforms'] = array_slice( $agents_raw[0]['platforms'], 0, 1 );
			}
		}
		// ----------------------------------------

		$sanitized = array();
		foreach ( $agents_raw as $agent_data ) {
			$agent = self::sanitize_agent_data( $agent_data );
			if ( empty( $agent['id'] ) ) {
				$agent['id'] = wp_generate_uuid4();
			}
			$sanitized[] = $agent;
		}

		update_option( 'shcb_agents', $sanitized, 'no' );

		return rest_ensure_response( $sanitized );
	}

	/**
	 * Update an existing agent.
	 *
	 * @param \WP_REST_Request $request The request object.
	 * @return \WP_REST_Response|\WP_Error
	 */
	public static function update_agent( $request ) {
		$agent_id = sanitize_text_field( $request->get_param( 'id' ) );
		$agents   = get_option( 'shcb_agents', array() );
		$found    = false;

		foreach ( $agents as $index => $agent ) {
			if ( isset( $agent['id'] ) && $agent['id'] === $agent_id ) {
				$updated         = self::sanitize_agent_data( $request->get_json_params() );
				$updated['id']   = $agent_id;
				
				// --- Freemius PRO Limit Enforcement ---
				if ( function_exists( 'scb_fs' ) && ! scb_fs()->can_use_premium_code__premium_only() ) {
					if ( isset( $updated['platforms'] ) && count( $updated['platforms'] ) > 1 ) {
						$updated['platforms'] = array_slice( $updated['platforms'], 0, 1 );
					}
				}
				// ----------------------------------------

				$agents[ $index ] = array_merge( $agent, $updated );
				$found           = true;
				break;
			}
		}

		if ( ! $found ) {
			return new \WP_Error(
				'shcb_agent_not_found',
				esc_html__( 'Agent not found.', 'shois-chat-button' ),
				array( 'status' => 404 )
			);
		}

		update_option( 'shcb_agents', $agents, 'no' );

		return rest_ensure_response( $agents[ $index ] );
	}

	/**
	 * Delete an agent.
	 *
	 * @param \WP_REST_Request $request The request object.
	 * @return \WP_REST_Response|\WP_Error
	 */
	public static function delete_agent( $request ) {
		$agent_id = sanitize_text_field( $request->get_param( 'id' ) );
		$agents   = get_option( 'shcb_agents', array() );
		$found    = false;

		foreach ( $agents as $index => $agent ) {
			if ( isset( $agent['id'] ) && $agent['id'] === $agent_id ) {
				array_splice( $agents, $index, 1 );
				$found = true;
				break;
			}
		}

		if ( ! $found ) {
			return new \WP_Error(
				'shcb_agent_not_found',
				esc_html__( 'Agent not found.', 'shois-chat-button' ),
				array( 'status' => 404 )
			);
		}

		update_option( 'shcb_agents', $agents, 'no' );

		return rest_ensure_response( array( 'deleted' => true, 'id' => $agent_id ) );
	}

	// ─────────────────────────────────────────────────────────────────
	// Settings Endpoints
	// ─────────────────────────────────────────────────────────────────

	/**
	 * Get global settings.
	 *
	 * @param \WP_REST_Request $request The request object.
	 * @return \WP_REST_Response
	 */
	public static function get_settings( $request ) {
		$settings = get_option( 'shcb_global_settings', SHCB_Activator::get_default_settings() );
		return rest_ensure_response( $settings );
	}

	/**
	 * Update global settings.
	 *
	 * @param \WP_REST_Request $request The request object.
	 * @return \WP_REST_Response
	 */
	public static function update_settings( $request ) {
		$current  = get_option( 'shcb_global_settings', SHCB_Activator::get_default_settings() );
		$incoming = $request->get_json_params();

		// Sanitize top-level booleans and strings.
		if ( isset( $incoming['active'] ) ) {
			$current['active'] = rest_sanitize_boolean( $incoming['active'] );
		}

		if ( isset( $incoming['default_template_id'] ) ) {
			$current['default_template_id'] = absint( $incoming['default_template_id'] );
		}

		if ( isset( $incoming['active_template_slug'] ) ) {
			$current['active_template_slug'] = sanitize_key( $incoming['active_template_slug'] );
		}

		if ( isset( $incoming['brand_color'] ) ) {
			$current['brand_color'] = sanitize_hex_color( $incoming['brand_color'] );
		}



		if ( isset( $incoming['integrations'] ) && is_array( $incoming['integrations'] ) ) {
			$current['integrations'] = array();
			foreach ( $incoming['integrations'] as $key => $val ) {
				$current['integrations'][ sanitize_key( $key ) ] = rest_sanitize_boolean( $val );
			}
		}

		if ( isset( $incoming['performance'] ) && is_array( $incoming['performance'] ) ) {
			$current['performance'] = array();
			$string_perf = array( 'load_scope', 'css_delivery' );
			foreach ( $incoming['performance'] as $key => $val ) {
				$skey = sanitize_key( $key );
				if ( in_array( $skey, $string_perf, true ) ) {
					$current['performance'][ $skey ] = sanitize_text_field( $val );
				} else {
					$current['performance'][ $skey ] = rest_sanitize_boolean( $val );
				}
			}
		}

		if ( isset( $incoming['gdpr'] ) && is_array( $incoming['gdpr'] ) ) {
			$current['gdpr'] = array();
			if ( isset( $incoming['gdpr']['enabled'] ) ) {
				$current['gdpr']['enabled'] = rest_sanitize_boolean( $incoming['gdpr']['enabled'] );
			}
			if ( isset( $incoming['gdpr']['message'] ) ) {
				$current['gdpr']['message'] = sanitize_text_field( $incoming['gdpr']['message'] );
			}
			if ( isset( $incoming['gdpr']['button_text'] ) ) {
				$current['gdpr']['button_text'] = sanitize_text_field( $incoming['gdpr']['button_text'] );
			}
		}

		if ( isset( $incoming['lead_capture'] ) && is_array( $incoming['lead_capture'] ) ) {
			$current['lead_capture'] = array();
			foreach ( $incoming['lead_capture'] as $key => $val ) {
				if ( is_bool( $val ) || in_array( $val, array( true, false, 'true', 'false' ), true ) ) {
					$current['lead_capture'][ sanitize_key( $key ) ] = rest_sanitize_boolean( $val );
				} elseif ( is_array( $val ) ) {
					$current['lead_capture'][ sanitize_key( $key ) ] = array_map( 'sanitize_text_field', $val );
				} else {
					$current['lead_capture'][ sanitize_key( $key ) ] = sanitize_text_field( $val );
				}
			}
		}

		// Template config (content, design, behavior from template editor).
		if ( isset( $incoming['template_config'] ) && is_array( $incoming['template_config'] ) ) {
			$tc = array();
			$text_keys = array(
				'template_slug', 'header_title', 'header_subtitle', 'welcome_message',
				'offline_message', 'tooltip_text', 'label_text', 'footer_text', 'position', 'open_in',
				'trigger_icon',
				'entrance', 'idle', 'hover', 'popup',
			);
			$color_keys = array(
				'primary_color', 'header_bg_color', 'text_color', 'bg_color', 'header_text_color',
				'agent_bg_color', 'agent_text_color', 'icon_color',
			);
			$bool_keys = array(
				'auto_open', 'close_on_outside_click', 'remember_closed',
				'show_after_delay', 'show_after_scroll', 'show_label', 'badge_enabled',
				'enable_pulse_ring',
			);
			$int_keys = array(
				'auto_open_delay', 'delay_seconds', 'scroll_percentage', 'btn_size', 'popup_width',
				'offset_x', 'offset_y', 'radius_btn', 'radius_popup', 'idle_interval',
				'platform_radius', 'platform_margin', 'platform_padding',
			);

			foreach ( $incoming['template_config'] as $key => $val ) {
				$skey = sanitize_key( $key );
				if ( in_array( $skey, $text_keys, true ) ) {
					$tc[ $skey ] = sanitize_text_field( $val );
				} elseif ( in_array( $skey, $color_keys, true ) ) {
					// Supports hex (#abc123) and CSS gradients.
					$tc[ $skey ] = sanitize_text_field( $val );
				} elseif ( in_array( $skey, $bool_keys, true ) ) {
					$tc[ $skey ] = rest_sanitize_boolean( $val );
				} elseif ( in_array( $skey, $int_keys, true ) ) {
					$tc[ $skey ] = absint( $val );
				} elseif ( 'brand_logo' === $skey ) {
					$tc[ $skey ] = esc_url_raw( $val );
				} elseif ( 'badge_value' === $skey ) {
					$tc[ $skey ] = sanitize_text_field( $val );
				} elseif ( 'chips' === $skey && is_array( $val ) ) {
					$tc['chips'] = array();
					foreach ( $val as $chip ) {
						if ( is_array( $chip ) ) {
							$tc['chips'][] = array(
								'label'   => sanitize_text_field( isset( $chip['label'] ) ? $chip['label'] : '' ),
								'emoji'   => sanitize_text_field( isset( $chip['emoji'] ) ? $chip['emoji'] : '' ),
								'message' => sanitize_text_field( isset( $chip['message'] ) ? $chip['message'] : '' ),
							);
						}
					}
				}
			}
			$current['template_config'] = $tc;
		}

		update_option( 'shcb_global_settings', $current, 'no' );

		return rest_ensure_response( $current );
	}

	// ─────────────────────────────────────────────────────────────────
	// Display Rules Endpoints (scaffolded)
	// ─────────────────────────────────────────────────────────────────

	/**
	 * Get all display rules.
	 *
	 * @param \WP_REST_Request $request The request object.
	 * @return \WP_REST_Response
	 */
	public static function get_rules( $request ) {
		$rules = get_option( 'shcb_display_rules', array() );
		return rest_ensure_response( $rules );
	}

	/**
	 * Create or Update display rules.
	 *
	 * Supports both single rule creation (append) and batch save (replace).
	 *
	 * @param \WP_REST_Request $request The request object.
	 * @return \WP_REST_Response
	 */
	public static function create_rule( $request ) {
		$raw_data = $request->get_json_params();

		// If it's a batch save (contains 'rules' array), replace everything.
		if ( isset( $raw_data['rules'] ) && is_array( $raw_data['rules'] ) ) {
			// --- Freemius PRO Limit Enforcement ---
			if ( function_exists( 'scb_fs' ) && ! scb_fs()->can_use_premium_code__premium_only() ) {
				if ( count( $raw_data['rules'] ) > 1 ) {
					$raw_data['rules'] = array_slice( $raw_data['rules'], 0, 1 );
				}
			}
			// ----------------------------------------

			$sanitized = self::sanitize_rule_data( $raw_data );
			update_option( 'shcb_display_rules', $sanitized, 'no' );
			return rest_ensure_response( $sanitized );
		}

		// Otherwise, treat as a single rule to append (legacy/scaffolded behavior).
		$rules = get_option( 'shcb_display_rules', array() );
		// Ensure $rules is the format that contains a 'rules' list.
		if ( ! is_array( $rules ) || ! isset( $rules['rules'] ) ) {
			$rules = array(
				'mode'  => 'advanced',
				'rules' => is_array( $rules ) ? $rules : array(),
			);
		}

		// --- Freemius PRO Limit Enforcement ---
		if ( function_exists( 'scb_fs' ) && ! scb_fs()->can_use_premium_code__premium_only() ) {
			if ( count( $rules['rules'] ) >= 1 ) {
				return new \WP_Error(
					'shcb_pro_required',
					esc_html__( 'Free version is limited to 1 display rule. Please upgrade to PRO to add more rules.', 'shois-chat-button' ),
					array( 'status' => 403 )
				);
			}
		}
		// ----------------------------------------

		$rule = self::sanitize_rule_data( $raw_data );
		if ( empty( $rule['id'] ) ) {
			$rule['id'] = wp_generate_uuid4();
		}

		$rules['rules'][] = $rule;
		update_option( 'shcb_display_rules', $rules, 'no' );

		return rest_ensure_response( $rule );
	}

	/**
	 * Update a display rule.
	 *
	 * @param \WP_REST_Request $request The request object.
	 * @return \WP_REST_Response|\WP_Error
	 */
	public static function update_rule( $request ) {
		$rule_id = sanitize_text_field( $request->get_param( 'id' ) );
		$rules   = get_option( 'shcb_display_rules', array() );
		$found   = false;

		foreach ( $rules as $index => $rule ) {
			if ( isset( $rule['id'] ) && $rule['id'] === $rule_id ) {
				$updated         = self::sanitize_rule_data( $request->get_json_params() );
				$updated['id']   = $rule_id;
				$rules[ $index ] = array_merge( $rule, $updated );
				$found           = true;
				break;
			}
		}

		if ( ! $found ) {
			return new \WP_Error(
				'shcb_rule_not_found',
				esc_html__( 'Rule not found.', 'shois-chat-button' ),
				array( 'status' => 404 )
			);
		}

		update_option( 'shcb_display_rules', $rules, 'no' );

		return rest_ensure_response( $rules[ $index ] );
	}

	/**
	 * Delete a display rule.
	 *
	 * @param \WP_REST_Request $request The request object.
	 * @return \WP_REST_Response|\WP_Error
	 */
	public static function delete_rule( $request ) {
		$rule_id = sanitize_text_field( $request->get_param( 'id' ) );
		$rules   = get_option( 'shcb_display_rules', array() );
		$found   = false;

		foreach ( $rules as $index => $rule ) {
			if ( isset( $rule['id'] ) && $rule['id'] === $rule_id ) {
				array_splice( $rules, $index, 1 );
				$found = true;
				break;
			}
		}

		if ( ! $found ) {
			return new \WP_Error(
				'shcb_rule_not_found',
				esc_html__( 'Rule not found.', 'shois-chat-button' ),
				array( 'status' => 404 )
			);
		}

		update_option( 'shcb_display_rules', $rules, 'no' );

		return rest_ensure_response( array( 'deleted' => true, 'id' => $rule_id ) );
	}

	// ─────────────────────────────────────────────────────────────────
	// Analytics Endpoints
	// ─────────────────────────────────────────────────────────────────

	/**
	 * Get analytics summary.
	 *
	 * @param \WP_REST_Request $request The request object.
	 * @return \WP_REST_Response
	 */
	public static function get_analytics( $request ) {
		$days = absint( $request->get_param( 'days' ) );
		if ( ! $days ) {
			$days = 30;
		}
		
		require_once SHCB_PLUGIN_DIR . 'includes/class-shcb-analytics.php';
		$summary = SHCB_Analytics::get_summary( $days );
		
		return rest_ensure_response( $summary );
	}

	/**
	 * Track frontend event (impression, click, platform click).
	 *
	 * Rate-limited via transient. Max 60 requests per minute per IP.
	 *
	 * @param \WP_REST_Request $request The request object.
	 * @return \WP_REST_Response|\WP_Error
	 */
	public static function track_event( $request ) {
		$ip_hash       = md5( sanitize_text_field( wp_unslash( $_SERVER['REMOTE_ADDR'] ?? '0.0.0.0' ) ) );
		$transient_key = 'shcb_rate_' . $ip_hash;
		$count         = absint( get_transient( $transient_key ) );

		if ( $count >= 60 ) {
			return new \WP_Error(
				'shcb_rate_limited',
				esc_html__( 'Too many requests.', 'shois-chat-button' ),
				array( 'status' => 429 )
			);
		}

		set_transient( $transient_key, $count + 1, MINUTE_IN_SECONDS );

		$event_type = sanitize_key( $request->get_param( 'event_type' ) );
		$meta       = $request->get_param( 'meta' );
		if ( ! is_array( $meta ) ) {
			$meta = array();
		}

		if ( ! isset( $meta['device'] ) && $request->get_param( 'device_type' ) ) {
			$meta['device'] = sanitize_key( $request->get_param( 'device_type' ) );
		}

		if ( ! isset( $meta['platform'] ) && $request->get_param( 'platform_id' ) ) {
			$meta['platform'] = sanitize_key( $request->get_param( 'platform_id' ) );
		}
		
		require_once SHCB_PLUGIN_DIR . 'includes/class-shcb-analytics.php';
		$success = SHCB_Analytics::record_event( $event_type, $meta );
		
		return rest_ensure_response( array( 'success' => $success ) );
	}

	// ─────────────────────────────────────────────────────────────────

	/**
	 * Get all platform definitions.
	 *
	 * @param \WP_REST_Request $request The request object.
	 * @return \WP_REST_Response
	 */
	public static function get_platforms( $request ) {
		return rest_ensure_response( SHCB_Platform_Handler::get_platforms_for_api() );
	}

	// ─────────────────────────────────────────────────────────────────
	// Export / Import Endpoints (scaffolded)
	// ─────────────────────────────────────────────────────────────────

	/**
	 * Export full configuration.
	 *
	 * @param \WP_REST_Request $request The request object.
	 * @return \WP_REST_Response
	 */
	public static function export_config( $request ) {
		$data = array(
			'schema_version' => SHCB_SCHEMA_VERSION,
			'settings'       => get_option( 'shcb_global_settings', array() ),
			'agents'         => get_option( 'shcb_agents', array() ),
			'rules'          => get_option( 'shcb_display_rules', array() ),
			'templates'      => array(),
		);

		$templates = SHCB_Template_CPT::get_all_templates();
		foreach ( $templates as $template ) {
			$data['templates'][] = self::prepare_template_response( $template );
		}

		return rest_ensure_response( $data );
	}

	/**
	 * Import configuration.
	 *
	 * @param \WP_REST_Request $request The request object.
	 * @return \WP_REST_Response|\WP_Error
	 */
	public static function import_config( $request ) {
		// Placeholder: full import logic will be implemented in Phase 7.
		return rest_ensure_response( array( 'imported' => false, 'message' => 'Not yet implemented.' ) );
	}

	// ─────────────────────────────────────────────────────────────────
	// Helpers
	// ─────────────────────────────────────────────────────────────────

	/**
	 * Prepare a template post for API response.
	 *
	 * @param \WP_Post $template The template post object.
	 * @return array
	 */
	private static function prepare_template_response( $template ) {
		$config = json_decode( $template->post_content, true );

		return array(
			'id'             => $template->ID,
			'title'          => $template->post_title,
			'status'         => $template->post_status,
			'type'           => get_post_meta( $template->ID, SHCB_Template_CPT::META_TYPE, true ),
			'preview_thumb'  => get_post_meta( $template->ID, SHCB_Template_CPT::META_PREVIEW_THUMB, true ),
			'schema_version' => absint( get_post_meta( $template->ID, SHCB_Template_CPT::META_SCHEMA_VERSION, true ) ),
			'is_default'     => (bool) get_post_meta( $template->ID, SHCB_Template_CPT::META_IS_DEFAULT, true ),
			'config'         => is_array( $config ) ? $config : array(),
			'modified'       => $template->post_modified_gmt,
		);
	}

	/**
	 * Sanitize agent data from request.
	 *
	 * @param array $data Raw agent data.
	 * @return array Sanitized agent data.
	 */
	private static function sanitize_agent_data( $data ) {
		$sanitized = array();

		if ( isset( $data['id'] ) ) {
			$sanitized['id'] = sanitize_text_field( $data['id'] );
		}

		$text_fields = array( 'name', 'title', 'department', 'avatar_type', 'avatar_initials', 'status_override', 'status_message' );
		foreach ( $text_fields as $field ) {
			if ( isset( $data[ $field ] ) ) {
				$sanitized[ $field ] = sanitize_text_field( $data[ $field ] );
			}
		}

		if ( isset( $data['avatar_url'] ) ) {
			$sanitized['avatar_url'] = esc_url_raw( $data['avatar_url'] );
		}

		if ( isset( $data['avatar_bg_color'] ) ) {
			$sanitized['avatar_bg_color'] = sanitize_hex_color( $data['avatar_bg_color'] );
		}

		if ( isset( $data['enabled'] ) ) {
			$sanitized['enabled'] = rest_sanitize_boolean( $data['enabled'] );
		}

		if ( isset( $data['sort_order'] ) ) {
			$sanitized['sort_order'] = absint( $data['sort_order'] );
		}

		// Platforms array — sanitize each entry.
		if ( isset( $data['platforms'] ) && is_array( $data['platforms'] ) ) {
			$sanitized['platforms'] = array();
			foreach ( $data['platforms'] as $platform ) {
				$sanitized['platforms'][] = array(
					'platform_id'  => isset( $platform['platform_id'] ) ? sanitize_key( $platform['platform_id'] ) : '',
					'value'        => isset( $platform['value'] ) ? sanitize_text_field( $platform['value'] ) : '',
					'label'        => isset( $platform['label'] ) ? sanitize_text_field( $platform['label'] ) : '',
					'pre_message'  => isset( $platform['pre_message'] ) ? sanitize_textarea_field( $platform['pre_message'] ) : '',
					'enabled'      => isset( $platform['enabled'] ) ? rest_sanitize_boolean( $platform['enabled'] ) : true,
					'is_primary'   => isset( $platform['is_primary'] ) ? rest_sanitize_boolean( $platform['is_primary'] ) : false,
				);
			}
		}

		// Schedule — deep sanitize day keys and time values.
		if ( isset( $data['schedule'] ) && is_array( $data['schedule'] ) ) {
			$sanitized_schedule = array();
			foreach ( $data['schedule'] as $day_key => $day_data ) {
				$sday = sanitize_key( $day_key );
				if ( is_array( $day_data ) ) {
					$sanitized_schedule[ $sday ] = array(
						'enabled' => isset( $day_data['enabled'] ) ? rest_sanitize_boolean( $day_data['enabled'] ) : false,
						'start'   => isset( $day_data['start'] ) ? sanitize_text_field( $day_data['start'] ) : '09:00',
						'end'     => isset( $day_data['end'] ) ? sanitize_text_field( $day_data['end'] ) : '17:00',
					);
				}
			}
			$sanitized['schedule'] = $sanitized_schedule;
		}

		return $sanitized;
	}

	/**
	 * Sanitize a single display rule data array.
	 *
	 * @param array $data Raw rule data.
	 * @return array Sanitized rule data.
	 */
	private static function sanitize_rule_data( $data ) {
		$sanitized = array();

		if ( isset( $data['id'] ) ) {
			$sanitized['id'] = sanitize_text_field( $data['id'] );
		}

		if ( isset( $data['name'] ) ) {
			$sanitized['name'] = sanitize_text_field( $data['name'] );
		}

		if ( isset( $data['match'] ) ) {
			$sanitized['match'] = sanitize_key( $data['match'] );
		}

		if ( isset( $data['type'] ) ) {
			$sanitized['type'] = sanitize_key( $data['type'] );
		}

		if ( isset( $data['value'] ) ) {
			$sanitized['value'] = sanitize_text_field( $data['value'] );
		}

		if ( isset( $data['enabled'] ) ) {
			$sanitized['enabled'] = rest_sanitize_boolean( $data['enabled'] );
		}

		// Batch save via Settings page sends { mode, rules[] }.
		if ( isset( $data['mode'] ) ) {
			$sanitized['mode'] = sanitize_key( $data['mode'] );
		}

		if ( isset( $data['rules'] ) && is_array( $data['rules'] ) ) {
			$sanitized['rules'] = array();
			foreach ( $data['rules'] as $sub_rule ) {
				$sanitized['rules'][] = self::sanitize_rule_data( $sub_rule );
			}
		}

		return $sanitized;
	}

	// ─────────────────────────────────────────────────────────────────
	// Recommendation Handlers
	// ─────────────────────────────────────────────────────────────────

	/**
	 * Get the status of recommended plugins.
	 *
	 * @param \WP_REST_Request $request The request object.
	 * @return \WP_REST_Response
	 */
	public static function get_recommendations( $request ) {
		if ( ! function_exists( 'get_plugins' ) ) {
			require_once ABSPATH . 'wp-admin/includes/plugin.php';
		}

		$plugins = array(
			'smartwait-animated-preloader'       => 'smartwait-animated-preloader/smartwait-animated-preloader.php',
			'login-page-customizer-and-designer' => 'login-page-customizer-and-designer/login-page-customizer-and-designer.php',
			'uply-scroll-to-top'                 => 'uply-scroll-to-top/uply-scroll-to-top.php',
		);

		$status = array();

		foreach ( $plugins as $slug => $file ) {
			$is_installed = file_exists( WP_PLUGIN_DIR . '/' . $file );
			$is_active    = is_plugin_active( $file );

			$status[ $slug ] = array(
				'installed' => $is_installed,
				'active'    => $is_active,
			);
		}

		return rest_ensure_response( $status );
	}

	/**
	 * Handle plugin installation or activation.
	 *
	 * @param \WP_REST_Request $request The request object.
	 * @return \WP_REST_Response|\WP_Error
	 */
	public static function handle_recommendation_action( $request ) {
		$slug   = sanitize_key( $request->get_param( 'slug' ) );
		$action = sanitize_key( $request->get_param( 'action' ) );

		$allowed_plugins = array(
			'smartwait-animated-preloader'       => 'smartwait-animated-preloader/smartwait-animated-preloader.php',
			'login-page-customizer-and-designer' => 'login-page-customizer-and-designer/login-page-customizer-and-designer.php',
			'uply-scroll-to-top'                 => 'uply-scroll-to-top/uply-scroll-to-top.php',
		);

		if ( ! isset( $allowed_plugins[ $slug ] ) ) {
			return new \WP_Error( 'invalid_plugin', 'Invalid plugin requested.', array( 'status' => 400 ) );
		}

		$plugin_file = $allowed_plugins[ $slug ];

		if ( ! function_exists( 'get_plugins' ) ) {
			require_once ABSPATH . 'wp-admin/includes/plugin.php';
		}

		if ( 'install' === $action ) {
			if ( file_exists( WP_PLUGIN_DIR . '/' . $plugin_file ) ) {
				return rest_ensure_response( array( 'success' => true, 'message' => 'Already installed.' ) );
			}

			include_once ABSPATH . 'wp-admin/includes/file.php';
			include_once ABSPATH . 'wp-admin/includes/misc.php';
			include_once ABSPATH . 'wp-admin/includes/class-wp-upgrader.php';

			WP_Filesystem();

			// Silence the upgrader skin so it doesn't corrupt the JSON response.
			ob_start();
			$upgrader = new \Plugin_Upgrader( new \Automatic_Upgrader_Skin() );
			$download_link = 'https://downloads.wordpress.org/plugin/' . $slug . '.latest-stable.zip';
			
			$result = $upgrader->install( $download_link );
			$upgrade_output = ob_get_clean();

			if ( is_wp_error( $result ) || ! $result ) {
				$error_msg = is_wp_error( $result ) ? $result->get_error_message() : 'Unknown error';
				return new \WP_Error( 'install_failed', 'Failed to install plugin: ' . $error_msg, array( 'status' => 500, 'output' => $upgrade_output ) );
			}

			return rest_ensure_response( array( 'success' => true, 'message' => 'Installed successfully.' ) );

		} elseif ( 'activate' === $action ) {
			if ( ! file_exists( WP_PLUGIN_DIR . '/' . $plugin_file ) ) {
				return new \WP_Error( 'not_installed', 'Plugin is not installed.', array( 'status' => 400 ) );
			}

			$result = activate_plugin( $plugin_file );

			if ( is_wp_error( $result ) ) {
				return new \WP_Error( 'activation_failed', 'Failed to activate plugin: ' . $result->get_error_message(), array( 'status' => 500 ) );
			}

			return rest_ensure_response( array( 'success' => true, 'message' => 'Activated successfully.' ) );

		}

		return new \WP_Error( 'invalid_action', 'Invalid action requested.', array( 'status' => 400 ) );
	}
}
