<?php
/**
 * Licensing admin UX: notices, Site Health, and operational diagnostics.
 *
 * @package WP_PowerSuite
 * @since 1.1.0
 */

if ( ! defined( 'ABSPATH' ) ) {
	exit;
}

/**
 * @since 1.1.0
 */
final class WPPS_License_Admin {

	private const UPDATE_SUCCESS_TRANSIENT = 'wpps_license_update_success';

	private const EXPIRY_NOTICE_DAYS = 30;

	/**
	 * Register admin hooks.
	 */
	public static function register(): void {
		add_action( 'admin_notices', [ self::class, 'render_expiry_notice' ], 15 );
		add_action( 'admin_notices', [ self::class, 'render_disable_updates_notice' ], 16 );
		add_action( 'admin_notices', [ self::class, 'render_post_update_notice' ], 17 );
		add_action( 'admin_notices', [ self::class, 'render_modules_update_notice' ], 18 );
		add_action( 'admin_notices', [ self::class, 'render_updates_checked_notice' ], 19 );
		add_action( 'admin_enqueue_scripts', [ self::class, 'enqueue_styles' ] );
		add_filter( 'debug_information', [ self::class, 'add_debug_information' ] );
		add_filter( 'plugin_row_meta', [ self::class, 'add_plugin_row_meta' ], 10, 2 );
	}

	/**
	 * Enqueue license styles where update cards/notices appear outside the License page.
	 */
	public static function enqueue_styles( string $hook = '' ): void {
		unset( $hook );

		if ( ! self::should_enqueue_styles() ) {
			return;
		}

		$url = defined( 'WP_POWERSUITE_PLUGIN_URL' )
			? WP_POWERSUITE_PLUGIN_URL . 'includes/licensing/_lic_style.css'
			: plugins_url( 'includes/licensing/_lic_style.css', defined( 'WP_POWERSUITE_PLUGIN_FILE' ) ? WP_POWERSUITE_PLUGIN_FILE : '' );

		wp_register_style(
			'wpps-license',
			$url,
			[],
			defined( 'WP_POWERSUITE_VERSION' ) ? WP_POWERSUITE_VERSION : '1.0.0'
		);
		wp_enqueue_style( 'wpps-license' );
	}

	/**
	 * Warn when the license expires within {@see EXPIRY_NOTICE_DAYS} days.
	 */
	public static function render_expiry_notice(): void {
		if ( ! \WP_PowerSuite\Core\NetworkScope::canManagePlugin() || ! class_exists( 'WPPS_License_Manager', false ) ) {
			return;
		}

		if ( ! self::is_notice_screen( [ 'dashboard', 'plugins', 'update-core', 'plugins-network', 'toplevel_page_powersuite' ] ) ) {
			return;
		}

		$reminder = self::get_expiry_reminder();
		if ( $reminder === null ) {
			return;
		}

		echo '<div class="notice notice-warning is-dismissible"><p>';
		echo esc_html( (string) $reminder['message'] );
		if ( ! empty( $reminder['renew_url'] ) ) {
			echo ' <a href="' . esc_url( (string) $reminder['renew_url'] ) . '" target="_blank" rel="noopener noreferrer">';
			esc_html_e( 'Renew license', 'wp-powersuite' );
			echo '</a>';
		}
		echo '</p></div>';
	}

	/**
	 * Confirm update check completed (License page, Plugins screen, etc.).
	 */
	public static function render_updates_checked_notice(): void {
		if ( ! \WP_PowerSuite\Core\NetworkScope::canManagePlugin() ) {
			return;
		}

		$notice = isset( $_GET['wpps_license_notice'] ) ? sanitize_key( wp_unslash( $_GET['wpps_license_notice'] ) ) : '';
		if ( $notice !== 'updates_checked' ) {
			return;
		}

		$page = isset( $_GET['page'] ) ? sanitize_key( wp_unslash( $_GET['page'] ) ) : '';
		if ( class_exists( 'WPPS_License_Manager', false ) && $page === WPPS_License_Manager::get_license_page_slug() ) {
			return;
		}

		echo '<div class="notice notice-success is-dismissible"><p>';
		esc_html_e( 'Update check completed.', 'wp-powersuite' );
		echo '</p></div>';
	}

