<?php

/**
 * Registers and renders the Offer edit screen's metaboxes (Scope, Conditions, Offers, Pricing) and handles saving them.
 *
 * @link       https://nudgesells.com
 * @since      1.0.0
 *
 * @package    NudgeSells
 * @subpackage NudgeSells/admin
 */

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

/**
 * NudgeSells_Admin_Offer
 *
 * Builds the Offer custom post type's edit-screen metaboxes and persists their submitted values on save.
 *
 * @since      1.0.0
 * @package    NudgeSells
 * @subpackage NudgeSells/admin
 * @author     NudgeSells <support@nudgesells.com>
 */
class NudgeSells_Admin_Offer
{

	/**
	 * Ajax search terms categories.
	 *
	 * @return void
	 * @since 1.0.0
	 */
	public function ajax_search_terms_categories()
	{
		$this->ajax_search_terms('product_cat');
	}

	/**
	 * Ajax search terms tags.
	 *
	 * @return void
	 * @since 1.0.0
	 */
	public function ajax_search_terms_tags()
	{
		$this->ajax_search_terms('product_tag');
	}

	/**
	 * Ajax search terms.
	 *
	 * @param mixed $taxonomy
	 *
	 * @return void
	 * @since 1.0.0
	 */
	private function ajax_search_terms($taxonomy)
	{
		check_ajax_referer('search-products', 'security');
		if (! current_user_can('edit_products')) {
			wp_die(-1);
		}
		$term_search = isset($_GET['term']) ? sanitize_text_field(wp_unslash($_GET['term'])) : '';
		$terms = get_terms(array(
			'taxonomy'   => $taxonomy,
			'name__like' => $term_search,
			'number'     => 20,
			'hide_empty' => false,
		));
		$results = array();
		if (! is_wp_error($terms)) {
			foreach ($terms as $term) {
				$results[] = array('id' => $term->term_id, 'name' => $term->name);
			}
		}
		wp_send_json($results);
	}

	/**
	 * Title placeholder.
	 *
	 * @param mixed $placeholder
	 *
	 * @return mixed
	 * @since 1.0.0
	 */
	public function title_placeholder($placeholder)
	{
		$screen = get_current_screen();
		if ($screen && NudgeSells_CPT::POST_TYPE === $screen->post_type) {
			return __('Offer name (internal - customers never see this)', 'nudgesells');
		}
		return $placeholder;
	}

	/**
	 * Add metaboxes.
	 *
	 * @return void
	 * @since 1.0.0
	 */
	public function add_metaboxes()
	{
		$screen = NudgeSells_CPT::POST_TYPE;
		add_meta_box('nudgesells_scope', __('1. Scope - where it applies', 'nudgesells'), array($this, 'render_scope'), $screen, 'normal', 'high');
		add_meta_box('nudgesells_conditions', __('2. Conditions - when it triggers', 'nudgesells'), array($this, 'render_conditions'), $screen, 'normal', 'high');
		add_meta_box('nudgesells_offers', __('3. Offers - what is shown', 'nudgesells'), array($this, 'render_offers'), $screen, 'normal', 'high');
		if (NudgeSells_Pro_Loader::is_active()) {
			add_meta_box('nudgesells_pricing', __('4. Pricing Rules - how price changes', 'nudgesells'), array($this, 'render_pricing'), $screen, 'normal', 'high');
		}
		add_meta_box('nudgesells_status', __('Offer status', 'nudgesells'), array($this, 'render_status'), $screen, 'side', 'high');
	}

