<?php
/**
 * SocialPromoter Nudge
 *
 * Prompts editors to promote posts to social media immediately after
 * publishing (modal overlay) and on subsequent edits if the post has
 * not yet been promoted (persistent amber banner).
 *
 * Promotion status is stored in post meta:
 *   _pkits_sp_promotion_status = '' | 'pending' | 'promoted' | 'dismissed'
 *
 * @package PublisherKits_SocialPromoter
 */

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

/**
 * Class PKITS_SP_Nudge
 */
class PKITS_SP_Nudge {

	/**
	 * Post meta key for promotion status.
	 *
	 * @var string
	 */
	const META_KEY = '_pkits_sp_promotion_status';

	/**
	 * Transient prefix for classic-editor post-publish detection.
	 *
	 * @var string
	 */
	const TRANSIENT_PREFIX = 'pkits_sp_nudge_show_';

	/**
	 * Register all hooks.
	 *
	 * @return void
	 */
	public function register_hooks() {
		add_action( 'transition_post_status', array( $this, 'on_post_transition' ), 10, 3 );
		add_action( 'admin_enqueue_scripts', array( $this, 'enqueue_nudge_assets' ) );
		add_action( 'admin_notices', array( $this, 'render_nudge_banner' ) );
		add_action( 'admin_footer', array( $this, 'render_nudge_modal' ) );
		add_action( 'wp_ajax_pkits_sp_set_promotion_status', array( $this, 'ajax_set_promotion_status' ) );
		add_action( 'restrict_manage_posts', array( $this, 'add_promotion_filter_dropdown' ) );
		add_action( 'parse_query', array( $this, 'filter_posts_by_promotion_status' ) );
	}

	// ----------------------------------------------------------------
	// Copy template
	// ----------------------------------------------------------------

	/**
	 * Get the copy template for a post, with placeholders resolved.
	 *
	 * @param int $post_id Post ID.
	 * @return string Resolved copy string.
	 */
	private function get_copy_template( $post_id ) {
		$settings = get_option( 'pkits_sp_settings', array() );
		$settings = is_array( $settings ) ? $settings : array();
		$template = isset( $settings['copy_template'] ) && '' !== $settings['copy_template']
			? $settings['copy_template']
			: '{post_title} {post_url}';

		if ( ! $post_id ) {
			return '';
		}

		$post_title     = (string) ( get_the_title( $post_id ) );
		$post_permalink = (string) ( get_permalink( $post_id ) ?: '' );
		$site_name      = (string) ( get_bloginfo( 'name' ) );

		$resolved = str_replace(
			array( '{post_title}', '{post_url}', '{site_name}' ),
			array( $post_title, $post_permalink, $site_name ),
			(string) $template
		);

		return sanitize_textarea_field( $resolved );
	}

	// ----------------------------------------------------------------
	// Post transition
	// ----------------------------------------------------------------

	/**
	 * When a post transitions to published, mark it as pending promotion.
	 *
	 * Also sets a short-lived transient so the classic editor can trigger
	 * the modal on the next page load.
	 *
	 * @param string  $new_status New post status.
	 * @param string  $old_status Old post status.
	 * @param WP_Post $post       Post object.
	 * @return void
	 */
	public function on_post_transition( $new_status, $old_status, $post ) {
		if ( 'publish' !== $new_status || 'publish' === $old_status ) {
			return;
		}

		if ( ! $this->is_supported_post_type( $post->post_type ) ) {
			return;
		}

		$current = get_post_meta( $post->ID, self::META_KEY, true );

		// Only set pending if no status yet — don't overwrite dismissed.
		if ( empty( $current ) ) {
			update_post_meta( $post->ID, self::META_KEY, 'pending' );
		}

		// Transient for classic editor page-reload detection (60 second window).
		set_transient( self::TRANSIENT_PREFIX . $post->ID, '1', 60 );
	}

	// ----------------------------------------------------------------
	// Assets
	// ----------------------------------------------------------------

