<?php
/**
 * Conditional admin asset loading.
 *
 * @package RewindBrevoFormBridge
 */

namespace RewindBrevoFormBridge\Admin;

use RewindBrevoFormBridge\Adapters\Registry;

defined( 'ABSPATH' ) || exit;

/**
 * Registers the compiled SPA bundle on this plugin's screen only, and
 * localizes the `rbfb` bootstrap object.
 *
 * Dependencies and cache-busting versions come from the wp-scripts
 * generated assets/admin.asset.php, never from a hand-maintained list.
 *
 * @since 0.4.0
 */
class AdminAssets {

	/**
	 * Script and style handle.
	 *
	 * @var string
	 */
	const HANDLE = 'rbfb-admin';

	/**
	 * Date format used when Settings > General has none saved.
	 *
	 * Hyphenated so the day, month and year stay unambiguous whatever the
	 * reader's locale expects from a slash.
	 *
	 * @var string
	 */
	const DEFAULT_DATE_FORMAT = 'd-m-Y';

	/**
	 * Time format used when Settings > General has none saved.
	 *
	 * @var string
	 */
	const DEFAULT_TIME_FORMAT = 'H:i';

	/**
	 * Settings storage service.
	 *
	 * @var Settings
	 */
	private Settings $settings;

	/**
	 * Adapter registry.
	 *
	 * @var Registry
	 */
	private Registry $registry;

	/**
	 * The menu, for its screen hook.
	 *
	 * @var AdminMenu
	 */
	private AdminMenu $menu;

	/**
	 * Constructor.
	 *
	 * @since 0.4.0
	 * @param Settings  $settings Settings storage service.
	 * @param Registry  $registry Adapter registry.
	 * @param AdminMenu $menu     Admin menu.
	 */
	public function __construct( Settings $settings, Registry $registry, AdminMenu $menu ) {
		$this->settings = $settings;
		$this->registry = $registry;
		$this->menu     = $menu;
	}

	/**
	 * Attach admin hooks.
	 *
	 * @since 0.4.0
	 * @return void
	 */
	public function register_hooks(): void {
		add_action( 'admin_enqueue_scripts', array( $this, 'enqueue' ) );
		add_filter( 'admin_body_class', array( $this, 'body_class' ) );
	}

	/**
	 * Mark the body so the stylesheet can neutralise wp-admin chrome.
	 *
	 * @since 0.4.0
	 * @param string $classes Existing body classes.
	 * @return string
	 */
	public function body_class( string $classes ): string {
		if ( ! $this->is_our_screen() ) {
			return $classes;
		}

		return $classes . ' rbfb-admin';
	}

	/**
	 * Whether the current screen belongs to this plugin.
	 *
	 * @since 0.4.0
	 * @return bool
	 */
	private function is_our_screen(): bool {
		$screen = function_exists( 'get_current_screen' ) ? get_current_screen() : null;
		$hook   = $this->menu->hook();

		return null !== $screen && '' !== $hook && $screen->id === $hook;
	}

	/**
	 * Enqueue the bundle on this plugin's screen only.
	 *
	 * @since 0.4.0
	 * @param string $hook_suffix Current admin page hook suffix.
	 * @return void
	 */
	public function enqueue( string $hook_suffix ): void {
		if ( '' === $this->menu->hook() || $hook_suffix !== $this->menu->hook() ) {
			return;
		}

		$asset_file = RBFB_PATH . 'assets/admin.asset.php';

		if ( ! is_readable( $asset_file ) ) {
			// Not admin_notices: AdminMenu clears that hook on this screen.
			add_action( 'rbfb_admin_before_app', array( $this, 'render_missing_build_notice' ) );
			return;
		}

		$asset = require $asset_file;

		$dependencies = isset( $asset['dependencies'] ) && is_array( $asset['dependencies'] ) ? $asset['dependencies'] : array();
		$version      = isset( $asset['version'] ) ? (string) $asset['version'] : RBFB_VERSION;

		wp_enqueue_script(
			self::HANDLE,
			RBFB_URL . 'assets/admin.js',
			$dependencies,
			$version,
			true
		);

		if ( is_readable( RBFB_PATH . 'assets/admin.css' ) ) {
			wp_enqueue_style(
				self::HANDLE,
				RBFB_URL . 'assets/admin.css',
				array( 'wp-components' ),
				$version
			);
		}

		wp_set_script_translations( self::HANDLE, 'rewind-form-bridge-for-brevo', RBFB_PATH . 'languages' );

		wp_localize_script( self::HANDLE, 'rbfb', $this->bootstrap() );
	}