	/**
	 * Assets.
	 *
	 * @param mixed $hook
	 *
	 * @return void
	 * @since 1.0.0
	 */
	public function assets($hook)
	{
		global $post;
		if (! in_array($hook, array('post.php', 'post-new.php'), true)) {
			return;
		}
		if (! $post || NudgeSells_CPT::POST_TYPE !== $post->post_type) {
			return;
		}

		wp_enqueue_style('nudgesells-admin', NUDGESELLS_PLUGIN_URL . 'admin/css/nudgesells-admin.css', array(), NUDGESELLS_VERSION);
		wp_enqueue_media();

		if (! wp_script_is('select2', 'registered')) {
			wp_register_script('select2', WC()->plugin_url() . '/assets/js/select2/select2.full.min.js', array('jquery'), '4.0.3', true);
		}
		if (! wp_style_is('select2', 'registered')) {
			wp_register_style('select2', WC()->plugin_url() . '/assets/css/select2.css', array(), '4.0.3');
		}
		wp_enqueue_script('select2');
		wp_enqueue_style('select2');

		wp_enqueue_script('jquery-ui-datepicker');
		wp_enqueue_script('nudgesells-admin', NUDGESELLS_PLUGIN_URL . 'admin/js/nudgesells-admin.js', array('jquery', 'select2', 'jquery-ui-datepicker'), NUDGESELLS_VERSION, true);

		$rules = NudgeSells_Rules_Repository::get_rules_for_offer($post->ID);
		$scope = NudgeSells_Offer_Repository::get_scope($post->ID);

		if ('post-new.php' === $hook && isset($_GET['nudgesells_suggest_host'], $_GET['nudgesells_suggest_addon'])) {
			$suggest_host  = absint($_GET['nudgesells_suggest_host']);
			$suggest_addon = absint($_GET['nudgesells_suggest_addon']);
			if ($suggest_host && $suggest_addon && wc_get_product($suggest_host) && wc_get_product($suggest_addon)) {
				$scope = array(
					'type'        => 'products',
					'ids'         => array($suggest_host),
					'exclude_ids' => array(),
				);
				$rules['addons'] = array(
					array(
						'product_id'      => $suggest_addon,
						'discount_type'   => 'percent',
						'discount_value'  => 0,
						'label'           => '',
					),
				);
			}
		}

		$product_ids = array_merge(
			wp_list_pluck($rules['addons'], 'product_id'),
			wp_list_pluck($rules['upgrades'], 'product_id'),
			'products' === $scope['type'] ? $scope['ids'] : array(),
			'products' === $scope['type'] ? $scope['exclude_ids'] : array()
		);
		$product_labels = array();
		foreach (array_unique($product_ids) as $pid) {
			$p = wc_get_product($pid);
			if ($p) {

				$product_labels[$pid] = rawurldecode($p->get_name()) . ' (#' . $pid . ')';
			}
		}

		$term_labels = array();
		if (in_array($scope['type'], array('categories', 'tags'), true)) {
			$taxonomy = 'categories' === $scope['type'] ? 'product_cat' : 'product_tag';
			foreach ($scope['ids'] as $term_id) {
				$term = get_term($term_id, $taxonomy);
				if ($term && ! is_wp_error($term)) {
					$term_labels[$term_id] = $term->name;
				}
			}
		}

		wp_localize_script('nudgesells-admin', 'NudgeSells_Admin', array(
			'ajax_url'        => admin_url('admin-ajax.php'),
			'search_nonce'    => wp_create_nonce('search-products'),
			'is_pro'          => NudgeSells_Pro_Loader::is_active(),
			'rules'           => $rules,
			'scope'           => $scope,
			'product_labels'  => $product_labels,
			'term_labels'     => $term_labels,
			'currency_symbol' => get_woocommerce_currency_symbol(),
			'i18n'            => array(
				'select_product'  => __('Search for a product…', 'nudgesells'),
				'select_category' => __('Search for a category…', 'nudgesells'),
				'select_tag'      => __('Search for a tag…', 'nudgesells'),
				'remove'          => __('Remove', 'nudgesells'),
				'badge_placeholder' => __('e.g. Bestseller', 'nudgesells'),
				'col_product'         => __('Product', 'nudgesells'),
				'col_upgrade_product' => __('Upgrade product', 'nudgesells'),
				'col_type'            => __('Discount type', 'nudgesells'),
				'col_value'           => __('Discount value', 'nudgesells'),
				'col_label'           => __('Badge (optional)', 'nudgesells'),
				'col_subline'         => __('Subline', 'nudgesells'),
				'col_default_value'   => __('Default value', 'nudgesells'),
				'col_sublabel'        => __('Sublabel / reason', 'nudgesells'),
				'col_tier_label'      => __('Label', 'nudgesells'),
				'col_min_qty'         => __('Min. add-on qty', 'nudgesells'),
				'free_gift'           => __('Free gift (specific product)', 'nudgesells'),
				'free_units'          => __('Free units (any add-on)', 'nudgesells'),
				'free_units_gift'     => __('Free units of a specific product', 'nudgesells'),
				'repeat_scale'        => __('Repeat scale (buy 1 get 1, buy 2 get 2, etc.)', 'nudgesells'),
				'free_qty_placeholder' => __('e.g. 2', 'nudgesells'),
				'percent_off'         => __('% off', 'nudgesells'),
				'fixed_off'           => __('Fixed amount off', 'nudgesells'),
				'fixed_price'         => __('Fixed price', 'nudgesells'),
				'select_gift_product' => __('Select an add-on...', 'nudgesells'),
				'select_icon_title'   => __('Select Icon', 'nudgesells'),
				'select_icon_button'  => __('Use this icon', 'nudgesells'),
			),
		));
	}

