<?php

namespace Limb_Chatbot\Includes\Repositories;

use Limb_Chatbot\Includes\Blocks\Chatbot;
use Limb_Chatbot\Includes\Data_Objects\Vector;
use Limb_Chatbot\Includes\Data_Objects\Vector_Index;
use Limb_Chatbot\Includes\Data_Objects\Vector_Index_Meta;
use Limb_Chatbot\Includes\Data_Objects\Vector_Index_Vector;
use Limb_Chatbot\Includes\Database_Strategies\WPDB;
use Limb_Chatbot\Includes\Services\Collection;


/**
 * Repository for managing Vector_Index data objects.
 *
 * Provides methods for querying, creating, updating, and deleting vector indices.
 *
 * @since 1.0.0
 */
class Vector_Index_Repository {

	/**
	 * Retrieves a paginated collection of Vector_Index objects filtered by parameters.
	 *
	 * @since 1.0.0
	 *
	 * @param array $params {
	 *     Optional. Query parameters for filtering and pagination.
	 *
	 *     @type int    $per_page Number of items per page. Default 10.
	 *     @type int    $page     Current page number. Default 1.
	 *     @type string $orderby  Field to order by. Default 'id'.
	 *     @type string $order    Direction of sorting: 'asc' or 'desc'. Default 'asc'.
	 * }
	 *
	 * @return Collection|null Collection of Vector_Index objects or null if none found.
	 */
	public function get_items( array $params ): ?Collection {
		if ( array_key_exists( 'chatbot_uuid', $params ) ) {
			if ( empty( $params['chatbot_uuid'] ) ) {
				$params['chatbot_uuid'] = null;
			}
			$vector_index_metas = Vector_Index_Meta::where( [
				'meta_key'   => 'chatbot_uuid',
				'meta_value' => $params['chatbot_uuid']
			] );
			if ( ! $vector_index_metas->is_empty() ) {
				$params['id'] = $vector_index_metas->pluck( 'vector_index_id' );
			} else {
				return new Collection();
			}
		}
		if ( ! empty( $params['post_type'] ) ) {
			$params['per_page'] = - 1;
		}
		$indexes = Vector_Index::where(
			$params,
			$params['per_page'] ?? 10,
			$params['page'] ?? 1,
			$params['orderby'] ?? 'id',
			$params['order'] ?? 'asc'
		);
		if ( ! empty( $params['post_type'] ) ) {
			return $indexes->filter( function ( Vector_Index $vector_index ) use ( $params ) {
				return str_contains( $vector_index->get_name(), $params['post_type'] );
			} );
		}

		return $indexes;
	}

	/**
	 * Retrieves a single Vector_Index by ID, optionally including relations.
	 *
	 * @since 1.0.0
	 *
	 * @param int   $id     The ID of the Vector_Index.
	 * @param array $params Optional parameters, supports 'include' for eager loading.
	 *
	 * @return Vector_Index|null The Vector_Index object or null if not found.
	 */
	public function get_item( int $id, $params ): ?Vector_Index {
		$vector_index = Vector_Index::where( [ 'id' => $id ] );
		if ( ! $vector_index->is_empty() && ! empty( $params['include'] ) ) {
			$vector_index = $vector_index->with( $params['include'] );
		}

		return $vector_index->first();
	}

	/**
	 * Creates a new Vector_Index record.
	 *
	 * @param  array  $data  Data attributes for the new Vector_Index.
	 *
	 * @return Vector_Index The created Vector_Index object.
	 * @throws \Exception
	 * @since 1.0.0
	 *
	 */
	public function create( array $data ): Vector_Index {
		return Vector_Index::create( $data );
	}

	/**
	 * Instantiates a new Vector_Index object without persisting it.
	 *
	 * @since 1.0.0
	 *
	 * @param array $data Data attributes to populate the new Vector_Index object.
	 *
	 * @return Vector_Index The instantiated Vector_Index object.
	 */
	public function make( array $data ): Vector_Index {
		return Vector_Index::make( $data );
	}

	/**
	 * Deletes a Vector_Index by its ID.
	 *
	 * @since 1.0.0
	 *
	 * @param int $id ID of the Vector_Index to delete.
	 *
	 * @return bool True if deletion was successful, false otherwise.
	 */
	public function delete( int $id ): bool {
		return Vector_Index::delete( [ 'id' => $id ] );
	}

	public function get_inactive_vectors( ?int $vector_index_id = null ): array {
		if ( empty( $vector_index_id ) ) {
			return [];
		}

		$wpdb = WPDB::instance()->get_wpdb();

		$vectors_table              = $wpdb->prefix . Vector::TABLE_NAME;
		$vector_index_vectors_table = $wpdb->prefix . Vector_Index_Vector::TABLE_NAME;

		$sql = "
			SELECT DISTINCT v.id
			FROM {$vectors_table} v
			INNER JOIN {$vector_index_vectors_table} viv ON viv.vector_id = v.id
			WHERE viv.vector_index_id = %d
			  AND v.status = %d
		";

		$prepared = $wpdb->prepare(
			$sql,
			$vector_index_id,
			Vector::STATUS_INACTIVE
		);

		$ids = $wpdb->get_col( $prepared );

		return array_map( 'intval', $ids ?? [] );
	}

}