<?php
/**
 * Model: Notification.php.
 *
 * @package RewardsWP
 */

namespace Awesomemotive\Rewardswp\Models;

if ( ! defined( 'ABSPATH' ) ) {
	exit;
}

use Awesomemotive\Rewardswp\Abstracts\AbstractModel;
use Awesomemotive\Rewardswp\Database\DatabaseHandler;
use Awesomemotive\Rewardswp\Database\Tables\NotificationsTable;
use InvalidArgumentException;

/**
 * Class Notification
 *
 * Represents a notification entity and handles database interactions.
 *
 * @since 1.1.0
 */
class Notification extends AbstractModel {

	/**
	 * Allowed notification types.
	 *
	 * @since 1.1.0
	 * @var array
	 */
	public const ALLOWED_TYPES = [ 'success', 'warning', 'error', 'info' ];

	/**
	 * WordPress database handler.
	 *
	 * @since 1.1.0
	 * @var DatabaseHandler
	 */
	protected DatabaseHandler $db_handler;

	/**
	 * Notifications table instance.
	 *
	 * @since 1.1.0
	 * @var NotificationsTable
	 */
	protected NotificationsTable $db_table;

	/**
	 * Notification ID.
	 *
	 * @since 1.1.0
	 * @var int
	 */
	public int $id = 0;

	/**
	 * Remote notification ID from the feed.
	 *
	 * @since 1.1.0
	 * @var string
	 */
	public string $remote_id = '';

	/**
	 * Notification title.
	 *
	 * @since 1.1.0
	 * @var string
	 */
	public string $title = '';

	/**
	 * Notification content/message.
	 *
	 * @since 1.1.0
	 * @var string
	 */
	public string $content = '';

	/**
	 * Notification buttons (JSON encoded array).
	 *
	 * @since 1.1.0
	 * @var string|null
	 */
	public ?string $buttons = null;

	/**
	 * Notification type (success, warning, error, info).
	 *
	 * @since 1.1.0
	 * @var string
	 */
	public string $type = 'success';

	/**
	 * Display conditions - JSON array of license levels (e.g., ["basic", "plus"]).
	 * If NULL or empty, shows to all license levels.
	 *
	 * @since 1.1.0
	 * @var string|null
	 */
	public ?string $conditions = null;

	/**
	 * Start date for displaying the notification.
	 *
	 * @since 1.1.0
	 * @var string|null
	 */
	public ?string $start = null;

	/**
	 * End date for displaying the notification.
	 *
	 * @since 1.1.0
	 * @var string|null
	 */
	public ?string $end = null;

	/**
	 * Whether the notification has been dismissed.
	 *
	 * @since 1.1.0
	 * @var int
	 */
	public int $dismissed = 0;

	/**
	 * Date the notification was created.
	 *
	 * @since 1.1.0
	 * @var string|null
	 */
	public ?string $created_at = null;

	/**
	 * Date the notification was last updated.
	 *
	 * @since 1.1.0
	 * @var string|null
	 */
	public ?string $updated_at = null;

	/**
	 * Notification constructor.
	 *
	 * @since 1.1.0
	 *
	 * @param DatabaseHandler    $db_handler Database handler instance.
	 * @param NotificationsTable $db_table   Notifications table instance.
	 */
	public function __construct( DatabaseHandler $db_handler, NotificationsTable $db_table ) {
		$this->db_handler = $db_handler;
		$this->db_table   = $db_table;
	}

	/**
	 * Retrieve the labels for the model columns.
	 *
	 * @since 1.1.0
	 * @return array The notification labels.
	 */
	public function get_labels(): array {
		return $this->db_table->get_columns();
	}

	/**
	 * Sanitize notification data.
	 *
	 * Must be used before saving data into the database.
	 *
	 * @since 1.1.0
	 * @return void
	 */
	public function sanitize(): void {
		$this->remote_id  = sanitize_text_field( $this->remote_id );
		$this->title      = sanitize_text_field( $this->title );
		$this->content    = wp_kses_post( $this->content );
		$this->buttons    = ! empty( $this->buttons ) ? sanitize_text_field( $this->buttons ) : null;
		$this->type       = sanitize_text_field( $this->type );
		$this->conditions = ! empty( $this->conditions ) ? sanitize_text_field( $this->conditions ) : null;
		$this->start      = ! empty( $this->start ) ? sanitize_text_field( $this->start ) : null;
		$this->end        = ! empty( $this->end ) ? sanitize_text_field( $this->end ) : null;
		$this->dismissed  = (int) $this->dismissed;
		$this->created_at = ! empty( $this->created_at ) ? sanitize_text_field( $this->created_at ) : null;
		$this->updated_at = ! empty( $this->updated_at ) ? sanitize_text_field( $this->updated_at ) : null;
	}