	/**
	 * Render scope.
	 *
	 * @param mixed $post
	 *
	 * @return void
	 * @since 1.0.0
	 */
	public function render_scope($post)
	{
		wp_nonce_field('nudgesells_save_offer', 'nudgesells_offer_nonce');
		$scope = NudgeSells_Offer_Repository::get_scope($post->ID);
?>
		<p class="description">
			<?php esc_html_e('Which product pages should this offer appear on?', 'nudgesells'); ?>
			<?php if (NudgeSells_Pro_Loader::is_active()) : ?>
				<?php esc_html_e('For variable products, you can pick the parent product (applies to every variation) or search for one specific variation to scope the offer to just that option.', 'nudgesells'); ?>
			<?php else : ?>
				<?php esc_html_e('For variable products, this applies to every variation. Scoping to one specific variation is a Pro feature.', 'nudgesells'); ?>
			<?php endif; ?>
		</p>
		<p>
			<label style="margin-right:16px"><input type="radio" name="nudgesells_scope_type_display" value="all" <?php checked($scope['type'], 'all'); ?> /> <?php esc_html_e('All products', 'nudgesells'); ?></label>
			<label style="margin-right:16px"><input type="radio" name="nudgesells_scope_type_display" value="products" <?php checked($scope['type'], 'products'); ?> /> <?php esc_html_e('Specific products', 'nudgesells'); ?></label>
			<label style="margin-right:16px"><input type="radio" name="nudgesells_scope_type_display" value="categories" <?php checked($scope['type'], 'categories'); ?> /> <?php esc_html_e('Specific categories', 'nudgesells'); ?></label>
			<label><input type="radio" name="nudgesells_scope_type_display" value="tags" <?php checked($scope['type'], 'tags'); ?> /> <?php esc_html_e('Specific tags', 'nudgesells'); ?></label>
		</p>
		<div id="nudgesells-scope-products-wrap" class="nudgesells-scope-sub"><select multiple id="nudgesells-scope-products" style="width:100%"></select></div>
		<div id="nudgesells-scope-categories-wrap" class="nudgesells-scope-sub"><select multiple id="nudgesells-scope-categories" style="width:100%"></select></div>
		<div id="nudgesells-scope-tags-wrap" class="nudgesells-scope-sub"><select multiple id="nudgesells-scope-tags" style="width:100%"></select></div>

		<div id="nudgesells-scope-exclude-wrap">
			<p style="margin-top:16px" class="description"><?php esc_html_e('Always exclude these products, even if matched above (optional):', 'nudgesells'); ?></p>
			<select multiple id="nudgesells-scope-exclude" style="width:100%"></select>
		</div>

		<input type="hidden" name="nudgesells_scope_type" id="nudgesells-scope-type-hidden" value="<?php echo esc_attr($scope['type']); ?>" />
		<input type="hidden" name="nudgesells_scope_ids" id="nudgesells-scope-ids-hidden" value="<?php echo esc_attr(implode(',', $scope['ids'])); ?>" />
		<input type="hidden" name="nudgesells_exclude_ids" id="nudgesells-exclude-ids-hidden" value="<?php echo esc_attr(implode(',', $scope['exclude_ids'])); ?>" />
	<?php
	}

	/**
	 * Render conditions.
	 *
	 * @param mixed $post
	 *
	 * @return void
	 * @since 1.0.0
	 */
	public function render_conditions($post)
	{
		$user_condition = get_post_meta($post->ID, '_nudgesells_condition_user', true) ?: 'everyone';
		$is_pro         = NudgeSells_Pro_Loader::is_active();
		$locked         = $is_pro ? '' : 'disabled';
		$pro_badge      = '<span class="nudgesells-badge" style="background:var(--ns-accent-dark);color:#fff;margin-inline-start:6px;">' . esc_html__('Pro', 'nudgesells') . '</span>';
	?>
		<table class="form-table">
			<?php
			/**
			 * Fires at the top of the Conditions metabox -- Pro renders its
			 * Minimum Product Quantity field here as an additional <tr> row.
			 *
			 * @param WP_Post $post
			 * @param bool    $is_pro
			 * @param string  $locked    'disabled' attribute string when Pro isn't active.
			 * @param string  $pro_badge Pre-rendered "Pro" badge markup.
			 */
			do_action('nudgesells_conditions_fields_top', $post, $is_pro, $locked, $pro_badge);
			?>
			<tr>
				<th><?php esc_html_e('Customer', 'nudgesells'); ?></th>
				<td>
					<select name="nudgesells_condition_user">
						<option value="everyone" <?php selected($user_condition, 'everyone'); ?>><?php esc_html_e('Everyone', 'nudgesells'); ?></option>
						<option value="logged_in" <?php selected($user_condition, 'logged_in'); ?>><?php esc_html_e('Logged-in customers only', 'nudgesells'); ?></option>
						<option value="logged_out" <?php selected($user_condition, 'logged_out'); ?>><?php esc_html_e('Guests only', 'nudgesells'); ?></option>
					</select>
				</td>
			</tr>
			<?php
			/**
			 * Fires at the bottom of the Conditions metabox -- Pro renders
			 * its Restrict To User Roles and Active Date Range fields here
			 * as additional <tr> rows.
			 *
			 * @param WP_Post $post
			 * @param bool    $is_pro
			 * @param string  $locked    'disabled' attribute string when Pro isn't active.
			 * @param string  $pro_badge Pre-rendered "Pro" badge markup.
			 */
			do_action('nudgesells_conditions_fields_bottom', $post, $is_pro, $locked, $pro_badge);
			?>
		</table>
	<?php
	}

