<?php
/**
 * Order magic-link token persistence.
 *
 * @package WPDudeProducts
 */

declare(strict_types=1);

namespace WPDude\Products\Access;

/**
 * Persist hashed order view tokens.
 */
final class Order_Token_Repository {

	/**
	 * Table name.
	 */
	public function table(): string {
		global $wpdb;
		return $wpdb->prefix . 'wpdude_dc_order_tokens';
	}

	/**
	 * Create a token row.
	 *
	 * @param array<string, mixed> $data Data.
	 */
	public function create( array $data ): int {
		global $wpdb;
		$row = array_merge(
			array(
				'created_at' => current_time( 'mysql', true ),
			),
			$data
		);
		// phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery
		$wpdb->insert( $this->table(), $row );
		return (int) $wpdb->insert_id;
	}

	/**
	 * Find by token hash.
	 *
	 * @return array<string, mixed>|null
	 */
	public function find_by_hash( string $hash ): ?array {
		global $wpdb;
		// phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching
		$row = $wpdb->get_row(
			$wpdb->prepare( 'SELECT * FROM %i WHERE token_hash = %s', $this->table(), $hash ),
			ARRAY_A
		);
		return $row ?: null;
	}

	/**
	 * Find latest token for an order.
	 *
	 * @return array<string, mixed>|null
	 */
	public function find_by_order( int $order_id ): ?array {
		global $wpdb;
		// phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching
		$row = $wpdb->get_row(
			$wpdb->prepare(
				'SELECT * FROM %i WHERE order_id = %d ORDER BY id DESC LIMIT 1',
				$this->table(),
				$order_id
			),
			ARRAY_A
		);
		return $row ?: null;
	}

	/**
	 * Replace the token hash (re-issue for emails / cache miss).
	 */
	public function update_token_hash( int $id, string $hash ): void {
		global $wpdb;
		// phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching
		$wpdb->update(
			$this->table(),
			array( 'token_hash' => $hash ),
			array( 'id' => $id ),
			array( '%s' ),
			array( '%d' )
		);
	}
}
