<?php

namespace AtlasAiDev\Awfah\Admin;

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

/**
 * Data-driven admin notice system for AtlasAI Connector.
 *
 * Adapted from the AtlasVoice (TTA_Notices) pattern: notices are declared as
 * config arrays via {@see register_notice()} and run through a single display
 * pipeline with per-user dismissal, timed re-show, and legacy-meta migration.
 *
 * Replaces the former single-purpose Pro_Upsell_Notice.
 */
class Notices {

	/**
	 * Singleton instance.
	 *
	 * @var Notices|null
	 */
	private static $instance = null;

	/**
	 * Registered notices keyed by id.
	 *
	 * @var array
	 */
	private $notices = array();

	/**
	 * Whether the shared dismiss JS has been printed this request.
	 *
	 * @var bool
	 */
	private $js_printed = false;

	/**
	 * Get the singleton.
	 *
	 * @return Notices
	 */
	public static function instance(): self {
		if ( null === self::$instance ) {
			self::$instance = new self();
		}
		return self::$instance;
	}

	private function __construct() {
		add_action( 'admin_init', array( $this, 'register_notices' ), 20 );
		add_action( 'admin_notices', array( $this, 'display_notices' ) );
		add_action( 'wp_ajax_awfah_dismiss_notice', array( $this, 'ajax_dismiss' ) );
		add_action( 'wp_ajax_awfah_notice_action', array( $this, 'ajax_notice_action' ) );
	}

	/**
	 * Register a notice from a config array.
	 *
	 * @param array $args Notice config.
	 * @return void
	 */
	public function register_notice( array $args ): void {
		$defaults = array(
			'id'                  => '',
			'title'               => '',
			'message'             => '',
			'type'                => 'info',
			'dismissible'         => true,
			'reshow_after_days'   => 0,
			'condition'           => null,
			'buttons'             => array(),
			'footer_text'         => '',
			'message_callback'    => null,
			'click_action'        => null,
			'track_clicks'        => false,
			'max_clicks'          => 0,
			'legacy_dismiss_meta' => '',
		);
		$notice = wp_parse_args( $args, $defaults );
		if ( '' === $notice['id'] ) {
			return;
		}
		$this->notices[ $notice['id'] ] = $notice;
	}

