<?php

declare(strict_types=1);

namespace SiteFort\Modules\Cloud\Service;

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

use SiteFort\Includes\Capabilities;
use SiteFort\Includes\SettingsStore;

/**
 * Informational notice after paid features are suspended; free tier scanning continues.
 * Entitlements::reconcile() sets/clears the timestamp. Mirrored in PlanNotice.tsx for the app.
 */
class PlanSuspensionNotice {

	private const STATE_KEY = 'plan_suspended_notice_at';

	// Set to STATE_KEY's timestamp; a later suspension changes STATE_KEY so this stops matching.
	private const DISMISSED_KEY = 'plan_suspended_notice_dismissed_at';

	// 14 days: enough to notice, not permanent furniture.
	private const VISIBLE_FOR = 14 * DAY_IN_SECONDS;

	public static function is_active(): bool {
		$suspended_at = absint( SettingsStore::get_field( SettingsStore::COL_STATE, self::STATE_KEY, 0 ) );
		if ( $suspended_at === 0 || ( time() - $suspended_at ) > self::VISIBLE_FOR ) {
			return false;
		}

		$dismissed_at = absint( SettingsStore::get_field( SettingsStore::COL_STATE, self::DISMISSED_KEY, 0 ) );
		return $dismissed_at !== $suspended_at;
	}

	// Site-wide, not per-user.
	public static function dismiss(): void {
		$suspended_at = absint( SettingsStore::get_field( SettingsStore::COL_STATE, self::STATE_KEY, 0 ) );
		if ( $suspended_at > 0 ) {
			SettingsStore::set_field( SettingsStore::COL_STATE, self::DISMISSED_KEY, $suspended_at );
		}
	}

	public static function handle_dismiss_ajax(): void {
		check_ajax_referer( 'sitefort_nonce', false );
		if ( ! Capabilities::can_manage_plugin() ) {
			wp_send_json_error( [ 'message' => 'Unauthorized' ], 403 );
		}
		self::dismiss();
		wp_send_json_success();
	}

	/**
	 * Revoked licenses cannot be restored by renewing, so they get different wording.
	 */
	public static function is_revoked(): bool {
		return strtolower( (string) ( CloudSettings::get_all()['license_status'] ?? '' ) ) === 'revoked';
	}

	/**
	 * Headline, body and action, shared by both surfaces.
	 *
	 * @return array{title:string,body:string,action:string,url:string}
	 */
	public static function get_copy(): array {
		if ( self::is_revoked() ) {
			return [
				'title'  => __( 'SiteFort license revoked.', 'sitefort' ),
				'body'   => __( 'Scheduled scans, automated vulnerability alerts, and one-click malware repair are disabled.', 'sitefort' ),
				'action' => __( 'Contact support', 'sitefort' ),
				'url'    => 'https://securewp.net/support/',
			];
		}

		return [
			'title'  => __( 'SiteFort plan changed to Free.', 'sitefort' ),
			'body'   => __( 'Scheduled scans, automated vulnerability alerts, and one-click malware repair are disabled.', 'sitefort' ),
			'action' => __( 'Manage billing', 'sitefort' ),
			'url'    => 'https://console.securewp.net/dashboard/billing',
		];
	}

	// WordPress admin notice for screens outside the plugin; SiteFort's own screens render
	// PlanNotice instead. Dismiss button is wired in assets/admin-global.js, not WordPress's
	// is-dismissible, which doesn't persist across reloads.
	public static function render(): void {
		if ( ! Capabilities::can_manage_plugin() || ! self::is_active() ) {
			return;
		}

		$copy = self::get_copy();
		?>
		<div id="sitefort-plan-notice"
			class="notice notice-warning sitefort-plan-notice"
			data-nonce="<?php echo esc_attr( wp_create_nonce( 'sitefort_nonce' ) ); ?>"
			data-ajax-url="<?php echo esc_url( admin_url( 'admin-ajax.php' ) ); ?>">
			<div>
				<strong><?php echo esc_html( $copy['title'] ); ?></strong>
				<?php echo esc_html( $copy['body'] ); ?>
				<a href="<?php echo esc_url( $copy['url'] ); ?>" target="_blank" rel="noopener noreferrer"><?php
					echo esc_html( $copy['action'] );
				?></a>
			</div>
			<button type="button" class="notice-dismiss" data-sitefort-dismiss-plan-notice>
				<span class="screen-reader-text"><?php esc_html_e( 'Dismiss this notice.', 'sitefort' ); ?></span>
			</button>
		</div>
		<?php
	}
}