	/**
	 * Enqueue nudge JS and CSS on post edit screens.
	 *
	 * @param string $hook Current admin page hook suffix.
	 * @return void
	 */
	public function enqueue_nudge_assets( $hook ) {
		if ( ! in_array( $hook, array( 'post.php', 'post-new.php' ), true ) ) {
			return;
		}

		$post_id   = absint( isset( $_GET['post'] ) ? wp_unslash( $_GET['post'] ) : 0 );
		$post_type = get_post_type( $post_id );

		if ( $post_id && ! $this->is_supported_post_type( $post_type ) ) {
			return;
		}

		if ( ! $this->nudge_enabled() || ! $this->role_allowed() ) {
			return;
		}

		wp_enqueue_style(
			'pkits-sp-nudge',
			PKITS_SP_URL . 'admin/css/admin.css',
			array(),
			PKITS_SP_VERSION
		);

		wp_enqueue_script(
			'pkits-sp-nudge',
			PKITS_SP_URL . 'admin/js/nudge.js',
			array( 'jquery' ),
			PKITS_SP_VERSION,
			true
		);

		// Detect classic-editor post-just-published via transient.
		$show_modal_on_load = false;
		if ( $post_id ) {
			$transient = get_transient( self::TRANSIENT_PREFIX . $post_id );
			if ( $transient ) {
				delete_transient( self::TRANSIENT_PREFIX . $post_id );
				$show_modal_on_load = true;
			}
		}

		// Gather accounts for the modal.
		$accounts     = PKITS_SP_Accounts::get_active();
		$account_data = array();
		foreach ( $accounts as $storage_id => $account ) {
			$account_data[] = array(
				'storage_id' => $storage_id,
				'label'      => $account['label'],
				'platform'   => $account['platform'],
			);
		}

		// Post scheduled time (if post is scheduled).
		$scheduled_at = '';
		if ( $post_id ) {
			$post = get_post( $post_id );
			if ( $post && 'future' === $post->post_status ) {
				$scheduled_at = get_the_date( 'Y-m-d\TH:i', $post );
			}
		}

		// Post title and permalink for copy pre-population.
		$post_title     = '';
		$post_permalink = '';
		if ( $post_id && get_post( $post_id ) ) {
			$post_title     = (string) ( get_the_title( $post_id ) );
			$post_permalink = (string) ( get_permalink( $post_id ) ?: '' );
		}

		wp_localize_script(
			'pkits-sp-nudge',
			'pkitsSpNudge',
			array(
				'ajaxUrl'          => admin_url( 'admin-ajax.php' ),
				'nonce'            => wp_create_nonce( 'pkits_sp_metabox' ),
				'statusNonce'      => wp_create_nonce( 'pkits_sp_set_promotion_status' ),
				'postId'           => $post_id,
				'showModalOnLoad'  => $show_modal_on_load,
				'scheduledAt'      => $scheduled_at,
				'postTitle'        => $post_title,
				'postPermalink'    => $post_permalink,
				'accounts'         => $account_data,
				'hasAccounts'      => ! empty( $account_data ),
				'promotionStatus'  => $post_id ? get_post_meta( $post_id, self::META_KEY, true ) : '',
				'accountsPageUrl'  => admin_url( 'admin.php?page=publisherkits-socialpromoter-accounts' ),
				'copyTemplate'    => $this->get_copy_template( $post_id ),
				'strings'          => array(
					'modalTitle'      => esc_html__( "Don't forget to promote this post", 'publisherkits-socialpromoter' ),
					'noAccounts'      => esc_html__( 'No social accounts connected yet.', 'publisherkits-socialpromoter' ),
					'connectAccounts' => esc_html__( 'Connect accounts', 'publisherkits-socialpromoter' ),
					'promoteNow'      => esc_html__( 'Post Now', 'publisherkits-socialpromoter' ),
					'schedule'        => esc_html__( 'Schedule', 'publisherkits-socialpromoter' ),
					'confirmSchedule' => esc_html__( 'Confirm Schedule', 'publisherkits-socialpromoter' ),
					'remindLater'     => esc_html__( 'Remind me later', 'publisherkits-socialpromoter' ),
					'neverPromote'    => esc_html__( 'Never promote this post', 'publisherkits-socialpromoter' ),
					'posting'         => esc_html__( 'Posting...', 'publisherkits-socialpromoter' ),
					'scheduling'      => esc_html__( 'Scheduling...', 'publisherkits-socialpromoter' ),
					'successPost'     => esc_html__( 'Posted successfully.', 'publisherkits-socialpromoter' ),
					'successSchedule' => esc_html__( 'Scheduled successfully.', 'publisherkits-socialpromoter' ),
					'selectAccount'   => esc_html__( 'Select at least one account.', 'publisherkits-socialpromoter' ),
					'selectTime'      => esc_html__( 'Please pick a date and time.', 'publisherkits-socialpromoter' ),
					'pickTime'        => esc_html__( 'Pick a date/time then click Confirm Schedule', 'publisherkits-socialpromoter' ),
					'syncPublish'     => esc_html__( 'Sync with publish time', 'publisherkits-socialpromoter' ),
					'xLimit'          => esc_html__( 'X limit: 280 characters', 'publisherkits-socialpromoter' ),
				),
			)
		);
	}