	/**
	 * Register all plugin notices. Runs on admin pages and admin-ajax so the
	 * dismiss handler can read each notice's config.
	 *
	 * @return void
	 */
	public function register_notices(): void {
		// Only relevant on our own admin screens, for admins, when Pro is inactive.
		$pro_inactive = static function (): bool {
			if ( ! current_user_can( 'manage_options' ) ) {
				return false;
			}
			$screen = get_current_screen();
			if ( ! $screen || false === strpos( (string) $screen->id, 'ai-workflow-automation-ai-agent-hub' ) ) {
				return false;
			}
			return ! ( function_exists( 'awfah_is_pro_active' ) && awfah_is_pro_active() );
		};

		$dashboard_url = admin_url( 'admin.php?page=ai-workflow-automation-ai-agent-hub' );

		// 1. Free trial.
		$this->register_notice( array(
			'id'                => 'free_trial',
			'title'             => '<strong>🎁 ' . esc_html( sprintf( /* translators: %s: plugin brand name (do not translate) */ __( 'Try %s free for 7 days', 'ai-workflow-automation-ai-agent-hub' ), 'AtlasAI Connector Pro' ) ) . '</strong>',
			'message'           => esc_html__( 'Unlock unlimited workflows, per-ability RBAC, OAuth scope policies, advanced AI experiments, and more — no credit card required. Start the trial anytime; the free plugin stays free forever.', 'ai-workflow-automation-ai-agent-hub' ),
			'type'              => 'info',
			'reshow_after_days' => 300,
			'condition'         => $pro_inactive,
			'buttons'           => array(
				array(
					'text' => __( 'Start 7-Day Free Trial', 'ai-workflow-automation-ai-agent-hub' ),
                    'url'     => 'https://atlasaidev.com/atlas-ai-connector-pro/?utm_source=atlas-ai-connector&utm_medium=plugin&utm_campaign=pro_upgrade&utm_content=free_trial_notice',
					'type' => 'primary',
                    'new_tab' => true,
                ),
				array(
					'text'    => __( 'See Pro features', 'ai-workflow-automation-ai-agent-hub' ),
					'url'     => 'https://atlasaidev.com/atlas-ai-connector-pro/?utm_source=atlas-ai-connector&utm_medium=plugin&utm_campaign=pro_upgrade&utm_content=free_trial_notice',
					'type'    => 'secondary',
					'new_tab' => true,
				),
			),
		) );

		// 2. Review request — shown to admins 7+ days after activation.
		$activated_at = (int) get_option( 'awfah_activated_at', 0 );
		if ( ! $activated_at ) {
			// First run on this install: start the 7-day clock now. This also
			// backfills installs that were activated before this option existed.
			$activated_at = time();
			update_option( 'awfah_activated_at', $activated_at, false );
		}
		$days_active = ( time() - $activated_at ) / DAY_IN_SECONDS;

		if ( current_user_can( 'manage_options' ) && $days_active >= 7 ) {
			$this->register_notice( array(
				'id'                => 'review',
				'title'             => '<strong>⭐ ' . esc_html( sprintf( /* translators: %s: plugin brand name (do not translate) */ __( 'Enjoying %s?', 'ai-workflow-automation-ai-agent-hub' ), 'AtlasAI Connector' ) ) . '</strong>',
				'message'           => esc_html( sprintf( /* translators: %s: plugin brand name (do not translate) */ __( 'You\'ve been using %s for over a week. If it\'s helping you connect AI to WordPress, would you consider leaving a quick review? It takes a minute and helps other people discover the plugin.', 'ai-workflow-automation-ai-agent-hub' ), 'AtlasAI Connector' ) ),
				'type'              => 'info',
				'reshow_after_days' => 60,
				'condition'         => static function (): bool {
					return current_user_can( 'manage_options' );
				},
				'buttons'           => array(
					array(
						'text'   => __( '⭐ Leave a Review', 'ai-workflow-automation-ai-agent-hub' ),
						'type'   => 'primary',
						'action' => 'given',
						'track'  => true,
					),
					array(
						'text'   => __( 'Remind Me Later', 'ai-workflow-automation-ai-agent-hub' ),
						'type'   => 'secondary',
						'action' => 'later',
						'track'  => true,
					),
					array(
						'text'   => __( 'Already Done!', 'ai-workflow-automation-ai-agent-hub' ),
						'type'   => 'secondary',
						'action' => 'done',
						'track'  => true,
					),
					array(
						'text'   => __( 'Never Ask Again', 'ai-workflow-automation-ai-agent-hub' ),
						'type'   => 'secondary',
						'action' => 'never',
						'track'  => true,
					),
				),
				'track_clicks'      => true,
				'click_action'      => array( $this, 'handle_review_action' ),
				'footer_text'       => esc_html( sprintf( /* translators: %s: plugin brand name (do not translate) */ __( 'Thank you for using %s!', 'ai-workflow-automation-ai-agent-hub' ), 'AtlasAI Connector' ) ),
			) );
		}
	}

	/**
	 * Display all registered notices.
	 *
	 * @return void
	 */
	public function display_notices(): void {
		foreach ( $this->notices as $id => $notice ) {
			$this->display_notice( (string) $id, $notice );
		}
	}

	/**
	 * Run one notice through condition + dismissal checks, then render.
	 *
	 * @param string $id     Notice id.
	 * @param array  $notice Notice config.
	 * @return void
	 */
	private function display_notice( string $id, array $notice ): void {
		if ( is_callable( $notice['condition'] ) && ! call_user_func( $notice['condition'] ) ) {
			return;
		}
		if ( $notice['dismissible'] && $this->is_dismissed( $id, $notice ) ) {
			return;
		}
		if ( is_callable( $notice['message_callback'] ) ) {
			$notice['message'] = call_user_func( $notice['message_callback'] );
		}
		$this->render_notice( $id, $notice );
	}