	/**
	 * Add a manual update check link on the Plugins screen row meta.
	 *
	 * @param array<int, string> $links       Existing row meta links.
	 * @param string             $plugin_file Plugin basename.
	 * @return array<int, string>
	 */
	public static function add_plugin_row_meta( array $links, string $plugin_file ): array {
		if ( ! defined( 'WP_POWERSUITE_PLUGIN_BASENAME' ) || $plugin_file !== WP_POWERSUITE_PLUGIN_BASENAME ) {
			return $links;
		}

		if ( ! \WP_PowerSuite\Core\NetworkScope::canManagePlugin() || ! class_exists( 'WPPS_License_Manager', false ) ) {
			return $links;
		}

		$redirect = \WP_PowerSuite\Core\NetworkScope::adminUrl( 'plugins.php' );
		$url      = WPPS_License_Manager::get_check_updates_url( $redirect );
		$links[]  = '<a href="' . esc_url( $url ) . '">' . esc_html__( 'Check for updates', 'wp-powersuite' ) . '</a>';

		return $links;
	}

	/**
	 * Expiry reminder payload for admin notices and the License page, or null when not applicable.
	 *
	 * @return array{days:int,message:string,renew_url:string}|null
	 */
	public static function get_expiry_reminder(): ?array {
		if ( ! function_exists( 'wp_powersuite_is_license_current' ) || ! wp_powersuite_is_license_current() ) {
			return null;
		}

		$days = self::get_days_until_expiry();
		if ( $days === null || $days > self::EXPIRY_NOTICE_DAYS || $days < 0 ) {
			return null;
		}

		$renew_url = class_exists( 'WPPS_License_Manager', false ) ? WPPS_License_Manager::get_renew_url() : '';
		$brand     = class_exists( '\WP_PowerSuite\Core\WhiteLabel', false )
			? \WP_PowerSuite\Core\WhiteLabel::pluginName()
			: __( 'WP PowerSuite', 'wp-powersuite' );
		$message   = $days === 0
			? sprintf(
				/* translators: %s: plugin name */
				__( 'Your %s license expires today. Renew now to keep receiving updates.', 'wp-powersuite' ),
				$brand
			)
			: sprintf(
				/* translators: 1: plugin name, 2: number of days until license expiry */
				_n(
					'Your %1$s license expires in %2$d day. Renew to keep receiving updates.',
					'Your %1$s license expires in %2$d days. Renew to keep receiving updates.',
					$days,
					'wp-powersuite'
				),
				$brand,
				$days
			);

		return [
			'days'      => $days,
			'message'   => $message,
			'renew_url' => $renew_url,
		];
	}

	/**
	 * Explain when the Disable All Updates module blocks update detection.
	 */
	public static function render_disable_updates_notice(): void {
		if ( ! current_user_can( 'update_plugins' ) || ! self::is_plugin_update_checks_disabled() ) {
			return;
		}

		if ( ! self::is_notice_screen( [ 'dashboard', 'plugins', 'update-core', 'toplevel_page_powersuite' ] ) ) {
			return;
		}

		$brand = class_exists( '\WP_PowerSuite\Core\WhiteLabel', false )
			? \WP_PowerSuite\Core\WhiteLabel::pluginName()
			: __( 'WP PowerSuite', 'wp-powersuite' );
		echo '<div class="notice notice-info is-dismissible"><p>';
		echo esc_html(
			sprintf(
				/* translators: %s: plugin name */
				__( '%s update checks are limited because the Disable All Updates module is blocking WordPress plugin update checks.', 'wp-powersuite' ),
				$brand
			)
		);
		echo ' <a href="' . esc_url( \WP_PowerSuite\Core\NetworkScope::adminUrl( 'admin.php?page=powersuite' ) ) . '">';
		esc_html_e( 'Review modules', 'wp-powersuite' );
		echo '</a>';
		echo '</p></div>';
	}

