<?php

namespace CelerSearch\CLI;

use CelerSearch\Factories\IndexFactory;
use CelerSearch\Repositories\IndexRepository;
use WP_CLI;
use WP_CLI\Formatter;

/**
 * Manage CelerSearch indices via WP-CLI.
 */
class IndexCommand {

	/**
	 * List all CelerSearch indices.
	 *
	 * ## OPTIONS
	 *
	 * [--format=<format>]
	 * : Output format.
	 * ---
	 * default: table
	 * options:
	 *   - table
	 *   - csv
	 *   - json
	 *   - yaml
	 * ---
	 *
	 * ## EXAMPLES
	 *
	 *     # List all indices
	 *     wp celersearch index list
	 *
	 *     # Output as JSON
	 *     wp celersearch index list --format=json
	 *
	 * @when after_wp_load
	 *
	 * @param array $args       Positional arguments.
	 * @param array $assoc_args Associative arguments.
	 */
	public function list( $args, $assoc_args ) {
		$repo    = new IndexRepository();
		$indices = $repo->get( [], 1, 100 );

		if ( empty( $indices ) ) {
			WP_CLI::warning( 'No indices found.' );
			return;
		}

		$items = [];
		foreach ( $indices as $index_config ) {
			$local_count  = '-';
			$remote_count = '-';

			try {
				$index        = IndexFactory::create( $index_config->getId() );
				$local_count  = $index->get_candidate_count();
				$count_result = $index->count_items();
				if ( $count_result->is_success() ) {
					$remote_count = $count_result->get_value();
				}
			} catch ( \Exception $e ) {
				// Keep defaults
			}

			$items[] = [
				'ID'     => $index_config->getId(),
				'Name'   => $index_config->getName(),
				'Slug'   => $index_config->getSlug(),
				'Type'   => $index_config->getType(),
				'Local'  => $local_count,
				'Remote' => $remote_count,
				'Status' => $index_config->getStatus() ?: 'pending',
			];
		}

		$format    = WP_CLI\Utils\get_flag_value( $assoc_args, 'format', 'table' );
		$formatter = new Formatter( $assoc_args, [ 'ID', 'Name', 'Slug', 'Type', 'Local', 'Remote', 'Status' ] );
		$formatter->display_items( $items );
	}

	/**
	 * Show detailed information about an index.
	 *
	 * ## OPTIONS
	 *
	 * <index>
	 * : Index ID or slug.
	 *
	 * [--format=<format>]
	 * : Output format.
	 * ---
	 * default: table
	 * options:
	 *   - table
	 *   - json
	 *   - yaml
	 * ---
	 *
	 * ## EXAMPLES
	 *
	 *     # Show info for index ID 1
	 *     wp celersearch index info 1
	 *
	 *     # Show info for index by slug
	 *     wp celersearch index info posts-news
	 *
	 * @when after_wp_load
	 *
	 * @param array $args       Positional arguments.
	 * @param array $assoc_args Associative arguments.
	 */
	public function info( $args, $assoc_args ) {
		$identifier   = $args[0];
		$index_config = $this->resolve_index( $identifier );

		if ( ! $index_config ) {
			WP_CLI::error( "Index not found: {$identifier}" );
		}

		$info = [
			'ID'         => $index_config->getId(),
			'Name'       => $index_config->getName(),
			'Slug'       => $index_config->getSlug(),
			'Type'       => $index_config->getType(),
			'Service ID' => $index_config->getServiceId(),
			'Status'     => $index_config->getStatus() ?: 'pending',
			'Synced At'  => $index_config->getSyncedAt() ?: '-',
			'Checked At' => $index_config->getCheckedAt() ?: '-',
		];

		try {
			$index              = IndexFactory::create( $index_config->getId() );
			$info['Local Items']  = $index->get_candidate_count();
			$info['Batch Size']   = $index->get_candidate_batch_size();
			$info['Total Batches'] = $index->get_candidate_batch_pages();

			$count_result = $index->count_items();
			if ( $count_result->is_success() ) {
				$info['Remote Items'] = $count_result->get_value();
			} else {
				$info['Remote Items'] = 'Error: ' . $count_result->get_error_message();
			}
		} catch ( \Exception $e ) {
			$info['Error'] = $e->getMessage();
		}

		$format = WP_CLI\Utils\get_flag_value( $assoc_args, 'format', 'table' );

		if ( $format === 'json' ) {
			WP_CLI::log( json_encode( $info, JSON_PRETTY_PRINT ) );
		} elseif ( $format === 'yaml' ) {
			WP_CLI::log( \Spyc::YAMLDump( $info ) );
		} else {
			foreach ( $info as $key => $value ) {
				WP_CLI::log( sprintf( '%-15s %s', $key . ':', $value ) );
			}
		}
	}

	/**
	 * Clear an index (delete all documents without deleting the index).
	 *
	 * ## OPTIONS
	 *
	 * <index>
	 * : Index ID or slug.
	 *
	 * [--yes]
	 * : Skip confirmation prompt.
	 *
	 * ## EXAMPLES
	 *
	 *     # Clear index ID 1
	 *     wp celersearch index clear 1
	 *
	 *     # Clear without confirmation
	 *     wp celersearch index clear 1 --yes
	 *
	 * @when after_wp_load
	 *
	 * @param array $args       Positional arguments.
	 * @param array $assoc_args Associative arguments.
	 */
	public function clear( $args, $assoc_args ) {
		$identifier   = $args[0];
		$index_config = $this->resolve_index( $identifier );

		if ( ! $index_config ) {
			WP_CLI::error( "Index not found: {$identifier}" );
		}

		$index_name = $index_config->getName();

		WP_CLI::confirm( "Are you sure you want to clear all documents from '{$index_name}'?", $assoc_args );

		try {
			$index  = IndexFactory::create( $index_config->getId() );
			$result = $index->clear();

			if ( $result->is_success() ) {
				WP_CLI::success( "Index '{$index_name}' cleared successfully." );
			} else {
				WP_CLI::error( "Failed to clear index: " . $result->get_error_message() );
			}
		} catch ( \Exception $e ) {
			WP_CLI::error( "Failed to clear index: " . $e->getMessage() );
		}
	}

	/**
	 * Resolve index by ID or slug.
	 *
	 * @param string $identifier Index ID or slug.
	 *
	 * @return \CelerSearch\DataTransfer\IndexConfig|null
	 */
	private function resolve_index( $identifier ) {
		$repo = new IndexRepository();

		// Try as ID first.
		if ( is_numeric( $identifier ) ) {
			$index = $repo->find( (int) $identifier );
			if ( $index ) {
				return $index;
			}
		}

		// Try as slug.
		return $repo->find_by_slug( $identifier );
	}
}
