<?php

namespace Limb_Chatbot\Includes\Services;

use Limb_Chatbot\Includes\Data_Objects\Dataset;
use Limb_Chatbot\Includes\Data_Objects\Dataset_Entry;

/**
 * Parses rows from a CSV file and converts them into `Dataset_Entry` instances.
 *
 * This class supports parsing multiple input/output message pairs along with optional weights,
 * constructing structured dataset entries for AI training or analysis.
 *
 * @since 1.0.0
 */
class Dataset_Csv_File_Parser {

	/**
	 * Parses a single CSV row and returns a `Dataset_Entry` object.
	 *
	 * This method extracts `dataset_id`, `instruction`, and an arbitrary number of
	 * `input`, `output`, and `weight` pairs from the CSV row and assembles them into
	 * a structured `Dataset_Entry`.
	 *
	 * Supported column formats:
	 * - `dataset_id`
	 * - `instruction`
	 * - `input`, `output`, `weight` (for the first message)
	 * - `input_1`, `output_1`, `weight_1`, `input_2`, ... (for additional messages)
	 *
	 * @since 1.0.0
	 *
	 * @param array         $row     Associative array representing a CSV row.
	 * @param Dataset|null  $dataset Optional dataset object to inherit `dataset_id` from.
	 * @return Dataset_Entry|null    Returns a dataset entry object or null if invalid.
	 */
	public function parse_row( array $row, ?Dataset $dataset = null ): ?Dataset_Entry {
		$dataset_id = $row['dataset_id'] ?? ( $dataset ? $dataset->get_id() : null );
		if ( empty( $dataset_id ) ) {
			return null;
		}
		$entry = [ 'system' => $row['instruction'] ?? '', 'messages' => [], ];
		$index = 0;
		while ( true ) {
			$input_key  = $index === 0 ? 'input' : "input_{$index}";
			$output_key = $index === 0 ? 'output' : "output_{$index}";
			$weight_key = $index === 0 ? 'weight' : "weight_{$index}";
			if ( ( ! isset( $row[ $input_key ] ) || empty( trim( $row[ $input_key ] ) ) ) || ( ! isset( $row[ $output_key ] ) || empty( trim( $row[ $output_key ] ) ) ) ) {
				break;
			}
			$message = [
				'input'  => $row[ $input_key ],
				'output' => $row[ $output_key ],
				'weight' => isset( $row[ $weight_key ] ) ? (int) $row[ $weight_key ] : 1,
			];
			if ( isset( $row[ $weight_key ] ) && $row[ $weight_key ] ) {
				$message['weight'] = (int) $row[ $weight_key ];
			}
			$entry['messages'][] = $message;
			$index ++;
		}

		return Dataset_Entry::make( [ 'dataset_id' => $dataset_id, 'entry' => $entry, ] );
	}
}