	/**
	 * Success notice after WP PowerSuite was upgraded.
	 */
	public static function render_post_update_notice(): void {
		if ( ! current_user_can( 'update_plugins' ) ) {
			return;
		}

		$payload = get_transient( self::UPDATE_SUCCESS_TRANSIENT );
		if ( ! is_array( $payload ) || empty( $payload['version'] ) ) {
			return;
		}

		delete_transient( self::UPDATE_SUCCESS_TRANSIENT );

		$brand = class_exists( '\WP_PowerSuite\Core\WhiteLabel', false )
			? \WP_PowerSuite\Core\WhiteLabel::pluginName()
			: __( 'WP PowerSuite', 'wp-powersuite' );
		$message = sprintf(
			/* translators: 1: plugin name, 2: installed plugin version */
			__( '%1$s was updated to version %2$s.', 'wp-powersuite' ),
			$brand,
			(string) $payload['version']
		);

		if ( function_exists( 'wp_powersuite_is_license_current' ) && wp_powersuite_is_license_current() ) {
			$manager = WPPS_License_Manager::get_instance();
			$manager->ensure_response_object();
			$response = $manager->get_response_obj();
			if ( is_object( $response ) && ! empty( $response->expire_date ) ) {
				$message .= ' ' . sprintf(
					/* translators: %s: license expiry date */
					__( 'Your license is active until %s.', 'wp-powersuite' ),
					(string) $response->expire_date
				);
			}
		}

		echo '<div class="notice notice-success is-dismissible"><p>' . esc_html( $message ) . '</p></div>';
	}

	/**
	 * Update-available banner on the WP PowerSuite Modules screen.
	 */
	public static function render_modules_update_notice(): void {
		if ( ! current_user_can( 'update_plugins' ) || ! class_exists( 'WPPS_License_Updater', false ) ) {
			return;
		}

		if ( ! function_exists( 'get_current_screen' ) ) {
			return;
		}

		$screen = get_current_screen();
		if ( ! is_object( $screen ) || $screen->id !== 'toplevel_page_powersuite' ) {
			return;
		}

		$pending = WPPS_License_Updater::get_pending_update();
		if ( ! is_array( $pending ) ) {
			return;
		}

		$notice_class = ! empty( $pending['can_download'] ) ? 'notice-info' : 'notice-warning';
		$message = WPPS_License_Updater::get_update_available_notice_message( $pending );
		if ( $message === '' ) {
			return;
		}

		echo '<div class="notice ' . esc_attr( $notice_class ) . ' wpps-license-update-admin-notice"><p>';
		echo esc_html( $message );
		if ( ! empty( $pending['license_url'] ) && empty( $pending['can_download'] ) ) {
			echo ' <a href="' . esc_url( (string) $pending['license_url'] ) . '">';
			esc_html_e( 'Go to License page', 'wp-powersuite' );
			echo '</a>';
		} elseif ( ! empty( $pending['updates_url'] ) && ! empty( $pending['can_download'] ) ) {
			echo ' <a href="' . esc_url( (string) $pending['updates_url'] ) . '">';
			esc_html_e( 'Go to Updates', 'wp-powersuite' );
			echo '</a>';
		}
		echo '</p></div>';
	}

