<?php

namespace CelerSearch\Indices;

use CelerSearch\Builders\IndexSettingsBuilder;
use CelerSearch\DataTransfer\IndexableTestObject;
use CelerSearch\DataTransfer\IndexCandidate;
use CelerSearch\DataTransfer\IndexConfig;
use CelerSearch\DataTransfer\IndexSettings;
use CelerSearch\DataTransfer\ServiceConfig;
use CelerSearch\Exceptions\MissingServiceInIndexSettings;
use CelerSearch\Factories\ServiceFactory;
use CelerSearch\Interfaces\IIndexableObject;

class TestIndex extends BaseIndex {

	/**
	 * Constructor
	 *
	 * @param IndexConfig $index_details
	 * @param ServiceConfig $service_details
	 *
	 * @throws MissingServiceInIndexSettings
	 */
	public function __construct( IndexConfig $index_details, ServiceConfig $service_details ) {
		parent::__construct( $index_details );
		$this->service = ServiceFactory::create_for_testing( $service_details );
	}

	/**
	 * Performs additional initialization (if needed)
	 * @return void
	 */
	protected function init(): void {
		// Do nothing.
	}

	/**
	 * Check whether an item is supported.
	 *
	 * @param IndexCandidate $item
	 *
	 * @return bool
	 */
	public function is_supported( IndexCandidate $item ): bool {
		return true;
	}

	/**
	 * Check whether an item can be indexed.
	 *
	 * @param IndexCandidate $item
	 *
	 * @return bool
	 */
	public function should_index( IndexCandidate $item ): bool {
		return true;
	}

	/**
	 * Returns specific indexable items
	 *
	 * @param array $ids
	 *
	 * @return array<IndexCandidate>
	 */
	public function get_candidates_by_ids( array $ids ): array {
		$items = $this->get_candidates(1, 10);
		$specs = [];
		foreach ( $items as $item ) {
			if ( in_array( $item->get_id(), $ids ) ) {
				$specs[] = $item;
			}
		}

		return $specs;
	}

	/**
	 * Returns items from the index
	 *
	 * @param $page
	 * @param $batch_size
	 *
	 * @return array<IIndexableObject>
	 */
	public function get_candidates( $page, $batch_size ): array {
		return [
			new IndexCandidate( [
				'id'    => 1,
				'name'  => 'Peter Parker',
				'nick'  => 'Spider-man',
				'bio'   => 'With spider-like abilities, science genius Peter Parker swings above it all as Spider-Man, costumed champion of the innocent who lives and fights with the wisdom of “With Great Power Comes Great Responsibility!”',
				'loc'   => [ 'New York City', 'Queens' ],
				'power' => 45,
			] ),
			new IndexCandidate( [
				'id'    => 2,
				'name'  => 'Clark Kent',
				'nick'  => 'Superman',
				'bio'   => 'One of the last children of Krypton, sent as the dying planet\'s last hope to Earth, where he grew to become its kind, noble protector',
				'loc'   => [ 'Barons', 'Beynon' ],
				'power' => 48,
			] ),
			new IndexCandidate( [
				'id'    => 3,
				'name'  => 'Bruce Wayne',
				'nick'  => 'Batman',
				'bio'   => 'A a rich playboy and philanthropist who swore to fight crime after witnessing his parents brutal murder',
				'loc'   => [ 'New York City', 'Gotham City' ],
				'power' => 55,
			] ),
		];
	}

	/**
	 * Returns items from the index
	 *
	 * @return int
	 */
	public function get_candidate_count(): int {
		return count( $this->get_candidates( 1, 10 ) );
	}

	/**
	 * Returns the item records
	 *
	 * @param IndexCandidate $item
	 *
	 * @return array<IIndexableObject>
	 */
	public function get_candidate_objects( IndexCandidate $item ): array {
		return [ $item ];
	}

	/**
	 * Returns the index settings
	 * @return IndexSettings;
	 */
	public function get_settings(): IndexSettings {
		return ( new IndexSettingsBuilder )
			->distinct_attribute( 'id' )
			->searchable_attributes( [
				'name:unordered',
				'nick:unordered',
				'bio:unordered',
				'loc:unordered',
			] )
			->filterable_attributes( [
				'loc',
			] )
			->sortable_attributes( [
				'power:desc',
			] )
			->snippet_attributes( [
				'name:30',
				'bio:55',
			] )
			->max_hits( 20 )
			->build();
	}

	/**
	 * Format a test hit for autocomplete display
	 *
	 * @param array $hit Raw hit from search index
	 *
	 * @return array|null Formatted hit or null to skip
	 */
	public function format_autocomplete_hit( array $hit ): ?array {
		// Return the raw hit for testing purposes
		return $hit;
	}

	/**
	 * Get status filter for test autocomplete search
	 *
	 * @param string $context 'frontend' or 'admin'
	 *
	 * @return array|null
	 */
	public function get_autocomplete_status_filter( string $context ): ?array {
		// Test index doesn't use status filtering
		return null;
	}
}