<?php
/**
 * WooCommerce Appointments API
 *
 * @package WooCommerce\Appointments\Rest
 */

/**
 * API class which registers all the routes.
 */
class WC_Appointments_REST_API {

	const V1_NAMESPACE = 'wc-appointments/v1';
	/**
	 * V2 API namespace for expanded CRUD and indexed compatibility.
	 *
	 * Example base: /wp-json/wc-appointments/v2
	 */
	const V2_NAMESPACE = 'wc-appointments/v2';

	/**
	 * Constructor.
	 */
	public function __construct() {
		add_action( 'rest_api_init', [ $this, 'rest_api_init' ], 10 );
		add_action( 'rest_api_init', [ $this, 'register_order_fields' ], 10 );
		$this->rest_api_includes();
	}

	/**
     * Include REST API files.
     *
     * Includes all REST API controller files and internal services.
     */
    public function rest_api_includes(): void {
		include_once __DIR__ . '/api/trait-wc-appointments-rest-permission-check.php';
		include_once __DIR__ . '/api/class-wc-appointments-rest-crud-controller.php';
		include_once __DIR__ . '/api/class-wc-appointments-rest-appointments-controller.php';
		include_once __DIR__ . '/api/class-wc-appointments-rest-staff-controller.php';
		include_once __DIR__ . '/api/class-wc-appointments-rest-slots-controller.php';
		include_once __DIR__ . '/api/class-wc-appointments-rest-availabilities-controller.php';
		include_once __DIR__ . '/api/class-wc-appointments-rest-products-controller.php';
		include_once __DIR__ . '/api/class-wc-appointments-rest-products-categories-controller.php';

		// V2 controllers (CRUD-first, documented, efficient). Files are created in includes/api/v2.
		include_once __DIR__ . '/api/v2/class-wc-appointments-rest-v2-appointments-controller.php';
		include_once __DIR__ . '/api/v2/class-wc-appointments-rest-v2-availabilities-controller.php';
		include_once __DIR__ . '/api/v2/class-wc-appointments-rest-v2-slots-controller.php';
		include_once __DIR__ . '/api/v2/class-wc-appointments-rest-v2-index-controller.php';
		include_once __DIR__ . '/api/v2/class-wc-appointments-rest-v2-sse-controller.php';
		include_once __DIR__ . '/api/v2/class-wc-appointments-rest-v2-calendar-controller.php';

		// Internal REST API service (for plugin-internal usage).
		include_once __DIR__ . '/api/class-wc-appointments-rest-api-internal.php';
	}

	/**
	 * Initialize the REST API.
	 *
	 * Registers REST API routes for all controllers.
	 */
	public function rest_api_init(): void {
		$controller = new WC_Appointments_REST_Appointments_Controller();
		$controller->register_routes();

		$controller = new WC_Appointments_REST_Staff_Controller();
		$controller->register_routes();

		$controller = new WC_Appointments_REST_Slots_Controller();
		$controller->register_routes();

		$controller = new WC_Appointments_REST_Availabilities_Controller();
		$controller->register_routes();

		$controller = new WC_Appointments_REST_Products_Controller();
		$controller->register_routes();

		$controller = new WC_Appointments_REST_Products_Categories_Controller();
		$controller->register_routes();

		// Register V2 routes under /wc-appointments/v2.
		$v2_controllers = [
			new WC_Appointments_REST_V2_Appointments_Controller(),
			new WC_Appointments_REST_V2_Availabilities_Controller(),
			new WC_Appointments_REST_V2_Slots_Controller(),
			new WC_Appointments_REST_V2_Index_Controller(),
			new WC_Appointments_REST_V2_SSE_Controller(),
			new WC_Appointments_REST_V2_Calendar_Controller(),
		];

		foreach ( $v2_controllers as $controller ) {
			// Default namespace is V2; controllers set it internally.
			$controller->register_routes();
		}
	}

	/**
	 * Register additional REST fields on WooCommerce core Orders responses.
	 *
	 * Adds `appointments` array to each order payload, built from linked
	 * appointment posts. This provides better visibility when consuming
	 * orders via the API without making extra calls.
	 */
	public function register_order_fields(): void {
		// Register computed `appointments` field on `shop_order` REST objects.
		register_rest_field(
			'shop_order',
			'appointments',
			[
				'get_callback'    => [ $this, 'get_order_appointments_rest_field' ],
				'update_callback' => null,
				'schema'          => [
					'description' => 'Appointments linked to this order (from order items).',
					'type'        => 'array',
					'items'       => [ 'type' => 'object' ], // Follows appointments controller payload.
				],
			]
		);
	}

	/**
	 * Build the `appointments` field for an order REST response.
	 *
	 * @param array           $order_data Prepared order data (includes `id`).
	 * @param string          $field_name Field name.
	 * @param WP_REST_Request $request    Current REST request.
	 * @return array                      List of appointment payloads.
	 */
	public function get_order_appointments_rest_field( array $order_data, $field_name, $request ): array {
		// Defensive: require a valid order ID.
		$order_id = absint( $order_data['id'] ?? 0 );
		if ( $order_id <= 0 ) {
			return [];
		}

		// Fetch appointment IDs linked to this order via post_parent.
		$appointment_ids = \WC_Appointment_Data_Store::get_appointment_ids_from_order_id( $order_id );
		if ( empty( $appointment_ids ) ) {
			return [];
		}

		$controller = new \WC_Appointments_REST_Appointments_Controller();
		$items      = [];

		foreach ( $appointment_ids as $appointment_id ) {
			$appointment_id = (int) $appointment_id;
			if ( $appointment_id <= 0 ) {
				continue; // Skip invalid.
			}

			// Load appointment object; early‑continue on errors.
			try {
				$appointment = get_wc_appointment( $appointment_id );
			} catch ( \Exception $e ) {
				continue;
			}
			if ( ! $appointment ) {
				continue;
			}

			// Reuse appointments controller shaping to avoid duplication.
			$response = $controller->prepare_object_for_response( $appointment, $request );
			$data     = is_object( $response ) && method_exists( $response, 'get_data' ) ? $response->get_data() : [];
			if ( empty( $data ) ) {
				continue;
			}
			if ( ! is_array( $data ) ) {
				continue;
			}

			// Append order linkage context for convenience.
			$data['order_id']      = $order_id;
			$data['order_item_id'] = \WC_Appointment_Data_Store::get_appointment_order_item_id( $appointment_id );

			$items[] = $data;
		}

		return $items;
	}
}

new WC_Appointments_REST_API();