	/**
	 * Site Health → Info tab section.
	 *
	 * @param array<string,mixed> $info Debug information sections.
	 * @return array<string,mixed>
	 */
	public static function add_debug_information( array $info ): array {
		if ( ! class_exists( 'WPPS_License_Manager', false ) ) {
			return $info;
		}

		$manager = WPPS_License_Manager::get_instance();
		$manager->init();
		$status  = $manager->get_status_data();
		$fields  = [
			'status' => [
				'label' => __( 'License status', 'wp-powersuite' ),
				'value' => (string) ( $status['status'] ?? 'unknown' ),
			],
			'premium' => [
				'label' => __( 'Premium modules', 'wp-powersuite' ),
				'value' => function_exists( 'wp_powersuite_is_license_valid' ) && wp_powersuite_is_license_valid()
					? __( 'Allowed', 'wp-powersuite' )
					: __( 'Blocked', 'wp-powersuite' ),
			],
			'updates' => [
				'label' => __( 'Plugin updates', 'wp-powersuite' ),
				'value' => function_exists( 'wp_powersuite_is_license_current' ) && wp_powersuite_is_license_current()
					? __( 'Allowed', 'wp-powersuite' )
					: __( 'Blocked (license not current)', 'wp-powersuite' ),
			],
			'last_checked' => [
				'label' => __( 'Last checked', 'wp-powersuite' ),
				'value' => ! empty( $status['checked_at'] )
					? wp_date( get_option( 'date_format' ) . ' ' . get_option( 'time_format' ), (int) $status['checked_at'] )
					: __( 'Never', 'wp-powersuite' ),
			],
			'update_checks' => [
				'label' => __( 'WordPress update checks', 'wp-powersuite' ),
				'value' => self::is_plugin_update_checks_disabled()
					? __( 'Limited by Disable All Updates module', 'wp-powersuite' )
					: __( 'Enabled', 'wp-powersuite' ),
			],
			'vendor_site' => [
				'label' => __( 'License server co-install', 'wp-powersuite' ),
				'value' => $manager->is_vendor_site()
					? __( 'Yes (vendor host)', 'wp-powersuite' )
					: __( 'No', 'wp-powersuite' ),
			],
		];

		if ( class_exists( 'WPPS_License_Updater', false ) ) {
			$pending = WPPS_License_Updater::get_pending_update();
			$fields['pending_update'] = [
				'label' => __( 'Pending plugin update', 'wp-powersuite' ),
				'value' => is_array( $pending )
					? sprintf(
						/* translators: 1: available version, 2: installed version */
						__( '%1$s available (installed %2$s)', 'wp-powersuite' ),
						(string) $pending['new_version'],
						(string) $pending['installed_version']
					)
					: __( 'None', 'wp-powersuite' ),
			];
		}

		if ( is_multisite() ) {
			$fields['multisite'] = [
				'label' => __( 'Multisite', 'wp-powersuite' ),
				'value' => network_admin_url() === admin_url()
					? __( 'Network admin context', 'wp-powersuite' )
					: sprintf(
						/* translators: %s: site URL */
						__( 'Site license applies to %s', 'wp-powersuite' ),
						home_url( '/' )
					),
			];
		}

		$info['wp-powersuite-license'] = [
			'label'       => sprintf(
				/* translators: %s: plugin name */
				__( '%s License', 'wp-powersuite' ),
				class_exists( '\WP_PowerSuite\Core\WhiteLabel', false )
					? \WP_PowerSuite\Core\WhiteLabel::pluginName()
					: __( 'WP PowerSuite', 'wp-powersuite' )
			),
			'description' => __( 'License entitlement, update access, and operational status.', 'wp-powersuite' ),
			'fields'      => $fields,
		];

		return $info;
	}

	/**
	 * Store a one-time admin success notice after upgrading WP PowerSuite.
	 *
	 * @param array<string,mixed> $options Upgrader options.
	 */
	public static function note_successful_upgrade( array $options ): void {
		if ( ( $options['action'] ?? '' ) !== 'update' || ( $options['type'] ?? '' ) !== 'plugin' ) {
			return;
		}

		if ( ! defined( 'WP_POWERSUITE_PLUGIN_FILE' ) ) {
			return;
		}

		$basename = plugin_basename( WP_POWERSUITE_PLUGIN_FILE );
		$plugins  = isset( $options['plugins'] ) && is_array( $options['plugins'] ) ? $options['plugins'] : [];

		if ( ! in_array( $basename, $plugins, true ) ) {
			return;
		}

		set_transient(
			self::UPDATE_SUCCESS_TRANSIENT,
			[
				'version' => class_exists( 'W_P_Power_Suite_Premium_Base', false )
					? W_P_Power_Suite_Premium_Base::get_installed_version()
					: ( defined( 'WP_POWERSUITE_VERSION' ) ? WP_POWERSUITE_VERSION : '' ),
			],
			MINUTE_IN_SECONDS
		);
	}

