<?php

declare(strict_types=1);

namespace Australcode\Rewards\Domain\Wallet;

defined( 'ABSPATH' ) || exit;

/**
 * Immutable ledger entry. One row in wp_acrwd_transactions.
 *
 * points_delta is signed: positive for Earn/positive Adjust, negative for
 * Redeem/Expire/Refund. balance_after is the running balance immediately after
 * this entry was applied (denormalized for fast history rendering).
 */
final class Transaction {

	public function __construct(
		public readonly ?int $id,
		public readonly int $user_id,
		public readonly TransactionType $type,
		public readonly int $points_delta,
		public readonly int $balance_after,
		public readonly ?int $order_id = null,
		public readonly ?int $rule_id = null,
		public readonly string $reason = '',
		public readonly ?string $expires_at = null,
		public readonly TransactionStatus $status = TransactionStatus::Active,
		public readonly ?string $created_at = null,
	) {
	}

	/**
	 * @param array<string,mixed> $row
	 */
	public static function from_row( array $row ): self {
		return new self(
			id: isset( $row['id'] ) ? (int) $row['id'] : null,
			user_id: (int) ( $row['user_id'] ?? 0 ),
			type: TransactionType::tryFrom( (string) ( $row['type'] ?? 'adjust' ) ) ?? TransactionType::Adjust,
			points_delta: (int) ( $row['points_delta'] ?? 0 ),
			balance_after: (int) ( $row['balance_after'] ?? 0 ),
			order_id: isset( $row['order_id'] ) ? (int) $row['order_id'] : null,
			rule_id: isset( $row['rule_id'] ) ? (int) $row['rule_id'] : null,
			reason: (string) ( $row['reason'] ?? '' ),
			expires_at: isset( $row['expires_at'] ) ? (string) $row['expires_at'] : null,
			status: TransactionStatus::tryFrom( (string) ( $row['status'] ?? 'active' ) ) ?? TransactionStatus::Active,
			created_at: isset( $row['created_at'] ) ? (string) $row['created_at'] : null,
		);
	}

	/**
	 * Row for persistence (id and created_at are assigned by the DB layer).
	 *
	 * @return array<string,mixed>
	 */
	public function to_row(): array {
		return array(
			'user_id'       => $this->user_id,
			'type'          => $this->type->value,
			'points_delta'  => $this->points_delta,
			'balance_after' => $this->balance_after,
			'order_id'      => $this->order_id,
			'rule_id'       => $this->rule_id,
			'reason'        => $this->reason,
			'expires_at'    => $this->expires_at,
			'status'        => $this->status->value,
		);
	}
}