	/**
	 * Render section heading fields.
	 *
	 * @param mixed $post_id
	 * @param mixed $prefix
	 * @param mixed $title_default
	 *
	 * @return void
	 * @since 1.0.0
	 */
	public static function render_section_heading_fields($post_id, $prefix, $title_default)
	{
		$title         = get_post_meta($post_id, "_nudgesells_{$prefix}_title", true);
		$subline       = get_post_meta($post_id, "_nudgesells_{$prefix}_subline", true);
		$icon_id       = absint(get_post_meta($post_id, "_nudgesells_{$prefix}_icon_id", true));
		$icon_url      = $icon_id ? wp_get_attachment_image_url($icon_id, 'thumbnail') : '';
		$readmore_text = get_post_meta($post_id, "_nudgesells_{$prefix}_readmore_text", true);
		$readmore_url  = get_post_meta($post_id, "_nudgesells_{$prefix}_readmore_url", true);
	?>
		<div class="nudgesells-section-heading-fields">
			<div class="nudgesells-heading-field-row">

				<div class="nudgesells-heading-col-icon">
					<label><strong><?php esc_html_e('Icon', 'nudgesells'); ?></strong></label>
					<img id="nudgesells-<?php echo esc_attr($prefix); ?>-icon-preview" src="<?php echo esc_url($icon_url); ?>" class="nudgesells-icon-preview" style="<?php echo $icon_url ? '' : 'display:none;'; ?>" alt="" />
					<button type="button" class="button nudgesells-select-icon" data-target="<?php echo esc_attr($prefix); ?>"><?php esc_html_e('Select', 'nudgesells'); ?></button>
					<button type="button" class="button-link nudgesells-remove-icon" data-target="<?php echo esc_attr($prefix); ?>" style="<?php echo $icon_url ? '' : 'display:none;'; ?>"><?php esc_html_e('Remove', 'nudgesells'); ?></button>
					<input type="hidden" id="nudgesells-<?php echo esc_attr($prefix); ?>-icon-id" name="nudgesells_<?php echo esc_attr($prefix); ?>_icon_id" value="<?php echo esc_attr($icon_id); ?>" />
					<span class="description"><?php esc_html_e('Optional', 'nudgesells'); ?></span>
				</div>

				<div class="nudgesells-heading-col-title">
					<label for="nudgesells-<?php echo esc_attr($prefix); ?>-title"><strong><?php esc_html_e('Section heading', 'nudgesells'); ?></strong></label>
					<input type="text" id="nudgesells-<?php echo esc_attr($prefix); ?>-title" name="nudgesells_<?php echo esc_attr($prefix); ?>_title" value="<?php echo esc_attr($title); ?>" placeholder="<?php echo esc_attr($title_default); ?>" />
					<input type="text" id="nudgesells-<?php echo esc_attr($prefix); ?>-subline" name="nudgesells_<?php echo esc_attr($prefix); ?>_subline" value="<?php echo esc_attr($subline); ?>" placeholder="<?php esc_attr_e('Subline (optional) - a short supporting line shown under the heading', 'nudgesells'); ?>" />
					<span class="description"><?php esc_html_e('Leave the heading blank to use the default.', 'nudgesells'); ?></span>
				</div>

				<div class="nudgesells-heading-col-link">
					<label><strong><?php esc_html_e('"Read more" link', 'nudgesells'); ?></strong></label>
					<input type="text" name="nudgesells_<?php echo esc_attr($prefix); ?>_readmore_text" value="<?php echo esc_attr($readmore_text); ?>" placeholder="<?php esc_attr_e('Link text, e.g. Learn more', 'nudgesells'); ?>" />
					<input type="url" name="nudgesells_<?php echo esc_attr($prefix); ?>_readmore_url" value="<?php echo esc_attr($readmore_url); ?>" placeholder="https://…" />
					<span class="description"><?php esc_html_e('Optional', 'nudgesells'); ?></span>
				</div>

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

	/**
	 * Render offers.
	 *
	 * @param mixed $post
	 *
	 * @return void
	 * @since 1.0.0
	 */
	public function render_offers($post)
	{
		$display_style  = NudgeSells_Rules_Repository::get_raw_display_style($post->ID);
	?>
		<div id="nudgesells-admin-app">
			<p class="nudgesells-display-style-picker">
				<strong><?php esc_html_e('Add-on display style:', 'nudgesells'); ?></strong>
				<label style="margin-left:10px">
					<input type="radio" name="nudgesells_display_style" value="inherit" <?php checked($display_style, 'inherit'); ?> />
					<?php
					$inherited = NudgeSells_Admin_Settings::get('default_display', 'list');
					printf(
						/* translators: %s: default display setting value */
						esc_html__('Inherit from Settings (currently: %s)', 'nudgesells'),
						'card' === $inherited ? esc_html__('Cards', 'nudgesells') : esc_html__('List', 'nudgesells')
					);
					?>
				</label>
				<label style="margin-left:16px"><input type="radio" name="nudgesells_display_style" value="list" <?php checked($display_style, 'list'); ?> /> <?php esc_html_e('List (compact rows)', 'nudgesells'); ?></label>
				<label style="margin-left:16px"><input type="radio" name="nudgesells_display_style" value="card" <?php checked($display_style, 'card'); ?> /> <?php esc_html_e('Cards (grid with larger images)', 'nudgesells'); ?></label>
			</p>

			<?php if (NudgeSells_Pro_Loader::is_active()) : ?>
				<div class="nudgesells-tabs">
					<button type="button" class="nudgesells-tab-btn active" data-tab="addons"><?php esc_html_e('Add-ons', 'nudgesells'); ?></button>
					<button type="button" class="nudgesells-tab-btn" data-tab="upgrades"><?php esc_html_e('Upgrades', 'nudgesells'); ?></button>
				</div>
			<?php endif; ?>

			<div class="nudgesells-tab-panel" data-tab="addons">
				<p class="description"><?php esc_html_e('Products offered as inline add-ons above the Add to Cart button on every page this offer applies to.', 'nudgesells'); ?></p>
				<?php self::render_section_heading_fields($post->ID, 'addons', __('Frequently added together', 'nudgesells')); ?>
				<div class="nudgesells-repeater-wrap">
					<table class="widefat nudgesells-repeater" id="nudgesells-addons-table">
						<thead>
							<tr>
								<th><?php esc_html_e('Product', 'nudgesells'); ?></th>
								<th style="width:110px"><?php esc_html_e('Discount type', 'nudgesells'); ?></th>
								<th style="width:100px"><?php esc_html_e('Discount value', 'nudgesells'); ?></th>
								<th style="width:180px"><?php esc_html_e('Badge (optional)', 'nudgesells'); ?></th>
								<th style="width:180px"><?php esc_html_e('Subline', 'nudgesells'); ?></th>
								<th style="width:110px"><?php esc_html_e('Default value', 'nudgesells'); ?></th>
								<th style="width:40px"></th>
							</tr>
						</thead>
						<tbody></tbody>
					</table>
				</div>
				<button type="button" class="button nudgesells-add-row" data-repeater="addons"><?php esc_html_e('+ Add product add-on', 'nudgesells'); ?></button>

				<?php
				$addons_selection_type = get_post_meta($post->ID, '_nudgesells_addons_selection_type', true);
				$addons_selection_type = in_array($addons_selection_type, array('checkbox', 'qty'), true) ? $addons_selection_type : 'checkbox';
				?>
				<div style="margin-top:16px;">
					<label for="nudgesells-addons-selection-type"><strong><?php esc_html_e('Selection type', 'nudgesells'); ?></strong></label><br />
					<select id="nudgesells-addons-selection-type" style="margin:6px 0;">
						<option value="checkbox" <?php selected('checkbox', $addons_selection_type); ?>><?php esc_html_e('Checkbox (quantity of 1)', 'nudgesells'); ?></option>
						<option value="qty" <?php selected('qty', $addons_selection_type); ?>><?php esc_html_e('Quantity input', 'nudgesells'); ?></option>
					</select>
				<p class="description"><?php esc_html_e('Applies to every add-on in the table above -- all rows use the same selection type.', 'nudgesells'); ?></p>
				<p class="description"><?php esc_html_e('Each add-on\'s own "Default value" above works with either type: with Checkbox selected, a value of 1 makes that add-on pre-checked; with Quantity input selected, the value becomes the starting quantity shown.', 'nudgesells'); ?></p>
				</div>
			</div>

			<?php if (NudgeSells_Pro_Loader::is_active()) : ?>
				<div class="nudgesells-tab-panel" data-tab="upgrades" style="display:none">
					<?php
					/**
					 * Fires inside the Upgrades tab panel - Pro renders the
					 * entire tab's content here (original-option labels, the
					 * upgrades repeater table, etc.).
					 *
					 * @param WP_Post $post
					 */
					do_action('nudgesells_render_upgrades_tab_content', $post);
					?>
				</div>
			<?php endif; ?>
			<input type="hidden" name="nudgesells_rules_json" id="nudgesells-rules-json" value="" />
		</div>
	<?php
	}

	/**
	 * Render pricing.
	 *
	 * @param mixed $post
	 *
	 * @return void
	 * @since 1.0.0
	 */
	public function render_pricing($post)
	{
		$is_pro = NudgeSells_Pro_Loader::is_active();
	?>
		<div class="nudgesells-tab-panel" data-tab="bundle" style="display:block">
			<p class="description"><?php esc_html_e('Give an extra discount when the customer selects ALL of the add-ons above.', 'nudgesells'); ?></p>
			<?php if ($is_pro) : ?>
				<?php
				/**
				 * Fires inside the Bundle tab panel when Pro is active -- Pro
				 * renders the enable checkbox, discount type/value/label
				 * fields here.
				 *
				 * @param WP_Post $post
				 */
				do_action('nudgesells_render_bundle_tab_content', $post);
				?>
			<?php else : ?>
				<div class="nudgesells-note-box"><?php esc_html_e('Bundle discounts are a Pro feature.', 'nudgesells'); ?></div>
			<?php endif; ?>
		</div>
		<div class="nudgesells-tab-panel" data-tab="tiers" style="display:block; margin-top:20px; border-top:1px dashed #ddd; padding-top:16px;">
			<p class="description"><?php esc_html_e('Discount increases with total add-on quantity selected. Only the highest matching tier applies, competing against the bundle discount above - the better one wins.', 'nudgesells'); ?></p>
			<p class="description"><?php echo wp_kses(__('A tier\'s Label is the progress message shown while the customer is still working toward it. Use <code>{qty}</code> anywhere in it to insert the remaining quantity automatically - e.g. "Only {qty} left to unlock free shipping!"', 'nudgesells'), array('code' => array())); ?></p>
			<?php if ($is_pro) : ?>
				<?php
				/**
				 * Fires inside the Tiers tab panel when Pro is active -- Pro
				 * renders the tiers repeater table and the final-tier-reached
				 * message field here.
				 *
				 * @param WP_Post $post
				 */
				do_action('nudgesells_render_tiers_tab_content', $post);
				?>
			<?php else : ?>
				<div class="nudgesells-note-box"><?php esc_html_e('Tiered quantity discounts are a Pro feature.', 'nudgesells'); ?></div>
			<?php endif; ?>
		</div>
	<?php
	}

	/**
	 * Render status.
	 *
	 * @param mixed $post
	 *
	 * @return void
	 * @since 1.0.0
	 */
	public function render_status($post)
	{
		$priority = get_post_meta($post->ID, '_nudgesells_priority', true) ?: 10;
	?>
		<p>
			<label for="nudgesells_priority"><strong><?php esc_html_e('Priority', 'nudgesells'); ?></strong></label><br />
			<input type="number" id="nudgesells_priority" name="nudgesells_priority" value="<?php echo esc_attr($priority); ?>" style="width:100%" />
			<span class="description"><?php esc_html_e('Lower number = higher priority. If two offers match the same product, the lower number wins.', 'nudgesells'); ?></span>
		</p>
		<p class="description"><?php esc_html_e('Publish this offer to make it live. Move it to Draft to pause it without losing your settings.', 'nudgesells'); ?></p>
	<?php
	}

	/**
	 * Resolve to parent product id.
	 *
	 * @param int $id
	 *
	 * @return int
	 * @since 1.0.0
	 */
	private static function resolve_to_parent_product_id($id)
	{
		$product = wc_get_product($id);
		if ($product instanceof WC_Product_Variation) {
			return (int) $product->get_parent_id();
		}
		return (int) $id;
	}

	public function save($offer_id)
	{
		if (! isset($_POST['nudgesells_offer_nonce']) || ! wp_verify_nonce(sanitize_text_field(wp_unslash($_POST['nudgesells_offer_nonce'])), 'nudgesells_save_offer')) {
			return;
		}
		if (defined('DOING_AUTOSAVE') && DOING_AUTOSAVE) {
			return;
		}
		if (! current_user_can('edit_post', $offer_id)) {
			return;
		}

		$scope_type = isset($_POST['nudgesells_scope_type']) ? sanitize_key($_POST['nudgesells_scope_type']) : 'products';
		if (! in_array($scope_type, array('all', 'products', 'categories', 'tags'), true)) {
			$scope_type = 'products';
		}
		$scope_ids = (isset($_POST['nudgesells_scope_ids']) && is_scalar($_POST['nudgesells_scope_ids']))
			? array_map('absint', explode(',', wp_unslash($_POST['nudgesells_scope_ids'])))
			: array();
		$scope_ids = array_values(array_filter($scope_ids));
		$exclude_ids = (isset($_POST['nudgesells_exclude_ids']) && is_scalar($_POST['nudgesells_exclude_ids']))
			? array_map('absint', explode(',', wp_unslash($_POST['nudgesells_exclude_ids'])))
			: array();
		$exclude_ids = array_values(array_filter($exclude_ids));

		if ('products' === $scope_type && ! NudgeSells_Pro_Loader::is_active()) {
			$scope_ids   = array_unique(array_map(array(__CLASS__, 'resolve_to_parent_product_id'), $scope_ids));
			$exclude_ids = array_unique(array_map(array(__CLASS__, 'resolve_to_parent_product_id'), $exclude_ids));
		}

		update_post_meta($offer_id, '_nudgesells_scope_type', $scope_type);
		update_post_meta($offer_id, '_nudgesells_scope_ids', $scope_ids);
		update_post_meta($offer_id, '_nudgesells_exclude_ids', $exclude_ids);

		$is_pro = NudgeSells_Pro_Loader::is_active();

		$user_condition = isset($_POST['nudgesells_condition_user']) ? sanitize_key($_POST['nudgesells_condition_user']) : 'everyone';
		if (! in_array($user_condition, array('everyone', 'logged_in', 'logged_out'), true)) {
			$user_condition = 'everyone';
		}
		update_post_meta($offer_id, '_nudgesells_condition_user', $user_condition);

		/**
		 * Fires where the Conditions metabox's Pro-only fields (user
		 * roles, active date range, minimum quantity) are saved -- core no
		 * longer writes these post meta keys itself, so Pro is entirely
		 * responsible for both defining and persisting them.
		 *
		 * @param int  $offer_id
		 * @param bool $is_pro
		 */
		do_action('nudgesells_save_conditions_fields', $offer_id, $is_pro);

		update_post_meta($offer_id, '_nudgesells_priority', isset($_POST['nudgesells_priority']) ? absint($_POST['nudgesells_priority']) : 10);

		$display_style = isset($_POST['nudgesells_display_style']) ? sanitize_key($_POST['nudgesells_display_style']) : 'inherit';
		if (! in_array($display_style, array('list', 'card', 'inherit'), true)) {
			$display_style = 'inherit';
		}
		update_post_meta($offer_id, '_nudgesells_display_style', $display_style);

		update_post_meta($offer_id, '_nudgesells_addons_title', isset($_POST['nudgesells_addons_title']) ? sanitize_text_field(wp_unslash($_POST['nudgesells_addons_title'])) : '');
		update_post_meta($offer_id, '_nudgesells_upgrades_title', isset($_POST['nudgesells_upgrades_title']) ? sanitize_text_field(wp_unslash($_POST['nudgesells_upgrades_title'])) : '');

		foreach (array('addons', 'upgrades') as $prefix) {
			update_post_meta($offer_id, "_nudgesells_{$prefix}_subline", isset($_POST["nudgesells_{$prefix}_subline"]) ? sanitize_text_field(wp_unslash($_POST["nudgesells_{$prefix}_subline"])) : '');
			update_post_meta($offer_id, "_nudgesells_{$prefix}_icon_id", isset($_POST["nudgesells_{$prefix}_icon_id"]) ? absint($_POST["nudgesells_{$prefix}_icon_id"]) : 0);
			update_post_meta($offer_id, "_nudgesells_{$prefix}_readmore_text", isset($_POST["nudgesells_{$prefix}_readmore_text"]) ? sanitize_text_field(wp_unslash($_POST["nudgesells_{$prefix}_readmore_text"])) : '');
			update_post_meta($offer_id, "_nudgesells_{$prefix}_readmore_url", isset($_POST["nudgesells_{$prefix}_readmore_url"]) ? esc_url_raw(wp_unslash($_POST["nudgesells_{$prefix}_readmore_url"])) : '');
		}

		update_post_meta($offer_id, '_nudgesells_upgrades_original_label', isset($_POST['nudgesells_upgrades_original_label']) ? sanitize_text_field(wp_unslash($_POST['nudgesells_upgrades_original_label'])) : '');
		update_post_meta($offer_id, '_nudgesells_upgrades_original_sublabel', isset($_POST['nudgesells_upgrades_original_sublabel']) ? sanitize_text_field(wp_unslash($_POST['nudgesells_upgrades_original_sublabel'])) : '');

		/**
		 * Fires where the Tiers tab's Pro-only "final tier reached"
		 * message is saved.
		 *
		 * @param int  $offer_id
		 * @param bool $is_pro
		 */
		do_action('nudgesells_save_tier_final_message', $offer_id, $is_pro);

		$json = (isset($_POST['nudgesells_rules_json']) && is_scalar($_POST['nudgesells_rules_json']))
			? wp_unslash($_POST['nudgesells_rules_json'])
			: '';
		$data = json_decode($json, true);
		if (! is_array($data)) {
			$data = array();
		}
		$data = NudgeSells_Rules_Repository::sanitize_rules_payload($data);

		if (! $is_pro) {
			unset($data['upgrades']);
			if (isset($data['bundle_discount']) && is_array($data['bundle_discount'])) {
				$data['bundle_discount']['enabled'] = false;
			}
			unset($data['tiers']);
			unset($data['tiers_repeat_scale']);
		}

		NudgeSells_Rules_Repository::save_offer_rules($offer_id, $data);

		NudgeSells_Offer_Repository::flush_cache();
	}

	/**
	 * Duplicate offer.
	 *
	 * @return void
	 * @since 1.0.0
	 */
	public function duplicate_offer()
	{
		$offer_id = isset($_GET['offer_id']) ? absint($_GET['offer_id']) : 0;

		if (! $offer_id || ! current_user_can('edit_post', $offer_id)) {
			wp_die(esc_html__('You do not have permission to do this.', 'nudgesells'));
		}
		check_admin_referer('nudgesells_duplicate_offer_' . $offer_id);

		$source = get_post($offer_id);
		if (! $source || NudgeSells_CPT::POST_TYPE !== $source->post_type) {
			wp_die(esc_html__('That offer no longer exists.', 'nudgesells'));
		}

		$new_id = wp_insert_post(array(
			'post_type'   => NudgeSells_CPT::POST_TYPE,
			/* translators: %s: original offer's title */
			'post_title'  => sprintf(__('%s (copy)', 'nudgesells'), $source->post_title),
			'post_status' => 'draft',
		), true);

		if (is_wp_error($new_id) || ! $new_id) {
			wp_die(esc_html__('Could not duplicate that offer. Please try again.', 'nudgesells'));
		}

		foreach (get_post_meta($offer_id) as $key => $values) {
			if (0 !== strpos($key, '_nudgesells_')) {
				continue;
			}

			$value = maybe_unserialize($values[0]);
			update_post_meta($new_id, $key, $value);
		}

		if (! NudgeSells_Pro_Loader::is_active()) {
			delete_post_meta($new_id, '_nudgesells_upgrades');
			delete_post_meta($new_id, '_nudgesells_tiers');
			delete_post_meta($new_id, '_nudgesells_tiers_repeat_scale');
			$bundle = get_post_meta($new_id, '_nudgesells_bundle_discount', true);
			if (is_array($bundle)) {
				$bundle['enabled'] = false;
				update_post_meta($new_id, '_nudgesells_bundle_discount', $bundle);
			}
		}

		NudgeSells_Offer_Repository::flush_cache();

		wp_safe_redirect(admin_url('post.php?post=' . $new_id . '&action=edit&nudgesells_duplicated=1'));
		exit;
	}

	/**
	 * Duplicated notice.
	 *
	 * @return void
	 * @since 1.0.0
	 */
	public function duplicated_notice()
	{
		$screen = get_current_screen();
		if (! $screen || NudgeSells_CPT::POST_TYPE !== $screen->post_type || empty($_GET['nudgesells_duplicated'])) {
			return;
		}
	?>
		<div class="notice notice-success is-dismissible">
			<p><?php esc_html_e('Offer duplicated. This copy is a Draft - review it and publish when ready.', 'nudgesells'); ?></p>
		</div>
<?php
	}
}