	// ----------------------------------------------------------------
	// Banner
	// ----------------------------------------------------------------

	/**
	 * Render the persistent amber banner on post edit screens where the
	 * post is published but not yet promoted.
	 *
	 * @return void
	 */
	public function render_nudge_banner() {
		if ( ! $this->nudge_enabled() || ! $this->nudge_banner_enabled() || ! $this->role_allowed() ) {
			return;
		}

		$screen = get_current_screen();
		if ( ! $screen || 'post' !== $screen->base ) {
			return;
		}

		// phpcs:ignore WordPress.Security.NonceVerification.Recommended
		$post_id = absint( isset( $_GET['post'] ) ? wp_unslash( $_GET['post'] ) : 0 );
		if ( ! $post_id ) {
			return;
		}

		$post = get_post( $post_id );
		if ( ! $post || 'publish' !== $post->post_status ) {
			return;
		}

		if ( ! $this->is_supported_post_type( $post->post_type ) ) {
			return;
		}

		$status = get_post_meta( $post_id, self::META_KEY, true );
		if ( 'pending' !== $status ) {
			return;
		}

		// Don't show banner if modal will show on load (just published).
		$transient = get_transient( self::TRANSIENT_PREFIX . $post_id );
		if ( $transient ) {
			return;
		}
		?>
		<div id="pkits-sp-nudge-banner" class="notice pkits-sp-nudge-notice" data-post-id="<?php echo esc_attr( $post_id ); ?>">
			<div class="pkits-sp-nudge-banner-inner">
				<span class="pkits-sp-nudge-icon">&#9650;</span>
				<span class="pkits-sp-nudge-text">
					<?php esc_html_e( 'This post has not been promoted to social media yet.', 'publisherkits-socialpromoter' ); ?>
				</span>
				<div class="pkits-sp-nudge-banner-actions">
					<button type="button" class="button pkits-sp-nudge-btn-promote">
						<?php esc_html_e( 'Promote Now', 'publisherkits-socialpromoter' ); ?>
					</button>
					<button type="button" class="button pkits-sp-nudge-btn-schedule">
						<?php esc_html_e( 'Schedule', 'publisherkits-socialpromoter' ); ?>
					</button>
					<button type="button" class="pkits-sp-nudge-btn-dismiss-perm">
						<?php esc_html_e( 'Never promote this post', 'publisherkits-socialpromoter' ); ?>
					</button>
				</div>
			</div>
		</div>
		<?php
	}

	// ----------------------------------------------------------------
	// Modal
	// ----------------------------------------------------------------