	/**
	 * Validates the notification data before creating.
	 *
	 * @since 1.1.0
	 *
	 * @return bool When validates successfully.
	 * @throws InvalidArgumentException If validation fails.
	 */
	public function validate_create(): bool {
		if ( empty( $this->remote_id ) ) {
			throw new InvalidArgumentException( esc_html__( 'Remote ID is required.', 'rewardswp' ) );
		}

		if ( empty( $this->title ) ) {
			throw new InvalidArgumentException( esc_html__( 'Title is required.', 'rewardswp' ) );
		}

		if ( empty( $this->content ) ) {
			throw new InvalidArgumentException( esc_html__( 'Content is required.', 'rewardswp' ) );
		}

		// Validate type is one of the allowed values.
		if ( ! in_array( $this->type, self::ALLOWED_TYPES, true ) ) {
			throw new InvalidArgumentException( esc_html__( 'Invalid notification type.', 'rewardswp' ) );
		}

		return true;
	}

	/**
	 * Validates the notification data before updating.
	 *
	 * @since 1.1.0
	 *
	 * @return bool When validates successfully.
	 * @throws InvalidArgumentException If validation fails.
	 */
	public function validate_update(): bool {
		if ( empty( $this->id ) ) {
			throw new InvalidArgumentException( esc_html__( 'Notification ID is required for update.', 'rewardswp' ) );
		}

		return $this->validate_create();
	}

	/**
	 * Get buttons as array.
	 *
	 * Decodes the JSON buttons string into an array.
	 *
	 * @since 1.1.0
	 * @return array Buttons array or empty array if none.
	 */
	public function get_buttons_array(): array {
		if ( empty( $this->buttons ) ) {
			return [];
		}

		$decoded = json_decode( $this->buttons, true );

		return is_array( $decoded ) ? $decoded : [];
	}

	/**
	 * Set buttons from array.
	 *
	 * Encodes the buttons array as JSON string.
	 *
	 * @since 1.1.0
	 * @param array $buttons Buttons array.
	 * @return void
	 */
	public function set_buttons_array( array $buttons ): void {
		$this->buttons = ! empty( $buttons ) ? wp_json_encode( $buttons ) : null;
	}

	/**
	 * Get conditions as array.
	 *
	 * Decodes the JSON conditions string into an array.
	 *
	 * @since 1.1.0
	 * @return array Conditions array or empty array if none.
	 */
	public function get_conditions_array(): array {
		if ( empty( $this->conditions ) ) {
			return [];
		}

		$decoded = json_decode( $this->conditions, true );

		return is_array( $decoded ) ? $decoded : [];
	}

	/**
	 * Set conditions from array.
	 *
	 * Encodes the conditions array as JSON string.
	 *
	 * @since 1.1.0
	 * @param array $conditions Conditions array.
	 * @return void
	 */
	public function set_conditions_array( array $conditions ): void {
		$this->conditions = ! empty( $conditions ) ? wp_json_encode( $conditions ) : null;
	}

	/**
	 * Check if notification is active for given license.
	 *
	 * @since 1.1.0
	 *
	 * @param string $current_license Current license tier.
	 * @return bool True if active, false otherwise.
	 */
	public function is_active( string $current_license ): bool {
		$current_time = \Awesomemotive\Rewardswp\Helpers\get_current_time();

		// Check start date (null or <= current time).
		if ( ! empty( $this->start ) && $this->start > $current_time ) {
			return false;
		}

		// Check end date (null or >= current time).
		if ( ! empty( $this->end ) && $this->end < $current_time ) {
			return false;
		}

		// Check license level in conditions array.
		if ( ! empty( $this->conditions ) ) {
			$license_levels = $this->get_conditions_array();

			// If it's an array of license levels, check if current license is in it.
			if ( ! empty( $license_levels ) && is_array( $license_levels ) ) {
				return in_array( $current_license, $license_levels, true );
			}
		}

		// If conditions is null/empty, show to all.
		return true;
	}
}
