<?php

declare(strict_types=1);

namespace Australcode\Rewards\Infrastructure\Wallet;

use Australcode\Rewards\Domain\Wallet\ExpiryGateway;
use Australcode\Rewards\Domain\Wallet\Transaction;
use Australcode\Rewards\Domain\Wallet\TransactionStatus;
use Australcode\Rewards\Domain\Wallet\TransactionType;
use Australcode\Rewards\Infrastructure\Database\Schema;

defined( 'ABSPATH' ) || exit;

/**
 * wp_acrwd_transactions-backed expiry gateway: finds Active Earn entries past
 * their expires_at (oldest first) and marks a set of ids Expired.
 */
final class CustomTableExpiryGateway implements ExpiryGateway {

	public function due( string $now ): array {
		global $wpdb;
		$table = Schema::table_name( Schema::TABLE_TRANSACTIONS );

		// phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared -- table from internal Schema constant; values bound.
		$rows = $wpdb->get_results(
			$wpdb->prepare(
				"SELECT * FROM `{$table}` WHERE type = %s AND status = %s AND expires_at IS NOT NULL AND expires_at <= %s ORDER BY expires_at ASC, id ASC",
				TransactionType::Earn->value,
				TransactionStatus::Active->value,
				$now
			),
			ARRAY_A
		);

		$transactions = array();
		if ( is_array( $rows ) ) {
			foreach ( $rows as $row ) {
				if ( is_array( $row ) ) {
					$transactions[] = Transaction::from_row( $row );
				}
			}
		}

		return $transactions;
	}

	public function upcoming( string $from, string $to, int $limit ): array {
		$limit = max( 1, $limit );

		global $wpdb;
		$table = Schema::table_name( Schema::TABLE_TRANSACTIONS );

		// phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared -- table from internal Schema constant; values bound.
		$rows = $wpdb->get_results(
			$wpdb->prepare(
				"SELECT * FROM `{$table}` WHERE type = %s AND status = %s AND expires_at IS NOT NULL AND expires_at >= %s AND expires_at < %s ORDER BY expires_at ASC, id ASC LIMIT %d",
				TransactionType::Earn->value,
				TransactionStatus::Active->value,
				$from,
				$to,
				$limit
			),
			ARRAY_A
		);

		$transactions = array();
		if ( is_array( $rows ) ) {
			foreach ( $rows as $row ) {
				if ( is_array( $row ) ) {
					$transactions[] = Transaction::from_row( $row );
				}
			}
		}

		return $transactions;
	}

	public function mark_expired( array $ids ): void {
		$ids = array_values( array_filter( array_map( 'intval', $ids ), static fn ( int $id ): bool => $id > 0 ) );
		if ( array() === $ids ) {
			return;
		}

		global $wpdb;
		$table        = Schema::table_name( Schema::TABLE_TRANSACTIONS );
		$placeholders = implode( ', ', array_fill( 0, count( $ids ), '%d' ) );

		// phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared -- table + dynamic %d placeholders; values bound.
		$wpdb->query(
			$wpdb->prepare(
				"UPDATE `{$table}` SET status = %s WHERE id IN ({$placeholders})",
				TransactionStatus::Expired->value,
				...$ids
			)
		);
	}
}
