<?php

namespace Limb_Chatbot\Includes\Data_Schemas;

use Limb_Chatbot\Includes\Exceptions\Error_Codes;
use Limb_Chatbot\Includes\Exceptions\Exception;
use Limb_Chatbot\Includes\Scheme_Interface;
use Limb_Chatbot\Includes\Services\Csv_File_Reader;


/**
 * Class Dataset_Csv_File
 *
 * Handles validation rules for uploading and parsing dataset CSV files.
 * Ensures required structure and file size limits are met.
 *
 * @since 1.0.0
 */
class Dataset_Csv_File implements Scheme_Interface {

	/**
	 * Required column names for a valid dataset CSV.
	 *
	 * @since 1.0.0
	 */
	const REQUIRED_COLUMNS = [ 'input', 'output' ];

	/**
	 * Allowed column prefixes in addition to required ones.
	 * Useful for multi-column inputs like `input_1`, `output_2`, etc.
	 *
	 * @since 1.0.0
	 */
	const COLUMNS_WITH_ALLOWED_PREFIXES = [ 'input', 'output', 'weight' ];

	/**
	 * Maximum allowed file size in bytes (10 MB).
	 *
	 * @since 1.0.0
	 */
	const MAX_FILE_SIZE = 10 * 1024 * 1024;

	/**
	 * Returns validation rules for the dataset CSV upload.
	 *
	 * @return array An array of validation rules for the dataset CSV file.
	 *
	 * @since 1.0.0
	 */
	public static function rules(): array {
		return [
			'file' => [
				'name'              => __( 'Dataset file', 'limb-chatbot' ),
				'type'              => 'file',
				'required'          => true,
				'validate_callback' => function ( $value ): bool {
					$file_path = ! empty( $value['file']['tmp_name'] ) ? $value['file']['tmp_name'] : null;
					if ( ! $file_path || ! is_file( $file_path ) ) {
						throw new Exception( Error_Codes::VALIDATION_INVALID_OR_MISSING_FILE, esc_html__( 'Invalid or missing file upload.', 'limb-chatbot' ) );
					}
					if ( $value['file']['size'] > self::MAX_FILE_SIZE ) {
						// translators: %s is the maximum allowed file size in bytes.
						throw new Exception( Error_Codes::VALIDATION_FILE_SIZE_LIMIT, sprintf( __( 'Filesize exceeds the allowed limit of %s bytes.', 'limb-chatbot' ), self::MAX_FILE_SIZE ) );
					}
					$reader  = new Csv_File_Reader( $file_path, [ 'header_columns' => self::REQUIRED_COLUMNS ] );
					$headers = $reader->open()->get_headers();
					$reader->close();
					foreach ( $headers as $column ) {
						if ( in_array( $column, self::REQUIRED_COLUMNS, true ) ) {
							continue;
						}
						if ( $column === 'weight' ) {
							continue;
						}
						if ( preg_match( '/^(' . implode( '|', self::COLUMNS_WITH_ALLOWED_PREFIXES ) . ')_(\d+)$/', $column ) ) {
							continue;
						}
						// translators: %s is the name of the unexpected column found in the CSV file.
						throw new Exception( Error_Codes::VALIDATION_UNEXPECTED_CSV_COLUMN, sprintf( __( "Unexpected column in CSV: %s", 'limb-chatbot' ), $column ) );
					}

					return true;
				},
			]
		];
	}
}