<?php
/**
 * Analytics REST API.
 *
 * Provides read-only REST endpoints to retrieve data from the
 * preco_analytics_events table.
 *
 * Endpoints (all require manage_woocommerce capability):
 *
 *   GET /preco/v1/analytics/raw
 *     Returns all rows from the table with human-readable page/type labels.
 *     No server-side date filtering — the JS layer handles filtering client-side.
 *
 *   GET /preco/v1/analytics/recent-orders
 *     Returns up to 20 most-recent orders that contain at least one item
 *     originating from a Preco recommendation (have _preco_page_source meta).
 *     Optional query param: limit (int, 1–100, default 20).
 *
 * @package PRECO
 * @since 1.0.0
 */

namespace PRECO\Includes\Analytics;

use WP_REST_Request;
use WP_REST_Response;
use WP_Error;

defined( 'ABSPATH' ) || exit;

/**
 * AnalyticsRest class.
 */
class AnalyticsRest {

	const NAMESPACE = 'preco/v1';

	/**
	 * Register REST routes.
	 *
	 * @since 1.0.0
	 */
	public function __construct() {
		add_action( 'rest_api_init', array( $this, 'register_routes' ) );
	}

	/**
	 * Register all analytics REST routes.
	 *
	 * @return void
	 */
	public function register_routes() {
		// GET /preco/v1/analytics/raw — all rows, no date filter (JS handles filtering).
		register_rest_route(
			self::NAMESPACE,
			'/analytics/raw',
			array(
				'methods'             => 'GET',
				'callback'            => array( $this, 'get_raw' ),
				'permission_callback' => array( $this, 'admin_permission' ),
			)
		);

		// GET /preco/v1/analytics/recent-orders — recent orders that include Preco items.
		register_rest_route(
			self::NAMESPACE,
			'/analytics/recent-orders',
			array(
				'methods'             => 'GET',
				'callback'            => array( $this, 'get_recent_orders' ),
				'permission_callback' => array( $this, 'admin_permission' ),
				'args'                => array(
					'limit' => array(
						'required'          => false,
						'type'              => 'integer',
						'default'           => 20,
						'minimum'           => 1,
						'maximum'           => 100,
						'sanitize_callback' => 'absint',
					),
				),
			)
		);
	}

	// -------------------------------------------------------------------------
	// Callbacks
	// -------------------------------------------------------------------------

	/**
	 * GET /preco/v1/analytics/raw
	 *
	 * Returns every row in preco_analytics_events with human-readable labels.
	 * No date filtering is applied — the JS layer handles filtering client-side.
	 *
	 * @return WP_REST_Response
	 */
	public function get_raw() {
		$rows = AnalyticsTable::get_all_raw();

		return new WP_REST_Response(
			array(
				'success' => true,
				'data'    => $rows,
			),
			200
		);
	}

	/**
	 * GET /preco/v1/analytics/recent-orders
	 *
	 * Returns the most recent WooCommerce orders that contain at least one line
	 * item that originated from a Preco recommendation (identified by the
	 * _preco_page_source order item meta).
	 *
	 * Security:
	 *  - All raw DB queries use $wpdb->prepare() with typed placeholders.
	 *  - Order objects are loaded via wc_get_order() (HPOS-compatible).
	 *  - Input `limit` is validated as integer 1–100 before use.
	 *
	 * @param  WP_REST_Request $request REST request.
	 * @return WP_REST_Response
	 */
	public function get_recent_orders( WP_REST_Request $request ) {
		global $wpdb;

		$limit = (int) $request->get_param( 'limit' );
		$limit = max( 1, min( 100, $limit ) );

		$human_labels = array(
			'product-page'    => 'Product Page',
			'shop-page'       => 'Shop Page',
			'product-archive' => 'Product Archive',
			'cart'            => 'Cart',
			'checkout'        => 'Checkout',
			'thank-you'       => 'Thank You',
			'popup-upsell'    => 'PopUp Upsell',
			'order-bump'      => 'Order Bump',
		);

		/*
		 * Fetch one row per order_id — the first _preco_page_source meta value
		 * found among that order's line items. ORDER BY order_id DESC returns
		 * most-recent orders first.
		 *
		 * $wpdb->prepare() is used with %s and %d placeholders to prevent
		 * SQL injection. The table name uses $wpdb->prefix (safe constant) and
		 * esc_sql() as an extra safeguard.
		 */
		$order_items_table    = esc_sql( $wpdb->prefix . 'woocommerce_order_items' );
		$order_itemmeta_table = esc_sql( $wpdb->prefix . 'woocommerce_order_itemmeta' );

		// phpcs:disable WordPress.DB.DirectDatabaseQuery.DirectQuery,WordPress.DB.DirectDatabaseQuery.NoCaching,WordPress.DB.PreparedSQL.InterpolatedNotPrepared
		$rows = $wpdb->get_results(
			$wpdb->prepare(
				"SELECT oi.order_id, oim.meta_value AS page_source
				FROM {$order_items_table} AS oi
				INNER JOIN {$order_itemmeta_table} AS oim
					ON oi.order_item_id = oim.order_item_id
				WHERE oim.meta_key = %s
				GROUP BY oi.order_id
				ORDER BY oi.order_id DESC
				LIMIT %d",
				'_preco_page_source',
				$limit
			),
			ARRAY_A
		);
		// phpcs:enable

		if ( empty( $rows ) ) {
			return new WP_REST_Response(
				array(
					'success' => true,
					'data'    => array(),
				),
				200
			);
		}

		$data = array();

		foreach ( $rows as $row ) {
			$order = wc_get_order( (int) $row['order_id'] );
			if ( ! $order ) {
				continue;
			}

			// Unserialize the stored meta value → array( 'value' => 'product-page' ).
			$meta_value = maybe_unserialize( $row['page_source'] );
			$page_slug  = is_array( $meta_value ) ? ( $meta_value['value'] ?? '' ) : (string) $meta_value;
			$page_slug  = sanitize_text_field( $page_slug );
			$placement  = $human_labels[ $page_slug ] ?? $page_slug;

			$date_obj = $order->get_date_created();

			$data[] = array(
				'orderId'       => '#' . $order->get_order_number(),
				'orderLink'     => esc_url( $order->get_edit_order_url() ),
				'date'          => $date_obj ? $date_obj->date( 'Y-m-d' ) : '',
				'placementName' => $placement,
				'total'         => (float) $order->get_total(),
			);
		}

		return new WP_REST_Response(
			array(
				'success' => true,
				'data'    => $data,
			),
			200
		);
	}

	// -------------------------------------------------------------------------
	// Permissions & shared helpers
	// -------------------------------------------------------------------------

	/**
	 * Restrict access to users with the manage_woocommerce capability.
	 *
	 * @param  WP_REST_Request $request REST request.
	 * @return bool|WP_Error
	 */
	public function admin_permission( WP_REST_Request $request ) {
		if ( ! wp_verify_nonce( $request->get_header( 'X-WP-Nonce' ), 'wp_rest' ) ) {
			return new WP_Error(
				'wp_rest_forbidden',
				__( 'Invalid nonce.', 'wow-ai-product-recommendations' ),
				array( 'status' => 403 )
			);
		}
		if ( ! current_user_can( 'manage_woocommerce' ) ) {
			return new WP_Error(
				'wp_rest_forbidden',
				__( 'You do not have permission to access analytics data.', 'wow-ai-product-recommendations' ),
				array( 'status' => 403 )
			);
		}
		return true;
	}
}
