<?php

namespace Limb_Chatbot\Includes\Data_Objects;

/**
 * Class Limit
 *
 * Represents a usage limit in the chatbot system.
 *
 * @since 1.0.0
 */
class Limit extends WPDB_Data_Object {

	/**
	 * @since 1.0.0
	 */
	const TYPE_USER = 'user';

	/**
	 * @since 1.0.0
	 */
	const TYPE_GUEST = 'guest';

	/**
	 * @since 1.0.0
	 */
	const TYPE_INPUT = 'input';

	/**
	 * @since 1.0.0
	 */
	const TYPE_GENERAL = 'general';

	/**
	 * Unit constant for tokens.
	 *
	 * @since 1.0.0
	 */
	const UNIT_TOKEN = 1;

	/**
	 * Unit constant for messages per chat.
	 *
	 * @since 1.0.0
	 */
	const UNIT_MESSAGE_PER_CHAT = 2;

	/**
	 * Unit constant for new chat count.
	 *
	 * @since 1.0.0
	 */
	const UNIT_NEW_CHAT = 4;

	/**
	 * Unit constant for cost.
	 *
	 * @since 1.0.0
	 */
	const UNIT_COST = 3;

	/**
	 * Unit constant for word count of input message.
	 *
	 * @since 1.0.0
	 */
	const UNIT_WORD = 5;

	/**
	 * Unit constant for total messages sent per day across all chats.
	 *
	 * @since 1.0.0
	 */
	const UNIT_MESSAGE_PER_DAY = 6;

	/**
	 * Error key for rate-based limits (new_chat, messages_per_day, messages_per_chat, token, cost).
	 *
	 * @since 1.2.0
	 */
	const ERROR_KEY_RATE_LIMIT = 'rate_limit';

	/**
	 * Error key for input-based limits (word count).
	 *
	 * @since 1.2.0
	 */
	const ERROR_KEY_INPUT_LIMIT = 'input_limit';

	/**
	 * Status enabled.
	 *
	 * @since 1.0.0
	 */
	const STATUS_ENABLED = 1;

	/**
	 * Status disabled.
	 *
	 * @since 1.0.0
	 */
	const STATUS_DISABLED = 0;

	/**
	 * The type of the limit.
	 *
	 * @var string
	 * @since 1.0.0
	 */
	public string $type;

	/**
	 * The unit type of the limit.
	 *
	 * @var int|null
	 * @since 1.0.0
	 */
	public ?int $unit;

	/**
	 * The value of the limit.
	 *
	 * @var float
	 * @since 1.0.0
	 */
	public float $value;

	/**
	 * The period (in seconds or defined unit) for the limit.
	 *
	 * @var int|null
	 * @since 1.0.0
	 */
	public ?int $period;


	/**
	 * The error message for the limit
	 *
	 * @var int|null
	 * @since 1.0.0
	 */
	public ?string $error_message;

	/**
	 * The status of the limit (enabled/disabled).
	 *
	 * @var int
	 * @since 1.0.0
	 */
	public int $status = self::STATUS_DISABLED;

	/**
	 * Associated Chatbot instance.
	 *
	 * @var Chatbot|null
	 * @since 1.0.0
	 */
	public ?Chatbot $chatbot = null;

	/**
	 * Get the type of the limit.
	 *
	 * @return string
	 * @since 1.0.0
	 */
	public function get_type(): string {
		return $this->type;
	}

	/**
	 * Set the type of the limit.
	 *
	 * @param  string  $type
	 *
	 * @return void
	 * @since 1.0.0
	 */
	public function set_type( string $type ): void {
		$this->type = $type;
	}

	/**
	 * Get the value of the limit.
	 *
	 * @return float
	 * @since 1.0.0
	 */
	public function get_value(): float {
		return $this->value;
	}

	/**
	 * Set the value of the limit.
	 *
	 * @param  float  $value
	 *
	 * @return void
	 * @since 1.0.0
	 */
	public function set_value( float $value ): void {
		$this->value = $value;
	}

	/**
	 * Get the period of the limit.
	 *
	 * @return int|null
	 * @since 1.0.0
	 */
	public function get_period(): ?int {
		return $this->period;
	}

	/**
	 * Set the period of the limit.
	 *
	 * @param  int|null  $period
	 *
	 * @return void
	 * @since 1.0.0
	 */
	public function set_period( ?int $period ): void {
		$this->period = $period;
	}

	/**
	 * Get the unit type of the limit.
	 *
	 * @return int|null
	 * @since 1.0.0
	 */
	public function get_unit(): ?int {
		return $this->unit;
	}

	/**
	 * Set the unit type of the limit.
	 *
	 * @param  int|null  $unit
	 *
	 * @return void
	 * @since 1.0.0
	 */
	public function set_unit( ?int $unit ): void {
		$this->unit = $unit;
	}

	/**
	 * Get the status of the limit.
	 *
	 * @return int
	 * @since 1.0.0
	 */
	public function get_status(): int {
		return $this->status;
	}

	/**
	 * Set the status of the limit.
	 *
	 * @param  int  $status
	 *
	 * @return void
	 * @since 1.0.0
	 */
	public function set_status( int $status ): void {
		$this->status = $status;
	}

	/**
	 * Get the error message for the limit.
	 *
	 * @return string|null
	 * @since 1.0.0
	 */
	public function get_error_message(): ?string {
		return $this->error_message;
	}

	/**
	 * Set the error message for the limit.
	 *
	 * @param string|null $error_message The error message.
	 *
	 * @return void
	 * @since 1.0.0
	 */
	public function set_error_message( ?string $error_message ): void {
		$this->error_message = $error_message;
	}

	/**
	 * Resolves the error key for a given unit.
	 *
	 * @param int $unit The unit constant.
	 *
	 * @return string The error key (rate_limit or input_limit).
	 * @since 1.2.0
	 */
	public static function resolve_error_key_for_unit( int $unit ): string {
		if ( $unit === self::UNIT_WORD ) {
			return self::ERROR_KEY_INPUT_LIMIT;
		}

		return self::ERROR_KEY_RATE_LIMIT;
	}

	/**
	 * Check if the limit is enabled.
	 *
	 * @return bool True if enabled, false otherwise.
	 * @since 1.0.0
	 */
	public function is_enabled(): bool {
		return $this->status === self::STATUS_ENABLED;
	}

	/**
	 * Get the associated Chatbot instance.
	 *
	 * @return Chatbot|null
	 * @since 1.0.0
	 */
	public function get_chatbot(): ?Chatbot {
		return $this->chatbot;
	}

	/**
	 * Set the associated Chatbot instance.
	 *
	 * @param  Chatbot|null  $chatbot
	 *
	 * @return void
	 * @since 1.0.0
	 */
	public function set_chatbot( ?Chatbot $chatbot ): void {
		$this->chatbot = $chatbot;
	}

	/**
	 * Get the usage key string for this limit based on unit.
	 *
	 * @return string
	 * @since 1.0.0
	 */
	public function get_usage_key(): string {
		$unit_mapper = [
			self::UNIT_NEW_CHAT        => 'new_chat',
			self::UNIT_WORD            => 'words',
			self::UNIT_MESSAGE_PER_DAY => 'messages_per_day',
		];

		return 'current_' . $unit_mapper[ $this->unit ] . '_usage';
	}
}