	/**
	 * Output the modal HTML shell in admin_footer.
	 * JS controls visibility and populates content dynamically.
	 *
	 * @return void
	 */
	public function render_nudge_modal() {
		$screen = get_current_screen();
		if ( ! $screen || 'post' !== $screen->base ) {
			return;
		}

		if ( ! $this->nudge_enabled() || ! $this->role_allowed() ) {
			return;
		}
		?>
		<div id="pkits-sp-nudge-overlay" class="pkits-sp-nudge-overlay" style="display:none;" aria-modal="true" role="dialog" aria-labelledby="pkits-sp-nudge-title">
			<div class="pkits-sp-nudge-modal">

				<div class="pkits-sp-nudge-modal-header">
					<div class="pkits-sp-nudge-modal-logo">SP</div>
					<h2 id="pkits-sp-nudge-title" class="pkits-sp-nudge-modal-title">
						<?php esc_html_e( "Don't forget to promote this post", 'publisherkits-socialpromoter' ); ?>
					</h2>
					<button type="button" class="pkits-sp-nudge-modal-close" aria-label="<?php esc_attr_e( 'Close', 'publisherkits-socialpromoter' ); ?>">&times;</button>
				</div>

				<?php /* No-accounts state */ ?>
				<div id="pkits-sp-nudge-no-accounts" style="display:none;">
					<p class="pkits-sp-nudge-no-accounts-msg">
						<?php esc_html_e( 'No social accounts connected yet.', 'publisherkits-socialpromoter' ); ?>
					</p>
					<a id="pkits-sp-nudge-connect-link" href="<?php echo esc_url( admin_url( 'admin.php?page=publisherkits-socialpromoter-accounts' ) ); ?>" class="button button-primary">
						<?php esc_html_e( 'Connect accounts', 'publisherkits-socialpromoter' ); ?>
					</a>
				</div>

				<?php /* Compose state */ ?>
				<div id="pkits-sp-nudge-compose">
					<div class="pkits-sp-nudge-field">
						<label for="pkits-sp-nudge-copy">
							<strong><?php esc_html_e( 'Social copy', 'publisherkits-socialpromoter' ); ?></strong>
						</label>
						<textarea
							id="pkits-sp-nudge-copy"
							rows="4"
							placeholder="<?php esc_attr_e( 'Write your social post copy...', 'publisherkits-socialpromoter' ); ?>"
						></textarea>
						<div class="pkits-sp-char-row">
							<span class="pkits-sp-nudge-char-count">0</span>
							<span class="pkits-sp-char-hint"><?php esc_html_e( '(X limit: 280)', 'publisherkits-socialpromoter' ); ?></span>
						</div>
					</div>

					<div class="pkits-sp-nudge-field">
						<strong><?php esc_html_e( 'Post to:', 'publisherkits-socialpromoter' ); ?></strong>
						<div id="pkits-sp-nudge-accounts"></div>
					</div>

					<div id="pkits-sp-nudge-schedule-row" class="pkits-sp-nudge-schedule-row" style="display:none;">
						<p class="pkits-sp-nudge-schedule-hint"></p>
						<input type="datetime-local" id="pkits-sp-nudge-datetime" />
					</div>

					<div id="pkits-sp-nudge-result" class="pkits-sp-nudge-result" style="display:none;"></div>

					<div class="pkits-sp-nudge-modal-actions">
						<button type="button" id="pkits-sp-nudge-post-now" class="button button-primary">
							<?php esc_html_e( 'Post Now', 'publisherkits-socialpromoter' ); ?>
						</button>
						<button type="button" id="pkits-sp-nudge-schedule-btn" class="button">
							<?php esc_html_e( 'Schedule', 'publisherkits-socialpromoter' ); ?>
						</button>
						<div class="pkits-sp-nudge-modal-secondary">
							<button type="button" id="pkits-sp-nudge-remind" class="pkits-sp-nudge-text-btn">
								<?php esc_html_e( 'Remind me later', 'publisherkits-socialpromoter' ); ?>
							</button>
							<span class="pkits-sp-nudge-sep">|</span>
							<button type="button" id="pkits-sp-nudge-never" class="pkits-sp-nudge-text-btn pkits-sp-nudge-never">
								<?php esc_html_e( 'Never promote this post', 'publisherkits-socialpromoter' ); ?>
							</button>
						</div>
					</div>
				</div>

				<?php /* Success state */ ?>
				<div id="pkits-sp-nudge-success" style="display:none;">
					<div class="pkits-sp-nudge-success-icon">&#10003;</div>
					<p class="pkits-sp-nudge-success-msg"></p>
					<button type="button" class="button pkits-sp-nudge-modal-close">
						<?php esc_html_e( 'Close', 'publisherkits-socialpromoter' ); ?>
					</button>
				</div>

			</div>
		</div>
		<?php
	}

