<?php

namespace Limb_Chatbot\Includes\Vector_Dbs\Pinecone\Endpoints\Query;

use Limb_Chatbot\Includes\Data_Objects\Vector;
use Limb_Chatbot\Includes\Services\Collection;
use Limb_Chatbot\Includes\Vector_Dbs\Pinecone\Response_Handler as Base_Response_Handler;

/**
 * Class Response_Handler
 *
 * Handles the response from Pinecone query endpoint,
 * parses vector matches and enriches them with scores.
 *
 * @package Limb_Chatbot\Includes\Vector_Dbs\Pinecone\Endpoints\Query
 *
 * @since 1.0.0
 */
class Response_Handler extends Base_Response_Handler {

	/**
	 * @var bool|null Flag to cast response body as array
	 *
	 * @since 1.0.0
	 */
	protected ?bool $body_cast_array = true;

	/**
	 * @var Collection|null Collection of matched vectors with scores
	 *
	 * @since 1.0.0
	 */
	protected ?Collection $vectors = null;

	/**
	 * Parse the response body and populate vectors.
	 *
	 * @return void
	 *
	 * @since 1.0.0
	 */
	public function parse(): void {
		parent::parse();
		$this->define_vectors();
	}

	/**
	 * Define vectors by matching response IDs with stored vectors,
	 * and attach score values from the matches.
	 *
	 * @return void
	 *
	 * @since 1.0.0
	 */
	public function define_vectors(): void {
		if ( ! empty( $this->get_body() ) && is_array( $this->get_body() ) && ! empty( $this->get_body()['matches'] ) ) {
			$matches = $this->get_body()['matches'];
			$vectors = Vector::where( [ 'uuid' => array_column( $matches, 'id' ) ] );
			if ( ! $vectors->is_empty() ) {
				$vectors->filter( function ( $vector ) use ( $matches ) {
					foreach ( $matches as $match ) {
						if ( $vector->get_uuid() === $match['id'] ) {
							$vector->score = $match['score'];
						}
					}
				} );
			}
			$this->vectors = $vectors;
		}
	}

	/**
	 * Get the collection of matched vectors with scores.
	 *
	 * @return Collection|null Collection of vectors or null if none
	 *
	 * @since 1.0.0
	 */
	public function get_vectors(): ?Collection {
		return $this->vectors;
	}
}