	/**
	 * Render a notice's HTML.
	 *
	 * @param string $id     Notice id.
	 * @param array  $notice Notice config.
	 * @return void
	 */
	private function render_notice( string $id, array $notice ): void {
		$colors = array(
			'info'    => '#2563EB',
			'success' => '#00a32a',
			'warning' => '#ffc107',
			'error'   => '#dc3545',
		);
		$border = isset( $colors[ $notice['type'] ] ) ? $colors[ $notice['type'] ] : $colors['info'];
		?>
		<div class="notice notice-<?php echo esc_attr( $notice['type'] ); ?> <?php echo $notice['dismissible'] ? 'is-dismissible' : ''; ?> awfah-admin-notice"
			data-notice-id="<?php echo esc_attr( $id ); ?>"
			style="border-left-color: <?php echo esc_attr( $border ); ?>; padding: 16px 20px;">
			<?php if ( '' !== $notice['title'] ) : ?>
				<div style="margin-bottom: 6px;"><?php echo wp_kses_post( $notice['title'] ); ?></div>
			<?php endif; ?>
			<?php if ( '' !== $notice['message'] ) : ?>
				<p style="margin: 0 0 8px; font-size: 14px; line-height: 1.6;"><?php echo wp_kses_post( $notice['message'] ); ?></p>
			<?php endif; ?>
			<?php if ( ! empty( $notice['buttons'] ) ) : ?>
				<p style="display: flex; gap: 10px; flex-wrap: wrap; margin: 10px 0 0;">
					<?php foreach ( $notice['buttons'] as $button ) { echo $this->render_button( $button, $border ); } // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped ?>
				</p>
			<?php endif; ?>
			<?php if ( '' !== $notice['footer_text'] ) : ?>
				<p style="margin: 10px 0 0; font-size: 12px; color: #666;"><?php echo wp_kses_post( $notice['footer_text'] ); ?></p>
			<?php endif; ?>
		</div>
		<?php
		$this->print_dismiss_js();
	}

	/**
	 * Render a single button.
	 *
	 * @param array  $button Button config.
	 * @param string $border Accent color.
	 * @return string
	 */
	private function render_button( array $button, string $border ): string {
		$button = wp_parse_args(
			$button,
			array(
				'text'    => '',
				'url'     => '#',
				'type'    => 'primary',
				'new_tab' => false,
				'action'  => '',
				'track'   => false,
			)
		);
		$class  = 'button ' . ( 'primary' === $button['type'] ? 'button-primary' : 'button-secondary' );
		$style  = 'primary' === $button['type'] ? 'background:' . esc_attr( $border ) . ';border-color:' . esc_attr( $border ) . ';' : '';

		// Action buttons post back via AJAX (handled by the notice's click_action
		// callback) instead of navigating. The notice id is read from the wrapper.
		if ( '' !== $button['action'] ) {
			$track_attr = ! empty( $button['track'] ) ? ' data-track="true"' : '';
			return sprintf(
				'<a href="#" class="%s awfah-notice-action" data-action="%s"%s style="%s">%s</a>',
				esc_attr( $class ),
				esc_attr( $button['action'] ),
				$track_attr,
				$style,
				esc_html( $button['text'] )
			);
		}

		$target = $button['new_tab'] ? ' target="_blank" rel="noopener noreferrer"' : '';
		return sprintf(
			'<a href="%s" class="%s" style="%s"%s>%s</a>',
			esc_url( $button['url'] ),
			esc_attr( $class ),
			$style,
			$target,
			esc_html( $button['text'] )
		);
	}

