<?php

declare(strict_types=1);

namespace FormConnector\Core\Admin;

use FormConnector\Features\Retry\RetryQueue;

/**
 * Adds an admin-menu count badge for permanently-failed retry items.
 *
 * The badge mirrors the WP "Updates" badge styling so admins notice when
 * submissions to CareHQ have exhausted their retry attempts.
 *
 * Registered via `admin_menu` priority 11 so it runs after the menu is
 * registered (the main menu is added on the default priority 10).
 */
class MenuBadge {

	public const TRANSIENT = 'fc_failed_retry_count';

	/**
	 * Register hooks.
	 */
	public static function register(): void {
		add_action('admin_menu', [self::class, 'maybe_decorate'], 11);
		// Invalidate the cache whenever the retry queue marks an item failed.
		add_action('fc_retry_permanently_failed', [self::class, 'invalidate_cache']);
	}

	/**
	 * Append a count badge to the CareHQ menu item.
	 */
	public static function maybe_decorate(): void {
		global $menu;
		if (!is_array($menu)) {
			return;
		}

		$count = self::get_failed_count();
		if ($count <= 0) {
			return;
		}

		$slug = defined('FC_SETTINGS_SLUG') ? FC_SETTINGS_SLUG : 'CareHQConnector';
		$badge = sprintf(
			' <span class="awaiting-mod count-%1$d"><span class="pending-count" aria-hidden="true">%1$d</span><span class="screen-reader-text">%2$s</span></span>',
			(int) $count,
			esc_html(sprintf(
				/* translators: %d: number of failed submissions */
				_n('%d failed submission needs attention', '%d failed submissions need attention', $count, 'carehq-connector'),
				$count
			))
		);

		foreach ($menu as $index => $item) {
			if (isset($item[2]) && $item[2] === $slug) {
				$menu[$index][0] .= $badge;
				break;
			}
		}
	}

	/**
	 * Get the current count of permanently-failed retry items.
	 *
	 * Cached in a short-lived transient because this is computed on every
	 * admin page load.
	 */
	public static function get_failed_count(): int {
		$cached = get_transient(self::TRANSIENT);
		if ($cached !== false) {
			return (int) $cached;
		}

		if (!class_exists(RetryQueue::class)) {
			return 0;
		}

		try {
			$stats = RetryQueue::get_instance()->get_stats();
			$count = (int) ($stats['failed'] ?? 0);
		} catch (\Throwable $e) {
			$count = 0;
		}

		set_transient(self::TRANSIENT, $count, 5 * MINUTE_IN_SECONDS);
		return $count;
	}

	/**
	 * Clear the cached count so the next admin page load recomputes.
	 */
	public static function invalidate_cache(): void {
		delete_transient(self::TRANSIENT);
	}
}
