<?php

declare(strict_types=1);

namespace Australcode\Rewards\Rest;

use Australcode\Rewards\Domain\Wallet\Transaction;
use Australcode\Rewards\Domain\Wallet\TransactionType;
use Australcode\Rewards\Service\WalletService;
use WP_REST_Request;
use WP_REST_Response;

defined( 'ABSPATH' ) || exit;

/**
 * REST endpoints under acrwd/v1/wallet:
 *  - GET  /wallet/balance        current user's balance
 *  - GET  /wallet/transactions   current user's ledger (paginated)
 *  - POST /wallet/adjust         admin manual adjustment
 */
final class WalletController extends AbstractController {

	public function __construct( private readonly WalletService $wallet ) {
	}

	public function register(): void {
		add_action( 'rest_api_init', array( $this, 'register_routes' ) );
	}

	public function register_routes(): void {
		register_rest_route(
			self::REST_NAMESPACE,
			'/wallet/balance',
			array(
				'methods'             => 'GET',
				'callback'            => array( $this, 'get_balance' ),
				'permission_callback' => array( $this, 'check_logged_in' ),
			)
		);

		register_rest_route(
			self::REST_NAMESPACE,
			'/wallet/transactions',
			array(
				'methods'             => 'GET',
				'callback'            => array( $this, 'get_transactions' ),
				'permission_callback' => array( $this, 'check_logged_in' ),
				'args'                => array(
					'limit'  => array(
						'type'              => 'integer',
						'default'           => 20,
						'sanitize_callback' => 'absint',
					),
					'offset' => array(
						'type'              => 'integer',
						'default'           => 0,
						'sanitize_callback' => 'absint',
					),
				),
			)
		);

		register_rest_route(
			self::REST_NAMESPACE,
			'/wallet/adjust',
			array(
				'methods'             => 'POST',
				'callback'            => array( $this, 'adjust' ),
				'permission_callback' => array( $this, 'check_admin_permission' ),
				'args'                => array(
					'user_id' => array(
						'type'     => 'integer',
						'required' => true,
					),
					'points'  => array(
						'type'     => 'integer',
						'required' => true,
					),
					'reason'  => array(
						'type'    => 'string',
						'default' => '',
					),
				),
			)
		);
	}

	public function check_logged_in(): bool {
		return is_user_logged_in();
	}

	public function get_balance( WP_REST_Request $request ): WP_REST_Response {
		unset( $request );
		$balance = $this->wallet->get_balance( get_current_user_id() );
		return new WP_REST_Response( $balance->to_row(), 200 );
	}

	public function get_transactions( WP_REST_Request $request ): WP_REST_Response {
		$user_id = get_current_user_id();
		$limit   = max( 1, (int) $request->get_param( 'limit' ) );
		$offset  = max( 0, (int) $request->get_param( 'offset' ) );

		$data = array_map(
			static fn ( Transaction $entry ): array => array(
				'id'            => $entry->id,
				'type'          => $entry->type->value,
				'points_delta'  => $entry->points_delta,
				'balance_after' => $entry->balance_after,
				'order_id'      => $entry->order_id,
				'reason'        => $entry->reason,
				'created_at'    => $entry->created_at,
			),
			$this->wallet->get_transactions( $user_id, $limit, $offset )
		);

		return new WP_REST_Response(
			array(
				'transactions' => $data,
				'total'        => $this->wallet->count_transactions( $user_id ),
			),
			200
		);
	}

	public function adjust( WP_REST_Request $request ): WP_REST_Response {
		$user_id = (int) $request->get_param( 'user_id' );
		$points  = (int) $request->get_param( 'points' );
		$reason  = (string) $request->get_param( 'reason' );

		$entry = $this->wallet->credit(
			$user_id,
			$points,
			TransactionType::Adjust,
			'' !== $reason ? $reason : 'Manual adjustment'
		);

		return new WP_REST_Response(
			array(
				'transaction_id' => $entry->id,
				'balance_after'  => $entry->balance_after,
			),
			200
		);
	}
}
