<?php

/**
 * Class ETM_Machine_Translator_Logger
 *
 * This class handles the logging and tracking of machine translations. It provides methods to log translation
 * requests and maintain the translation counter for quota management.
 */
class ETM_Machine_Translator_Logger {
	/**
	 * An array containing settings options.
	 *
	 * @var array $settings
	 */
	protected $settings;

	/**
	 * The query object for database operations.
	 *
	 * @var object|null $query
	 */
	protected $query;

	/**
	 * The URL converter object.
	 *
	 * @var object|null $url_converter
	 */
	protected $url_converter;

	/**
	 * The counter to keep track of characters used for machine translation.
	 *
	 * @var int $counter
	 */
	protected $counter;

	/**
	 * The date associated with the machine translation counter.
	 *
	 * @var string $counter_date
	 */
	protected $counter_date;

	/**
	 * The character limit for machine translations.
	 *
	 * @var int $limit
	 */
	protected $limit;

	/**
	 * ETM_Machine_Translator_Logger constructor.
	 *
	 * @param array $settings Settings option.
	 */
	public function __construct( $settings ) {
		$this->settings     = $settings;
		$this->counter      = intval( $this->get_mt_option( 'machine_translation_counter', 0 ) );
		$this->counter_date = $this->get_mt_option( 'machine_translation_counter_date', date( 'Y-m-d' ) );
		$this->limit        = intval( $this->get_mt_option( 'machine_translation_limit', 1000000 ) );
		// If a new day has passed, update the counter and date
		$this->maybe_reset_counter_date();
	}

	/**
	 * Logs the machine translation request and saves it to the database.
	 *
	 * @param array $args An array containing translation request details.
	 * @return bool True on successful logging, false on failure.
	 */
	public function log( $args = array() ) {
		$etm = ETM_eTranslation_Multilingual::get_etm_instance();

		if ( ! $this->query ) {
			$this->query = $etm->get_component( 'query' );
		}

		if ( ! $this->url_converter ) {
			$this->url_converter = $etm->get_component( 'url_converter' );
		}

		if ( empty( $args ) ) {
			return false;
		}

		if ( $this->get_mt_option( 'machine_translation_log', false ) !== 'yes' ) {
			return false;
		}

		if ( ! $this->query->check_machine_translation_log_table() ) {
			return false;
		}

		// Expected structure.
		$log = array(
			'url'         => $this->url_converter->cur_page_url(),
			'strings'     => $args['strings'],
			'characters'  => $this->count( unserialize( $args['strings'] ) ),
			'response'    => $args['response'],
			'lang_source' => $args['lang_source'],
			'lang_target' => $args['lang_target'],
			'timestamp'   => date( 'Y-m-d H:i:s' ),
		);

		$table_name = $this->query->db->prefix . 'etm_machine_translation_log';

		$query = "INSERT INTO `$table_name` ( `url`, `strings`, `characters`, `response`, `lang_source`, `lang_target`, `timestamp` ) VALUES (%s, %s, %s, %s, %s, %s, %s)";

		$prepared_query = $this->query->db->prepare( $query, $log );
		$this->query->db->get_results( $prepared_query, OBJECT_K );

		if ( $this->query->db->last_error !== '' ) {
			return false;
		}

		return true;
	}

	/**
	 * Counts the number of characters in the given strings array.
	 *
	 * @param array $strings An array of strings to be counted.
	 * @return int The total number of characters in the strings.
	 */
	private function count( $strings ) {
		if ( ! is_array( $strings ) ) {
			return 0;
		}

		$char_number = 0;
		foreach ( $strings as $string ) {
			$char_number += strlen( $string );
		}

		return $char_number;
	}

	/**
	 * Updates the translation counter with the number of characters from the given strings.
	 *
	 * @param array $strings An array of strings to count towards the quota.
	 * @return int The updated translation counter.
	 */
	public function count_towards_quota( $strings ) {
		$this->counter += $this->count( $strings );

		$this->update_options(
			array(
				array(
					'name'  => 'machine_translation_counter',
					'value' => $this->counter,
				),
			)
		);

		return $this->counter;
	}

	/**
	 * Checks if the machine translation quota has been exceeded.
	 *
	 * @return bool Always returns false since the quota feature is not implemented.
	 */
	public function quota_exceeded() {
		return false;
	}

	/**
	 * Resets the translation counter and date if a new day has passed.
	 *
	 * @return bool True on successful reset, false otherwise.
	 */
	public function maybe_reset_counter_date() {
		// If the day has not passed
		if ( $this->counter_date === date( 'Y-m-d' ) ) {
			return false;
		}

		$options = array(
			// There is a new day
			array(
				'name'  => 'machine_translation_counter_date',
				'value' => date( 'Y-m-d' ),
			),
			// Clear the counter
			array(
				'name'  => 'machine_translation_counter',
				'value' => 0,
			),
			// Clear the notification
			array(
				'name'  => 'machine_translation_trigger_quota_notification',
				'value' => false,
			),
		);

		$this->update_options( $options );

		return true;
	}

	/**
	 * Retrieves the value of the specified machine translation option.
	 *
	 * @param string $option_name The name of the machine translation option to retrieve.
	 * @param mixed  $default The default value to return if the option is not set.
	 * @return mixed The value of the option if set, otherwise the default value.
	 */
	private function get_mt_option( $option_name, $default ) {
		return isset( $this->settings['etm_machine_translation_settings'][ $option_name ] ) ? $this->settings['etm_machine_translation_settings'][ $option_name ] : $default;
	}

	/**
	 * Updates the specified machine translation options and saves them to the database.
	 *
	 * @param array $options An array of option names and their corresponding values to update.
	 * @return void
	 */
	private function update_options( $options ) {
		$machine_translation_settings = $this->settings['etm_machine_translation_settings'];

		foreach ( $options as $option ) {
			$this->settings['etm_machine_translation_settings'][ $option['name'] ] = $option['value'];
			$machine_translation_settings[ $option['name'] ]                       = $option['value'];
		}

		update_option( 'etm_machine_translation_settings', $machine_translation_settings );
	}

	/**
	 * Sanitizes the machine translation settings.
	 *
	 * @param array $mt_settings An array of machine translation settings to sanitize.
	 * @return array The sanitized machine translation settings.
	 */
	public function sanitize_settings( $mt_settings ) {
		$machine_translation_settings = $this->settings['etm_machine_translation_settings'];

		if ( isset( $machine_translation_settings['machine_translation_counter'] ) ) {
			$mt_settings['machine_translation_counter'] = $machine_translation_settings['machine_translation_counter'];
		}

		if ( isset( $machine_translation_settings['machine_translation_counter_date'] ) ) {
			$mt_settings['machine_translation_counter_date'] = $machine_translation_settings['machine_translation_counter_date'];
		}

		if ( ! empty( $mt_settings['machine_translation_log'] ) ) {
			$mt_settings['machine_translation_log'] = sanitize_text_field( $mt_settings['machine_translation_log'] );
		} else {
			$mt_settings['machine_translation_log'] = 'no';
		}

		return $mt_settings;
	}
}
