<?php

namespace Limb_Chatbot\Includes\Services\Knowledge\Source_Validators;

use Limb_Chatbot\Includes\Exceptions\Error_Codes;
use Limb_Chatbot\Includes\Exceptions\Exception;
use Limb_Chatbot\Includes\Interfaces\Source_Validator_Interface;

class Manual_Validator implements Source_Validator_Interface {

	/**
	 * Validates the parameters for manual knowledge datasets.
	 *
	 * Accepts QA payload as an array of pairs:
	 * - question (required)
	 * - answer (required)
	 * - question_variations (optional string array)
	 *
	 * @param  array  $config  Configuration array containing manual knowledge data.
	 *
	 * @throws Exception If any required manual knowledge field is missing.
	 *
	 * @since 1.0.0
	 */
	public function validate( array $config ): void {
		$qa_items = $this->normalize_qa_items( $config['q_a'] ?? null );
		if ( empty( $qa_items ) || ! is_array( $qa_items ) ) {
			throw new Exception( Error_Codes::VALIDATION_INVALID_VALUE,
				__( 'Q&A knowledge is missing.', 'limb-chatbot' ) );
		}

		foreach ( $qa_items as $index => $item ) {
			$position = $index + 1;
			if ( ! is_array( $item ) ) {
				throw new Exception(
					Error_Codes::VALIDATION_INVALID_VALUE,
					sprintf(
						/* translators: %d is a 1-based Q&A item position. */
						__( 'Q&A item #%d must be an object.', 'limb-chatbot' ),
						$position
					)
				);
			}

			$question = trim( (string) ( $item['question'] ?? '' ) );
			$answer   = trim( (string) ( $item['answer'] ?? '' ) );

			if ( '' === $question ) {
				throw new Exception(
					Error_Codes::VALIDATION_INVALID_VALUE,
					sprintf(
						/* translators: %d is a 1-based Q&A item position. */
						__( 'Q&A item #%d question is missing.', 'limb-chatbot' ),
						$position
					)
				);
			}
			if ( '' === $answer ) {
				throw new Exception(
					Error_Codes::VALIDATION_INVALID_VALUE,
					sprintf(
						/* translators: %d is a 1-based Q&A item position. */
						__( 'Q&A item #%d answer is missing.', 'limb-chatbot' ),
						$position
					)
				);
			}

			if ( array_key_exists( 'question_variations', $item ) && ! is_array( $item['question_variations'] ) ) {
				throw new Exception(
					Error_Codes::VALIDATION_INVALID_VALUE,
					sprintf(
						/* translators: %d is a 1-based Q&A item position. */
						__( 'Q&A item #%d question variations must be an array.', 'limb-chatbot' ),
						$position
					)
				);
			}
		}
	}

	/**
	 * Gets the total number of manual knowledge items.
	 *
	 * Since manual knowledge consists of a single item, this method always returns 1.
	 *
	 * @param  array  $config
	 *
	 * @return int Total number of manual knowledge items.
	 *
	 * @since 1.0.0
	 */
	public function get_total( array $config ): int {
		$qa_items = $this->normalize_qa_items( $config['q_a'] ?? [] );
		if ( ! is_array( $qa_items ) ) {
			return 0;
		}

		return count( $qa_items );
	}

	/**
	 * Normalize legacy/new Q&A payloads to a list of items.
	 *
	 * @param  mixed  $qa_payload
	 *
	 * @return array
	 */
	private function normalize_qa_items( $qa_payload ): array {
		if ( ! is_array( $qa_payload ) ) {
			return [];
		}
		if ( isset( $qa_payload['question'] ) || isset( $qa_payload['input'] ) ) {
			$question = trim( (string) ( $qa_payload['question'] ?? $qa_payload['input'] ?? '' ) );
			$answer   = trim( (string) ( $qa_payload['answer'] ?? $qa_payload['output'] ?? '' ) );
			$variations = is_array( $qa_payload['question_variations'] ?? null ) ? $qa_payload['question_variations'] : [];

			return [
				[
					'question'            => $question,
					'question_variations' => $variations,
					'answer'              => $answer,
				],
			];
		}

		return $qa_payload;
	}
}