<?php
declare( strict_types=1 );

namespace FiboFilters\Struct;

use FiboFilters\Util\Helpers;

/**
 * Immutable runtime context passed to DB queries.
 *
 * ## Example
 * ```php
 * $ctx = new QueryContext( 'pl', 'tmp', true );
 * ```
 */
final class QueryContext {
	/** Main (production) index. */
	public const ROLE_MAIN = 'main';

	/** Temporary index used during rebuild. */
	public const ROLE_TMP = 'tmp';

	/**
	 * Two‑letter language code, '' means "default".
	 *
	 * @var string
	 */
	private string $lang = '';

	/**
	 * Index role – one of self::ROLE_*.
	 *
	 * @var string
	 */
	private string $index_role = self::ROLE_MAIN;

	/**
	 * Should the query run against the secondary DB connection?
	 *
	 * @var bool
	 */
	private bool $wpdb_second;

	/**
	 * Constructor.
	 *
	 * @param string $lang         Two‑letter language code ('' for default).
	 * @param string $index_role   Either self::ROLE_MAIN or self::ROLE_TMP.
	 * @param bool   $wpdb_second  Whether to use the secondary DB.
	 */
	public function __construct(
		string $lang = '',
		string $index_role = self::ROLE_MAIN,
		bool $wpdb_second = false
	) {
		$this->set_lang( $lang );
		$this->set_index_role( $index_role );
		$this->wpdb_second = $wpdb_second;
	}

	/**
	 * Returns a string representation of the context.
	 */
	public function __toString(): string {
		$lang = empty( $this->get_lang() ) ? 'no-lang' : $this->get_lang();

		return $lang . '_' . $this->get_index_role() . '_' . ( $this->is_wpdb_second() ? '2nd' : '1st' );
	}

	/**
	 * Gets the language code.
	 *
	 * @return string
	 */
	public function get_lang(): string {
		return $this->lang;
	}

	/**
	 * Gets the index role.
	 *
	 * @return string
	 */
	public function get_index_role(): string {
		return $this->index_role;
	}

	/**
	 * Returns true when secondary DB should be used.
	 *
	 * @return bool
	 */
	public function is_wpdb_second(): bool {
		return $this->wpdb_second;
	}

	/**
	 * Validates and sets language.
	 *
	 * Silently resets to '' when invalid.
	 *
	 * @param string $lang Language code to set.
	 * @return void
	 */
	private function set_lang( string $lang ): void {
		if ( '' !== $lang && ! Helpers::is_language_code( $lang ) ) {
			$lang = '';
		}
		$this->lang = $lang;
	}

	/**
	 * Validates and sets an index role.
	 *
	 * Silently resets to self::ROLE_MAIN when invalid.
	 *
	 * @param string $index_role Index role to set.
	 * @return void
	 */
	private function set_index_role( string $index_role ): void {
		if ( ! in_array( $index_role, [ self::ROLE_MAIN, self::ROLE_TMP ], true ) ) {
			$index_role = self::ROLE_MAIN;
		}
		$this->index_role = $index_role;
	}
}