	// ----------------------------------------------------------------
	// AJAX
	// ----------------------------------------------------------------

	/**
	 * AJAX: set the promotion status for a post.
	 *
	 * @return void
	 */
	public function ajax_set_promotion_status() {
		check_ajax_referer( 'pkits_sp_set_promotion_status', 'nonce' );

		if ( ! current_user_can( 'edit_posts' ) ) {
			wp_send_json_error( array( 'message' => esc_html__( 'Permission denied.', 'publisherkits-socialpromoter' ) ) );
		}

		$post_id = absint( isset( $_POST['post_id'] ) ? wp_unslash( $_POST['post_id'] ) : 0 );
		if ( ! $post_id || ! current_user_can( 'edit_post', $post_id ) ) {
			wp_send_json_error( array( 'message' => __( 'You cannot edit this post.', 'publisherkits-socialpromoter' ) ), 403 );
		}
		$status  = isset( $_POST['status'] ) ? sanitize_key( wp_unslash( $_POST['status'] ) ) : '';

		$allowed = array( 'pending', 'promoted', 'dismissed' );
		if ( ! $post_id || ! in_array( $status, $allowed, true ) ) {
			wp_send_json_error( array( 'message' => esc_html__( 'Invalid parameters.', 'publisherkits-socialpromoter' ) ) );
		}

		if ( ! get_post( $post_id ) ) {
			wp_send_json_error( array( 'message' => esc_html__( 'Post not found.', 'publisherkits-socialpromoter' ) ) );
		}

		update_post_meta( $post_id, self::META_KEY, $status );
		wp_send_json_success();
	}

	// ----------------------------------------------------------------
	// Posts list filter
	// ----------------------------------------------------------------

	/**
	 * Add "Promotion status" dropdown filter to the posts list table.
	 *
	 * @param string $post_type Current post type.
	 * @return void
	 */
	public function add_promotion_filter_dropdown( $post_type ) {
		if ( ! $this->is_supported_post_type( $post_type ) ) {
			return;
		}

		// phpcs:ignore WordPress.Security.NonceVerification.Recommended
		$selected = isset( $_GET['pkits_sp_promo_filter'] ) ? sanitize_key( wp_unslash( $_GET['pkits_sp_promo_filter'] ) ) : '';
		?>
		<select name="pkits_sp_promo_filter" id="pkits-sp-promo-filter">
			<option value=""><?php esc_html_e( 'All promotion statuses', 'publisherkits-socialpromoter' ); ?></option>
			<option value="pending" <?php selected( $selected, 'pending' ); ?>><?php esc_html_e( 'Not yet promoted', 'publisherkits-socialpromoter' ); ?></option>
			<option value="promoted" <?php selected( $selected, 'promoted' ); ?>><?php esc_html_e( 'Promoted', 'publisherkits-socialpromoter' ); ?></option>
			<option value="dismissed" <?php selected( $selected, 'dismissed' ); ?>><?php esc_html_e( 'Dismissed', 'publisherkits-socialpromoter' ); ?></option>
		</select>
		<?php
	}