	/**
	 * Whether a notice is dismissed for the current user (with timed re-show and
	 * legacy-meta migration).
	 *
	 * @param string $id     Notice id.
	 * @param array  $notice Notice config.
	 * @return bool
	 */
	private function is_dismissed( string $id, array $notice ): bool {
		$user_id = get_current_user_id();

		// Legacy meta (Pro_Upsell_Notice stored a dismissal timestamp).
		if ( '' !== $notice['legacy_dismiss_meta'] ) {
			$legacy = get_user_meta( $user_id, $notice['legacy_dismiss_meta'], true );
			if ( $legacy ) {
				if ( $notice['reshow_after_days'] > 0 && is_numeric( $legacy )
					&& ( time() - (int) $legacy ) >= ( $notice['reshow_after_days'] * DAY_IN_SECONDS ) ) {
					return false; // Cooldown elapsed.
				}
				return true;
			}
		}

		if ( get_user_meta( $user_id, 'awfah_dismiss_' . $id, true ) ) {
			if ( $notice['reshow_after_days'] > 0 ) {
				$next = (int) get_option( 'awfah_reshow_' . $id, 0 );
				if ( $next && time() > $next ) {
					delete_user_meta( $user_id, 'awfah_dismiss_' . $id );
					return false;
				}
			}
			return true;
		}

		return false;
	}

	/**
	 * AJAX: dismiss a notice for the current user.
	 *
	 * @return void
	 */
	public function ajax_dismiss(): void {
		check_ajax_referer( 'awfah_notice_nonce', 'nonce' );
		if ( ! current_user_can( 'manage_options' ) ) {
			wp_send_json_error();
		}
		$id = isset( $_POST['notice_id'] ) ? sanitize_key( wp_unslash( $_POST['notice_id'] ) ) : '';
		if ( '' === $id ) {
			wp_send_json_error();
		}

		$user_id = get_current_user_id();
		update_user_meta( $user_id, 'awfah_dismiss_' . $id, true );

		$notice = isset( $this->notices[ $id ] ) ? $this->notices[ $id ] : array();
		if ( ! empty( $notice['legacy_dismiss_meta'] ) ) {
			update_user_meta( $user_id, $notice['legacy_dismiss_meta'], time() );
		}
		$days = isset( $notice['reshow_after_days'] ) ? (int) $notice['reshow_after_days'] : 30;
		if ( $days > 0 ) {
			update_option( 'awfah_reshow_' . $id, time() + ( $days * DAY_IN_SECONDS ), false );
		}

		wp_send_json_success();
	}

	/**
	 * AJAX: handle an action-button click (the review notice buttons).
	 *
	 * Runs the notice's click_action callback and returns its result
	 * (optional redirect_url + dismiss flag) to the front-end handler.
	 *
	 * @return void
	 */
	public function ajax_notice_action(): void {
		check_ajax_referer( 'awfah_notice_nonce', 'nonce' );
		if ( ! current_user_can( 'manage_options' ) ) {
			wp_send_json_error();
		}
		$id     = isset( $_POST['notice_id'] ) ? sanitize_key( wp_unslash( $_POST['notice_id'] ) ) : '';
		$action = isset( $_POST['action_name'] ) ? sanitize_key( wp_unslash( $_POST['action_name'] ) ) : '';
		if ( '' === $id || '' === $action || ! isset( $this->notices[ $id ] ) ) {
			wp_send_json_error();
		}

		$notice = $this->notices[ $id ];

		// Click tracking (opt-in via the notice's track_clicks flag). Counts each
		// user once and enforces an optional max_clicks cap across all users.
		if ( ! empty( $notice['track_clicks'] ) ) {
			$total = (int) get_option( 'awfah_clicks_' . $id, 0 );
			if ( (int) $notice['max_clicks'] > 0 && $total >= (int) $notice['max_clicks'] ) {
				wp_send_json_error( array( 'message' => __( 'This action is no longer available.', 'ai-workflow-automation-ai-agent-hub' ) ) );
			}
			if ( ! get_user_meta( get_current_user_id(), 'awfah_clicked_' . $id, true ) ) {
				update_option( 'awfah_clicks_' . $id, $total + 1, false );
				update_user_meta( get_current_user_id(), 'awfah_clicked_' . $id, true );
			}
		}

		$result = array( 'dismiss' => true );
		if ( is_callable( $notice['click_action'] ) ) {
			$callback_result = call_user_func( $notice['click_action'], $id, $action, wp_get_current_user() );
			if ( is_array( $callback_result ) ) {
				$result = array_merge( $result, $callback_result );
			}
		}

		wp_send_json_success( $result );
	}