	/**
	 * Whether WordPress plugin update checks are disabled by WP PowerSuite.
	 */
	public static function is_plugin_update_checks_disabled(): bool {
		if ( ! class_exists( '\WP_PowerSuite\Core\OptionStore', false ) ) {
			return false;
		}

		$store = \WP_PowerSuite\Core\OptionStore::getInstance();
		if ( ! $store->isModuleEnabled( 'disable-all-updates' ) ) {
			return false;
		}

		$settings = \WP_PowerSuite\Core\OptionStoreModuleSettingsRepository::forModule( 'disable-all-updates' )->all();

		return ! empty( $settings['disable_plugin_updates'] );
	}

	/**
	 * Days until license expiry, or null when unknown.
	 */
	public static function get_days_until_expiry(): ?int {
		if ( ! class_exists( 'WPPS_License_Manager', false ) ) {
			return null;
		}

		$manager = WPPS_License_Manager::get_instance();
		$manager->ensure_response_object();
		$response = $manager->get_response_obj();
		if ( ! is_object( $response ) || empty( $response->expire_date ) ) {
			return null;
		}

		$expire_ts = self::parse_expire_timestamp( (string) $response->expire_date );
		if ( $expire_ts === null ) {
			return null;
		}

		return (int) floor( ( $expire_ts - time() ) / DAY_IN_SECONDS );
	}

	/**
	 * Parse a license expiry date into a Unix timestamp (end of expiry day when time is absent).
	 */
	private static function parse_expire_timestamp( string $expire_date ): ?int {
		$expire_str = strtolower( trim( $expire_date ) );
		if ( in_array( $expire_str, [ 'no expiry', 'unlimited', '' ], true ) ) {
			return null;
		}

		if ( preg_match( '/^\d{4}-\d{2}-\d{2}$/', $expire_str ) ) {
			$expire_ts = strtotime( $expire_str . ' 23:59:59' );
			return $expire_ts !== false ? $expire_ts : null;
		}

		$expire_ts = strtotime( $expire_date );
		if ( $expire_ts === false ) {
			return null;
		}

		if ( preg_match( '/(?:\s|T)00:00:00/', $expire_date ) ) {
			$expire_ts = strtotime( gmdate( 'Y-m-d', $expire_ts ) . ' 23:59:59' );
		}

		return $expire_ts !== false ? $expire_ts : null;
	}

	/**
	 * @param list<string> $screen_ids Allowed screen IDs.
	 */
	private static function is_notice_screen( array $screen_ids ): bool {
		if ( ! function_exists( 'get_current_screen' ) ) {
			return false;
		}

		$screen = get_current_screen();
		return is_object( $screen ) && in_array( (string) $screen->id, $screen_ids, true );
	}

	private static function should_enqueue_styles(): bool {
		if ( ! function_exists( 'get_current_screen' ) ) {
			return false;
		}

		$screen = get_current_screen();
		if ( ! is_object( $screen ) ) {
			return false;
		}

		if ( $screen->id === 'toplevel_page_powersuite' ) {
			return true;
		}

		if ( class_exists( 'WPPS_License_Manager', false ) ) {
			$page = isset( $_GET['page'] ) ? sanitize_key( wp_unslash( $_GET['page'] ) ) : '';
			if ( $page === WPPS_License_Manager::get_license_page_slug() ) {
				return true;
			}
		}

		return false;
	}
}