	/**
	 * Tell the developer the bundle has not been built yet.
	 *
	 * @since 0.4.0
	 * @return void
	 */
	public function render_missing_build_notice(): void {
		echo '<div class="notice notice-error"><p>';
		echo esc_html__( 'Rewind Form Bridge for Brevo: the admin bundle is missing. Run "npm install && npm run build" in the plugin directory.', 'rewind-form-bridge-for-brevo' );
		echo '</p></div>';
	}

	/**
	 * The `rbfb` bootstrap object.
	 *
	 * Neither credential is present here — only the redacted
	 * { hasKey, hint, source } state. The SMTP key is stripped from the
	 * settings array for the same reason the API key is.
	 *
	 * @since 0.4.0
	 * @return array
	 */
	private function bootstrap(): array {
		$user = wp_get_current_user();

		$adapters = array();
		foreach ( $this->registry->available() as $adapter ) {
			$adapters[] = array(
				'slug'  => $adapter->slug(),
				'label' => $adapter->label(),
			);
		}

		$settings = $this->settings->all();
		unset( $settings['api_key'], $settings['smtp_key'] );

		return array(
			'restUrl'     => esc_url_raw( rest_url( 'rbfb/v1' ) ),
			'restRoot'    => esc_url_raw( rest_url() ),
			'nonce'       => wp_create_nonce( 'wp_rest' ),
			'isPlain'     => ! get_option( 'permalink_structure' ),
			'siteUrl'     => esc_url_raw( get_site_url() ),
			'adminUrl'    => esc_url_raw( admin_url() ),
			'pluginUrl'   => esc_url_raw( RBFB_URL ),
			'version'     => RBFB_VERSION,
			'pluginName'  => __( 'Brevo Bridge', 'rewind-form-bridge-for-brevo' ),
			'textDomain'  => 'rewind-form-bridge-for-brevo',
			'isPro'       => false,
			'currentUser' => array(
				'id'   => (int) $user->ID,
				'name' => (string) $user->display_name,
			),
			'settings'    => $settings,
			'connection'  => array(
				'hasKey'       => '' !== $this->settings->api_key(),
				'hint'         => $this->settings->masked_key(),
				'source'       => $this->settings->api_key_source(),
				'lastVerified' => (string) get_option( 'rbfb_last_verified', '' ),
			),
			'adapters'    => $adapters,
			'dates'       => $this->date_formats(),
			'docsUrl'     => 'https://wordpress.org/plugins/rewind-form-bridge-for-brevo/',
			'supportUrl'  => 'https://wordpress.org/support/plugin/rewind-form-bridge-for-brevo/',
			'brevoKeyUrl' => 'https://app.brevo.com/settings/keys/api',
		);
	}

	/**
	 * Date and time formats for the dashboard.
	 *
	 * Settings > General is the single source of truth, so a date the plugin
	 * prints matches every other date in wp-admin. Both options can be saved
	 * empty, which would otherwise render a bare timestamp — fall back to the
	 * hyphenated ISO-style day and 24-hour clock in that case.
	 *
	 * @since 0.5.0
	 *
	 * @return array{date: string, time: string, gmtOffset: float, timezone: string}
	 */
	private function date_formats() {
		$date = trim( (string) get_option( 'date_format', '' ) );
		$time = trim( (string) get_option( 'time_format', '' ) );

		return array(
			'date'      => '' !== $date ? $date : self::DEFAULT_DATE_FORMAT,
			'time'      => '' !== $time ? $time : self::DEFAULT_TIME_FORMAT,
			'gmtOffset' => (float) get_option( 'gmt_offset', 0 ),
			'timezone'  => (string) wp_timezone_string(),
		);
	}
}