	/**
	 * Click handler for the review notice buttons.
	 *
	 * @param string   $id     Notice id.
	 * @param string   $action One of: given, later, done, never.
	 * @param \WP_User $user   Current user.
	 * @return array
	 */
	public function handle_review_action( string $id, string $action, $user ): array {
		$user_id = (int) $user->ID;
		$result  = array( 'dismiss' => true );

		switch ( $action ) {
			case 'given':
				// Leaving a review — dismiss permanently and send to wp.org.
				update_user_meta( $user_id, 'awfah_dismiss_' . $id, true );
				update_option( 'awfah_reshow_' . $id, 0, false );
				$result['redirect_url'] = 'https://wordpress.org/support/plugin/ai-workflow-automation-ai-agent-hub/reviews/?rate=5#new-post';
				break;

			case 'later':
				// Remind in 14 days.
				update_user_meta( $user_id, 'awfah_dismiss_' . $id, true );
				update_option( 'awfah_reshow_' . $id, time() + ( 14 * DAY_IN_SECONDS ), false );
				break;

			case 'done':
			case 'never':
				// Already reviewed / never ask again — dismiss permanently.
				update_user_meta( $user_id, 'awfah_dismiss_' . $id, true );
				update_option( 'awfah_reshow_' . $id, 0, false );
				break;
		}

		return $result;
	}

	/**
	 * Print the shared dismiss handler once per request.
	 *
	 * @return void
	 */
	private function print_dismiss_js(): void {
		if ( $this->js_printed ) {
			return;
		}
		$this->js_printed = true;
		$nonce = wp_create_nonce( 'awfah_notice_nonce' );
		?>
		<script>
		( function () {
			var nonce = '<?php echo esc_js( $nonce ); ?>';
			document.addEventListener( 'click', function ( e ) {
				// 1. The WordPress dismiss (✕).
				var dismiss = e.target.closest ? e.target.closest( '.notice-dismiss' ) : null;
				if ( dismiss ) {
					var dn = dismiss.closest( '.awfah-admin-notice' );
					if ( ! dn ) { return; }
					var did = dn.getAttribute( 'data-notice-id' );
					if ( ! did ) { return; }
					var xd = new XMLHttpRequest();
					xd.open( 'POST', ajaxurl );
					xd.setRequestHeader( 'Content-Type', 'application/x-www-form-urlencoded' );
					xd.send( 'action=awfah_dismiss_notice&notice_id=' + encodeURIComponent( did ) + '&nonce=' + nonce );
					return;
				}

				// 2. An action button (review: given / later / done / never).
				var act = e.target.closest ? e.target.closest( '.awfah-notice-action' ) : null;
				if ( ! act ) { return; }
				e.preventDefault();
				var notice = act.closest( '.awfah-admin-notice' );
				if ( ! notice ) { return; }
				var id = notice.getAttribute( 'data-notice-id' );
				var action = act.getAttribute( 'data-action' );
				if ( ! id || ! action ) { return; }
				var xa = new XMLHttpRequest();
				xa.open( 'POST', ajaxurl );
				xa.setRequestHeader( 'Content-Type', 'application/x-www-form-urlencoded' );
				xa.onload = function () {
					var redirect = '';
					try {
						var res = JSON.parse( xa.responseText );
						if ( res && res.success && res.data && res.data.redirect_url ) {
							redirect = res.data.redirect_url;
						}
					} catch ( err ) {}
					if ( redirect ) { window.open( redirect, '_blank', 'noopener' ); }
					if ( notice.parentNode ) { notice.parentNode.removeChild( notice ); }
				};
				xa.send( 'action=awfah_notice_action&notice_id=' + encodeURIComponent( id ) + '&action_name=' + encodeURIComponent( action ) + '&nonce=' + nonce );
			} );
		} )();
		</script>
		<?php
	}
}
