<?php

namespace Limb_Chatbot\Includes\Repositories;

use Limb_Chatbot\Includes\Data_Objects\Wp_Archive_Object_Group;
use Limb_Chatbot\Includes\Data_Objects\Wp_Object_Group;
use Limb_Chatbot\Includes\Data_Objects\Wp_Post_Object_Group;
use Limb_Chatbot\Includes\Data_Objects\Wp_Special_Page_Object_Group;
use Limb_Chatbot\Includes\Data_Objects\Wp_Term_Object_Group;
use Limb_Chatbot\Includes\Services\Wp_Object_By_Identifier_Service;

class Wp_Object_Group_Repository {

	public function get_items( array $params ) {
		$object_groups = [];
		$group_classes = array(
			Wp_Special_Page_Object_Group::class,
			Wp_Post_Object_Group::class,
			Wp_Term_Object_Group::class,
			Wp_Archive_Object_Group::class,
		);

		$allowed_groups = apply_filters( 'lbaic_allowed_object_groups', $group_classes );

		foreach ( $allowed_groups as $group ) {
			$groups = $group::all();
			// Only add non-empty groups
			if ( ! empty( $groups ) ) {
				$object_groups = array_merge( $object_groups, $groups );
			}
		}

		// Handle selected identifiers if provided
		if ( ! empty( $params['selected_identifiers'] ) && is_array( $params['selected_identifiers'] ) ) {
			$object_groups = $this->prepend_selected_objects_group( $object_groups, $params['selected_identifiers'] );
		}

		if ( ! empty( $params['include'] ) && in_array( 'objects', $params['include'] ) ) {
			$object_groups = $this->include_objects( $object_groups, $params );
		}

		return $object_groups;
	}

	/**
	 * Prepend a group containing selected objects by identifiers.
	 *
	 * Creates a special group at the beginning of the groups array containing
	 * all objects that match the provided identifiers, without pagination.
	 *
	 * @param  array  $groups  Existing groups array.
	 * @param  array  $identifiers  Array of identifier strings.
	 *
	 * @return array Modified groups array with selected objects group prepended.
	 */
	private function prepend_selected_objects_group( array $groups, array $identifiers ): array {
		$service            = new Wp_Object_By_Identifier_Service();
		$objects_collection = $service->get_objects_by_identifiers( $identifiers );

		// Only add the group if we found objects
		if ( $objects_collection->count() > 0 ) {
			$selected_group = Wp_Object_Group::make( [
				'name'  => 'selected_objects',
				'label' => __( 'Selected', 'limb-chatbot' ),
			] );

			// Add the objects to the group
			$selected_group->included['objects'] = $objects_collection;

			// Prepend the group to the beginning of the array
			array_unshift( $groups, $selected_group );
		}

		return $groups;
	}

	/**
	 * Include objects
	 *
	 * @param $groups
	 * @param $params
	 *
	 * @return array
	 */
	public function include_objects( $groups, $params ) {
		$search_term = ! empty( $params['s'] ) ? sanitize_text_field( $params['s'] ) : '';
		$per_page    = ! empty( $params['per_page'] ) ? (int) $params['per_page'] : 10;
		$page        = ! empty( $params['page'] ) ? (int) $params['page'] : 1;

		foreach ( $groups as $group ) {
			if ( ! $group instanceof Wp_Object_Group ) {
				continue;
			}

			// Skip the selected_objects group as it already has objects
			if ( $group->get_name() === 'selected_objects' ) {
				continue;
			}

			$objects_collection = $group->objects( $search_term, $per_page, $page );

			// Add _objects property to the group using push_property
			$group->included['objects'] = $objects_collection;
		}

		return $groups;
	}

}