	/**
	 * Filter the posts query by promotion status.
	 *
	 * @param WP_Query $query The current WP_Query.
	 * @return void
	 */
	public function filter_posts_by_promotion_status( $query ) {
		global $pagenow;

		if ( ! is_admin() || 'edit.php' !== $pagenow || ! $query->is_main_query() ) {
			return;
		}

		// phpcs:ignore WordPress.Security.NonceVerification.Recommended
		$filter = isset( $_GET['pkits_sp_promo_filter'] ) ? sanitize_key( wp_unslash( $_GET['pkits_sp_promo_filter'] ) ) : '';

		if ( empty( $filter ) ) {
			return;
		}

		$allowed = array( 'pending', 'promoted', 'dismissed' );
		if ( ! in_array( $filter, $allowed, true ) ) {
			return;
		}

		if ( 'pending' === $filter ) {
			// Include posts with empty meta OR 'pending' value.
			$meta_query = array(
				'relation' => 'OR',
				array(
					'key'     => self::META_KEY,
					'value'   => 'pending',
					'compare' => '=',
				),
				array(
					'key'     => self::META_KEY,
					'compare' => 'NOT EXISTS',
				),
			);
		} else {
			$meta_query = array(
				array(
					'key'     => self::META_KEY,
					'value'   => $filter,
					'compare' => '=',
				),
			);
		}

		$query->set( 'meta_query', $meta_query );
	}

	// ----------------------------------------------------------------
	// Helpers
	// ----------------------------------------------------------------

	/**
	 * Check whether the nudge feature is enabled.
	 *
	 * Reads from plugin settings; defaults to enabled.
	 *
	 * @return bool
	 */
	private function nudge_enabled() {
		$settings = get_option( 'pkits_sp_settings', array() );
		if ( isset( $settings['nudge_enabled'] ) && ! $settings['nudge_enabled'] ) {
			return false;
		}
		return true;
	}

	/**
	 * Check whether the unpromoted banner is enabled.
	 *
	 * @return bool
	 */
	private function nudge_banner_enabled() {
		$settings = get_option( 'pkits_sp_settings', array() );
		if ( isset( $settings['nudge_banner_enabled'] ) && ! $settings['nudge_banner_enabled'] ) {
			return false;
		}
		return true;
	}

	/**
	 * Check whether the current user holds one of the roles the publisher chose
	 * to nudge.
	 *
	 * Defaults to administrator and editor, matching the default the Settings
	 * screen shows, so a site that has never touched the control is unaffected.
	 * An empty list cannot arrive from the form - the save handler turns "none
	 * ticked" back into the default - so it is treated as unconfigured here too;
	 * silencing the nudge for everyone is what the master switch is for.
	 *
	 * @return bool
	 */
	private function role_allowed() {
		$settings = get_option( 'pkits_sp_settings', array() );
		$settings = is_array( $settings ) ? $settings : array();

		$roles = isset( $settings['nudge_roles'] ) && is_array( $settings['nudge_roles'] )
			? $settings['nudge_roles']
			: array();
		if ( empty( $roles ) ) {
			$roles = array( 'administrator', 'editor' );
		}

		$user = wp_get_current_user();
		if ( ! $user || ! $user->exists() ) {
			return false;
		}

		return ! empty( array_intersect( $roles, (array) $user->roles ) );
	}

	/**
	 * Check whether a post type should trigger the nudge.
	 *
	 * @param string $post_type Post type slug.
	 * @return bool
	 */
	private function is_supported_post_type( $post_type ) {
		$settings       = get_option( 'pkits_sp_settings', array() );
		$default_types  = array( 'post' );
		$supported      = isset( $settings['nudge_post_types'] ) && is_array( $settings['nudge_post_types'] )
			? $settings['nudge_post_types']
			: $default_types;

		/** This filter is documented in includes/class-sp-metabox.php */
		$supported = apply_filters( 'pkits_sp_nudge_post_types', $supported );

		return in_array( $post_type, $supported, true );
	}
}
