<?php

declare(strict_types=1);

namespace Australcode\Rewards\Frontend;

use Australcode\Rewards\Domain\Settings\SettingsRepository;
use Australcode\Rewards\Service\RedemptionService;
use Australcode\Rewards\Service\WalletService;

defined( 'ABSPATH' ) || exit;

/**
 * Adds a "Rewards" tab to WooCommerce My Account showing the customer's balance
 * and points history. The rewrite endpoint is registered on init; rewrite rules
 * flush on the first init after activation (acrwd_flush_rewrite option set by
 * the Activator) and whenever the endpoint slug changes, so the URL works
 * without the admin re-saving permalinks.
 */
final class MyAccountRewards {

	public const ENDPOINT = 'rewards';

	public function __construct(
		private readonly WalletService $wallet,
		private readonly SettingsRepository $settings,
		private readonly RedeemFormRenderer $redeem_form,
		private readonly RedemptionService $redemption,
	) {
	}

	public function register(): void {
		add_action( 'init', array( $this, 'add_endpoint' ) );
		add_filter( 'query_vars', array( $this, 'add_query_var' ) );
		add_filter( 'woocommerce_account_menu_items', array( $this, 'add_menu_item' ) );
	}

	public function add_endpoint(): void {
		$endpoint = $this->endpoint();
		add_rewrite_endpoint( $endpoint, EP_ROOT | EP_PAGES );
		// Registered on init (not construction time) so themes can hook the
		// acrwd_account_endpoint filter from functions.php before it resolves.
		add_action( 'woocommerce_account_' . $endpoint . '_endpoint', array( $this, 'render_content' ) );

		if ( '' !== (string) get_option( 'acrwd_flush_rewrite', '' ) || get_option( 'acrwd_registered_endpoint' ) !== $endpoint ) {
			flush_rewrite_rules();
			delete_option( 'acrwd_flush_rewrite' );
			update_option( 'acrwd_registered_endpoint', $endpoint );
		}
	}

	/**
	 * Endpoint slug, filterable for sites where "rewards" collides with another
	 * plugin or needs localising.
	 */
	private function endpoint(): string {
		$endpoint = (string) apply_filters( 'acrwd_account_endpoint', self::ENDPOINT );
		return '' !== $endpoint ? $endpoint : self::ENDPOINT;
	}

	/**
	 * @param string[] $vars
	 * @return string[]
	 */
	public function add_query_var( array $vars ): array {
		$vars[] = $this->endpoint();
		return $vars;
	}

	/**
	 * Inserts the Rewards item just before Logout.
	 *
	 * @param array<string,string> $items
	 * @return array<string,string>
	 */
	public function add_menu_item( array $items ): array {
		if ( ! $this->settings->get()->show_account_tab ) {
			return $items;
		}

		$logout = null;
		if ( isset( $items['customer-logout'] ) ) {
			$logout = $items['customer-logout'];
			unset( $items['customer-logout'] );
		}

		$items[ $this->endpoint() ] = __( 'Rewards', 'australcode-points-rewards' );

		if ( null !== $logout ) {
			$items['customer-logout'] = $logout;
		}

		return $items;
	}

	public function render_content(): void {
		if ( ! is_user_logged_in() || ! $this->settings->get()->show_account_tab ) {
			return;
		}

		$user_id  = get_current_user_id();
		$balance  = $this->wallet->get_balance( $user_id );
		$settings = $this->settings->get();

		echo '<div class="acrwd-rewards">';
		echo '<div class="acrwd-rewards-summary">';
		echo '<div class="acrwd-rewards-card"><div class="acrwd-stat">'
			. esc_html( number_format_i18n( $balance->points_balance ) ) . '</div><div>'
			. esc_html__( 'Available points', 'australcode-points-rewards' ) . '</div>';
		// Show what the balance is worth in money (A4) — reuses the redemption rate
		// so customers see the real value of their points, not just a count.
		if ( $settings->show_points_value && $settings->redemption_enabled ) {
			$value = $this->redemption->points_to_amount( $balance->points_balance );
			if ( $value > 0 ) {
				echo '<div class="acrwd-rewards-value">' . sprintf(
					/* translators: %s: the money value of the points balance (e.g. $10.00). */
					esc_html__( 'worth about %s', 'australcode-points-rewards' ),
					wp_kses_post( wc_price( $value ) )
				) . '</div>';
			}
		}
		echo '</div>';
		printf(
			'<div class="acrwd-rewards-card"><div class="acrwd-stat">%s</div><div>%s</div></div>',
			esc_html( number_format_i18n( $balance->lifetime_earned ) ),
			esc_html__( 'Total earned', 'australcode-points-rewards' )
		);
		echo '</div>';

		/**
		 * Fires in the My Account Rewards tab after the balance summary. The Pro
		 * VIP-tier renderer (TierProgressRenderer) hooks this to show the tier badge
		 * and progress-to-next-tier bar; stripped (no listener) in the free build, so
		 * the seam keeps MyAccountRewards free of any Pro coupling.
		 *
		 * @param int                                          $user_id Customer id.
		 * @param \Australcode\Rewards\Domain\Wallet\Balance $balance The customer's current balance.
		 */
		do_action( 'acrwd_myaccount_after_summary', $user_id, $balance );

		$this->redeem_form->render( $user_id );
		$this->render_history( $user_id );

		echo '</div>';
	}

	private function render_history( int $user_id ): void {
		$entries = $this->wallet->get_transactions( $user_id, 20 );
		if ( array() === $entries ) {
			echo '<p class="acrwd-history-empty">' . esc_html__( 'No points activity yet.', 'australcode-points-rewards' ) . '</p>';
			return;
		}

		echo '<table class="acrwd-history"><thead><tr>';
		printf(
			'<th>%s</th><th>%s</th><th>%s</th>',
			esc_html__( 'Date', 'australcode-points-rewards' ),
			esc_html__( 'Activity', 'australcode-points-rewards' ),
			esc_html__( 'Points', 'australcode-points-rewards' )
		);
		echo '</tr></thead><tbody>';

		foreach ( $entries as $entry ) {
			// U+2212 minus matches the admin ledger glyph (CustomersPage::signed()).
			$delta = ( $entry->points_delta < 0 ? '−' : '+' ) . number_format_i18n( abs( $entry->points_delta ) );
			// created_at is stored in UTC (current_time('mysql', true)); render in
			// the store timezone with the site date format, without seconds.
			$when = null !== $entry->created_at
				? wp_date( (string) get_option( 'date_format', 'Y-m-d' ), (int) strtotime( $entry->created_at . ' UTC' ) )
				: '—';
			printf(
				'<tr><td>%s</td><td>%s</td><td class="acrwd-delta">%s</td></tr>',
				esc_html( (string) $when ),
				esc_html( $entry->reason ),
				esc_html( $delta )
			);
		}

		echo '</tbody></table>';
	}
}
