
/**
 * Scheduled Order Data Container
 */
if ( typeof window.autoshipSchedulerData === 'undefined' )
window.autoshipSchedulerData = {

  // Activate & Deactivate Handler
  activationHandler : undefined, // Pluggable Function

  // Main Add Item Handler
  addItemHandler : undefined, // Pluggable Function

  // Main Delete Item Handler ( Ajax - not currently used )
  deleteItemHandler : undefined, // Pluggable Function

  // Cancel Action Handler
  cancelAction : undefined, // Pluggable Function

  // Add Item Success & Failure functions
  addItemSuccessCallback : undefined, // Pluggable Function
  addItemFailureCallback : undefined, // Pluggable Function

  // Currently Not Used
  removeItemSuccessCallback : undefined, // Pluggable Function
  removeItemFailureCallback : undefined, // Pluggable Function

  // Shipping Address Country Change Handler
  refreshCountryShipping : undefined, // Pluggable Function

  // Shipping Label Change Handler
  refreshShippingLabels : undefined, // Pluggable Function

  // Shipping Form
  shippingAddressFormClass : '.autoship-edit-scheduled-order-shipping-address-form',

  // Shipping Country
  shippingCountryFieldIdentifier : '#country',

  // Shipping State
  shippingStateFieldIdentifier : '#state',

  // Shipping field map
  shippingFieldsPrefix : 'shipping_',
  shippingFieldsLabelRequired : '<abbr class="required" title="required">*</abbr>',

};

jQuery(function ($) {

  var autoship_schdule_added_items = {};

  /**
   * Activate / Deactivate Action Handler.
   */
  var activationHandler = function(e){

    // Check for a custom override function
    if ( typeof window.autoshipSchedulerData.activationHandler !== 'undefined' ){
      var func = window.autoshipSchedulerData.activationHandler;
      return window[func](e);
    }

    e.preventDefault();

    var target = $(this).attr('data-target');
    var toggle_text = $(this).attr('data-toggle-text');
    $(this).attr('data-toggle-text', $(this).html() ).html(toggle_text);
    $( target ).toggleClass('activated');

  }

	/**
	 * Check if a node is blocked for processing.
	 *
	 * @param {JQuery Object} $node
	 * @return {bool} True if the DOM Element is UI Blocked, false if not.
	 */
	var is_locked = function( $node ) {
		return $node.is( '.processing' ) || $node.parents( '.processing' ).length;
	};

	/**
	 * Block a node visually for processing.
	 *
	 * @param {JQuery Object} $node
	 */
	var lock = function( $node ) {
		if ( ! is_locked( $node ) ) {
			$node.addClass( 'processing' );
		}
	};

	/**
	 * Unblock a node after processing is complete.
	 *
	 * @param {JQuery Object} $node
	 */
	var unlock = function( $node ) {
		$node.removeClass( 'processing' );
	};

	/**
	 * Unblock a node after processing is complete.
	 */
  var hide_totals = function(){

    var target_totals = $(".autoship-order-totals");

    if ( target_totals.length )
    target_totals.find('td').fadeOut();
  }

	/**
	 * Unblock a node after processing is complete.
	 */
  var show_totals = function(){

    var target_totals = $(".autoship-order-totals");

    if ( target_totals.length )
    target_totals.find('td').opacity(0);

  }

  /**
   * Check if the form is locked
   */
  var chck_locked = function(e){
    var target_form = $( this ).closest('form');
    if ( is_locked( target_form ) ){
      e.preventDefault();
      return false;
    }
  }

  /**
   * Callback for when an item is added successfully
   */
  var addItemSuccess = function( itemAction ){

    // Check for a custom override function
    if ( typeof window.autoshipSchedulerData.addItemSuccessCallback !== 'undefined' ){
      var func = window.autoshipSchedulerData.addItemSuccessCallback;
      return window[func]( itemAction );
    }

    itemAction.target_placeholder.fadeOut('400', function() {
      $(itemAction.response.content).insertBefore('.scheduled-order-add-ons');
      itemAction.target_option.prop("selected", false).attr('disabled','disabled');
      $('.autoship-msg').remove();
      $(itemAction.response.notice_target).prepend( $( itemAction.response.notice ) ).css({ opacity: 0, display: 'table-cell' }).animate({ opacity: 1 }, 400);
      hide_totals();
      itemAction.target_form.removeClass('empty-order');
      unlock( $(itemAction.target_form) );
    });

    return;

  }

  /**
   * Callback for when an item is added unsuccessfully
   */
  var addItemFailure = function( itemAction ){

    // Check for a custom override function
    if ( typeof window.autoshipSchedulerData.addItemFailureCallback !== 'undefined' ){
      var func = window.autoshipSchedulerData.addItemFailureCallback;
      return window[func]( itemAction );
    }

    itemAction.target_placeholder.fadeOut('400', function() {
      $(itemAction.response.content).insertBefore('.scheduled-order-add-ons');
      itemAction.target_option.prop("selected", false).attr('disabled','disabled');
      $('.autoship-msg').remove();
      $(itemAction.response.notice_target).prepend( $( itemAction.response.notice ) ).css({ opacity: 0, display: 'table-cell' }).animate({ opacity: 1 }, 400);
      hide_totals();
    });

    return;

  }

  /**
   * Main Handler for Adding an Item
   */
  var addItemHandler = function(e){

    // Check for a custom override function
    if ( typeof window.autoshipSchedulerData.addItemHandler !== 'undefined' ){
      var func = window.autoshipSchedulerData.addItemHandler;
      return window[func](e);
    }

    e.preventDefault();

    var itemAction = {};
        itemAction.target              = $('#autoship_add_scheduled_order_item');
        itemAction.target_option       = $("#autoship_add_scheduled_order_item option:selected");
        itemAction.target_placeholder  = $(".scheduled-order-add-ons-placeholder");
        itemAction.target_val          = itemAction.target_option.val();
        itemAction.target_form         = $( this ).closest('form');

    if ( is_locked( itemAction.target_form ) )
    return false;

    if ( typeof itemAction.target_val !== 'undefined' && itemAction.target_val.length ){

      // Clear any lingering WC Notices.
			$( '.woocommerce-error, .woocommerce-message, .woocommerce-info' ).remove();

      // Lock the form to prevent other form actions.
      lock( itemAction.target_form );

      // Bring in the item placeholder
      itemAction.target_placeholder.fadeIn();

      $.ajax({
        type: 'POST',
        dataType: 'json',
        url: AUTOSHIP_AJAX_URL,
        data: {
            action: "autoship_get_add_item_html",
            product_id: itemAction.target_val,
            metadata: autoshipSchedulerData
        },
        success: function(response) {

          itemAction.response = response;
          addItemSuccess( itemAction );

        },
        failure: function(response) {

          itemAction.response = response;
          addItemFailure( itemAction );

        }
      });
    }

  };

  /**
   * Main Handler for Deleting an Item
   */
  var deleteItemHandler = function(e){

    // Check for a custom override function
    if ( typeof window.autoshipSchedulerData.deleteItemHandler !== 'undefined' ){
      var func = window.autoshipSchedulerData.deleteItemHandler;
      return window[func](e);
    }

    e.preventDefault();

    var itemAction = {};
        itemAction.target         = $(this).attr('data-autoship-order'),
        itemAction.target_action  = $(this).attr('data-autoship-action'),
        itemAction.target_view    = $(this).attr('data-autoship-view');
        itemAction.target_form         = $( this ).closest('form');

    if ( is_locked( itemAction.target_form ) )
    return false;

    if ( typeof itemAction.target !== 'undefined' && itemAction.target ){

      $.ajax({
        type: 'POST',
        dataType: 'json',
        url: AUTOSHIP_AJAX_URL,
        data: {
            action: "autoship_" + itemAction.target_action + "_ajax_action",
            order_id: itemAction.target,
            order_view: itemAction.target_view
        },
        success: function(response) {
          $( response.notice ).insertAfter( $( response.notice_target )).fadeIn();

        },
        failure: function(response) {
          $( response.notice ).insertAfter( $( response.notice_target )).fadeIn();
        }
      });

    }

  }

  /**
   * Main Handler for Removing Newly Added Items
   */
  var removeNewItemHandler = function(e){

    // Check for a custom override function
    if ( typeof window.autoshipSchedulerData.removeNewItemHandler !== 'undefined' ){
      var func = window.autoshipSchedulerData.removeNewItemHandler;
      return window[func](e);
    }

    e.preventDefault();

    var target = $(this).attr('data-scheduled-order-item-id'),
        select = $('#autoship_add_scheduled_order_item'),
        option = $('#autoship_add_scheduled_order_item option[value="' + target.replace( 'item-', '' ) * 1 + '"]');
        $("#" + target ).remove();
        option.removeAttr('disabled');

  };

  /**
   * Main Handler for Canceling an Action
   */
  var cancelAction = function(e){

    // Check for a custom override function
    if ( typeof window.autoshipSchedulerData.cancelAction !== 'undefined' ){
      var func = window.autoshipSchedulerData.cancelAction;
      return window[func](e);
    }

    e.preventDefault();
    var wrapper = $(this).closest( $(this).attr('data-notice-wrapper') );

    if ( wrapper )
    wrapper.fadeOut('400', function() { $(this).remove(); });

  }

  /**
   * Callback for when the country drop down is changed
   */
  var refreshCountryShipping = function( e ){

    // Check for a custom override function
    if ( typeof window.autoshipSchedulerData.refreshCountryShipping !== 'undefined' ){
      var func = window.autoshipSchedulerData.refreshCountryShipping;
      return window[func](e);
    }

    var states            = e.data.states,
        locale            = e.data.locale,
        locale_fields     = e.data.locale_fields;
        select_state_text = e.data.select_state_text;

    var $countrySelect    = $( e.target ),
        country           = $countrySelect.val(),
        $form             = $countrySelect.closest( 'form' ),

        // Get the current State Fields value and attributes
  			$statefield       = $form.find( window.autoshipSchedulerData.shippingStateFieldIdentifier ),
  			$statefieldparent = $statefield.closest( '.form-row' ),
  			iname             = $statefield.attr( 'name' ),
  			iid               = $statefield.attr( 'id' ),
  			iclasses          = $statefield.attr( 'data-input-class' ) || '',
  			ivalue            = $statefield.val(),
  			iplaceholder      = $statefield.attr( 'placeholder' ) || $statefield.attr( 'data-placeholder' ) || '',
  			$newstatefield;

    var thislocale = locale['default'];

    // Check if the country is in our country list
    // if not default it
		if ( typeof locale[ country ] !== 'undefined' )
		thislocale = locale[ country ];

    // Check if country is in our states obj
		if ( states[ country ] ) {

      // Check if the country is in our state obj but an empty ojbect
      if ( $.isEmptyObject( states[ country ] ) ) {

        // Create a new hidden State Field for Countries with invalid objects
				$newstatefield = $( '<input type="hidden" />' )
					.prop( 'id', iid )
					.prop( 'name', iname )
					.prop( 'placeholder', iplaceholder )
					.attr( 'data-input-classes', iclasses )
					.addClass( 'hidden ' + iclasses );
				$statefieldparent.hide();
				$statefield.replaceWith( $newstatefield );

      // Else our counrty has states
			} else {

        // Get the country's states
        var avail_states   = states[ country ],
					  $defaultOption = $( '<option value=""></option>' ).text( select_state_text );

        // If there isn't a placeholder use the default
				if ( ! iplaceholder )
				iplaceholder = select_state_text;

        // If the state field is currently an input we need
        // to update it to a select field
				if ( $statefield.is( 'input' ) ) {

          $newstatefield = $( '<select></select>' )
						.prop( 'id', iid )
						.prop( 'name', iname )
						.data( 'placeholder', iplaceholder )
						.attr( 'data-input-classes', iclasses )
						.addClass( 'state_select ' + iclasses );

					$statefield.replaceWith( $newstatefield );
					$statefield = $form.find( window.autoshipSchedulerData.shippingStateFieldIdentifier );

        }

        // Add the default select option
				$statefield.empty().append( $defaultOption );

        // Add each of the states as an option
				$.each( avail_states, function( index ) {
					var $option = $( '<option></option>' )
						.prop( 'value', index )
						.text( avail_states[ index ] );
					$statefield.append( $option );
				} );

        // Show the state select field
				$statefieldparent.show();

        // Select the option and trigger a change
				$statefield.val( ivalue ).trigger( 'change' );

			}

    // Else the country isn't in our state obj
    // so let's convert it to a text field
		} else {

			if ( $statefield.is( 'select, input[type="hidden"]' ) ) {

      	$newstatefield = $( '<input type="text" />' )
					.prop( 'id', iid )
					.prop( 'name', iname )
					.prop('placeholder', iplaceholder)
					.attr('data-input-classes', iclasses )
					.addClass( 'input-text  ' + iclasses );

				$statefieldparent.show();
				$statefield.replaceWith( $newstatefield );

      }

		}

    // itterate through the shipping fields and adjust labels
		$.each( locale_fields, function( key, name ) {

      // We adjust the field name to match our form i.e. first_name ( ours ) vs shipping_first_name ( wc )
      var adjname = name.replace( window.autoshipSchedulerData.shippingFieldsPrefix , '' );

      // Grab the current field on the form & default any missing adjustments
      var $curField       = shippingAddressForm.find( adjname ),
          $label          = $curField.find( 'label' ),
          fieldLocale     = $.extend( true, {}, locale['default'][ key ], thislocale[ key ] );

      // Check for a label adjustment
      refreshShippingLabels( $curField, fieldLocale.label, typeof fieldLocale.required === 'undefined' ? false : fieldLocale.required );

    });

  }

  /**
   * Callback for refreshing the shipping address labels
   */
  var refreshShippingLabels = function( $curField, label, required ){

    if ( typeof required === 'undefined' )
    required = false;

    // Check for a custom override function
    if ( typeof window.autoshipSchedulerData.refreshShippingLabels !== 'undefined' ){
      var func = window.autoshipSchedulerData.refreshShippingLabels;
      return window[func]( $curField, label, required = false );
    }

    // get the current fields label
    if ( typeof $curField.find( 'label' ) !== 'undefined' && typeof label !== 'undefined' )
    $curField.find( 'label' ).html( required ? label + window.autoshipSchedulerData.shippingFieldsLabelRequired : label );

  }

  // wc_country_select_params is required to continue, ensure the object exists
	if ( typeof wc_country_select_params !== 'undefined' &&
       typeof wc_address_i18n_params !== 'undefined' ) {

    // Find the Shipping Country drop down to monitor
    var shippingAddressForm = $( window.autoshipSchedulerData.shippingAddressFormClass ),
        shippingCountry     = shippingAddressForm.find( window.autoshipSchedulerData.shippingCountryFieldIdentifier );

    // Remove the WC Classes to prevent the WC Handler from firing
    shippingCountry.removeClass('country_to_state');

    /**
    * When the Country drop down is changed update the shipping fields
    */
    shippingCountry.on( 'change refresh',
    {
      states            : JSON.parse( wc_country_select_params.countries.replace( /&quot;/g, '"' ) ),
      locale            : JSON.parse( wc_address_i18n_params.locale.replace( /&quot;/g, '"' ) ),
      locale_fields     : JSON.parse( wc_address_i18n_params.locale_fields ),
      select_state_text : wc_country_select_params.i18n_select_state_text
    }, refreshCountryShipping );

	}

  // Init all dismissible features
  var dismissibles = $(document).find('.autoship-tips' );

  // itterate through the dismissibles and show/hide accordingly
  $.each( dismissibles, function( key, name ) {

    var cookieName = $( this ).attr('data-feature-id');

  	if ( typeof Cookies !== 'undefined' && 'hidden' === Cookies.get( cookieName ) ) {
  		$( this ).hide();
  	} else {
  		$( this ).show();
  	}

  });

  var dismissibleHandler = function(e){

    if ( typeof Cookies === 'undefined' )
    return;

    var cookieName = $( this ).attr('data-feature-id');
		Cookies.set( cookieName, 'hidden', { path: '/' } );
		$( this ).hide();

  }

  $(document).on( 'click', dismissibles, dismissibleHandler );

  // Init all Tooltips
  $(document).find('.autoship-tips' ).tipTip( {
		'attribute': 'data-tip',
		'fadeIn': 50,
		'fadeOut': 50,
		'delay': 200
	} );

  // Hooked Event Handlers
  $(document).on( 'click', '.activate-action, .deactivate-action', activationHandler );
  $(document).on( 'click', 'form a,form button', chck_locked );
  $(document).on( 'click', '.add-item-action', addItemHandler );
  $(document).on( 'click', '.remove-new-item-action', removeNewItemHandler );
  $(document).on( 'click', 'a[data-autoship-action="Deleted"]', deleteItemHandler );
  $(document).on( 'click', 'a.cancel-action', cancelAction );

});

/**
* Adjusts the Size of the Scheduled Orders iframe
*/
document.addEventListener("DOMContentLoaded", function () {
  // Check if the iframe exists and only if it does run the interval
  var iframes = document.getElementsByClassName("autoship-scheduled-orders-iframe");
  if ( iframes !== undefined && iframes.length )
  setInterval(function () {
      if (iframes.length > 0) {
          Array.from(iframes).forEach(function (scheduledOrder) {
              var bodyHeight = '';
              try {
                  bodyHeight = Math.max(500, scheduledOrder.contentWindow.document.body.scrollHeight) + 'px';
              } catch (e) {
                  bodyHeight = '100vh';
              }
              if (bodyHeight != scheduledOrder.style.height) {
                  scheduledOrder.style.height = bodyHeight;
              }
          });
      }
  }, 500);
});

/**
* Custom Implementation of the from function for support in Edge/IE
*/
if (!Array.from) {
  Array.from = (function () {
    var toStr = Object.prototype.toString;
    var isCallable = function (fn) {
      return typeof fn === 'function' || toStr.call(fn) === '[object Function]';
    };
    var toInteger = function (value) {
      var number = Number(value);
      if (isNaN(number)) { return 0; }
      if (number === 0 || !isFinite(number)) { return number; }
      return (number > 0 ? 1 : -1) * Math.floor(Math.abs(number));
    };
    var maxSafeInteger = Math.pow(2, 53) - 1;
    var toLength = function (value) {
      var len = toInteger(value);
      return Math.min(Math.max(len, 0), maxSafeInteger);
    };

    // The length property of the from method is 1.
    return function from(arrayLike/*, mapFn, thisArg */) {
      // 1. Let C be the this value.
      var C = this;

      // 2. Let items be ToObject(arrayLike).
      var items = Object(arrayLike);

      // 3. ReturnIfAbrupt(items).
      if (arrayLike == null) {
        throw new TypeError("Array.from requires an array-like object - not null or undefined");
      }

      // 4. If mapfn is undefined, then let mapping be false.
      var mapFn = arguments.length > 1 ? arguments[1] : void undefined;
      var T;
      if (typeof mapFn !== 'undefined') {
        // 5. else
        // 5. a If IsCallable(mapfn) is false, throw a TypeError exception.
        if (!isCallable(mapFn)) {
          throw new TypeError('Array.from: when provided, the second argument must be a function');
        }

        // 5. b. If thisArg was supplied, let T be thisArg; else let T be undefined.
        if (arguments.length > 2) {
          T = arguments[2];
        }
      }

      // 10. Let lenValue be Get(items, "length").
      // 11. Let len be ToLength(lenValue).
      var len = toLength(items.length);

      // 13. If IsConstructor(C) is true, then
      // 13. a. Let A be the result of calling the [[Construct]] internal method of C with an argument list containing the single item len.
      // 14. a. Else, Let A be ArrayCreate(len).
      var A = isCallable(C) ? Object(new C(len)) : new Array(len);

      // 16. Let k be 0.
      var k = 0;
      // 17. Repeat, while k < len… (also steps a - h)
      var kValue;
      while (k < len) {
        kValue = items[k];
        if (mapFn) {
          A[k] = typeof T === 'undefined' ? mapFn(kValue, k) : mapFn.call(T, kValue, k);
        } else {
          A[k] = kValue;
        }
        k += 1;
      }
      // 18. Let putStatus be Put(A, "length", len, true).
      A.length = len;
      // 20. Return A.
      return A;
    };
  }());
}

/**
 * Snooze Form Handling
 *
 * Manages the inline snooze form: toggling visibility, calculating
 * resume dates, submitting snooze/cancel-snooze AJAX requests, and
 * updating the UI on success or failure.
 */
jQuery(function ($) {

  /**
   * Get snooze config, or null if not available.
   */
  function getSnoozeConfig() {
    return typeof window.autoshipSnooze !== 'undefined' ? window.autoshipSnooze : null;
  }

  /**
   * Pull the user-facing message out of a snooze AJAX response, whether
   * the server replied with {success:false, data:{message}} on a 200 or
   * with the same payload on a 4xx/5xx that jQuery routes to the error
   * callback. Falls back to the generic label when the body is empty.
   */
  function getSnoozeErrorMessage(responseOrXhr, fallback) {
    if (!responseOrXhr) {
      return fallback;
    }
    // Success-callback path: {success:false, data:{message:...}}.
    if (responseOrXhr.data && responseOrXhr.data.message) {
      return responseOrXhr.data.message;
    }
    // Error-callback path: jqXHR.responseJSON.data.message.
    if (responseOrXhr.responseJSON && responseOrXhr.responseJSON.data && responseOrXhr.responseJSON.data.message) {
      return responseOrXhr.responseJSON.data.message;
    }
    return fallback;
  }

  /**
   * Calculate the resume date from duration and type.
   */
  function calculateResumeDate(duration, durationType) {
    var date = new Date();
    duration = parseInt(duration, 10);

    switch (durationType) {
      case 'Days':
        date.setDate(date.getDate() + duration);
        break;
      case 'Weeks':
        date.setDate(date.getDate() + (duration * 7));
        break;
      case 'Months':
        date.setMonth(date.getMonth() + duration);
        break;
    }

    return date;
  }

  /**
   * Format a date for display.
   */
  function formatDate(date) {
    var options = { year: 'numeric', month: 'long', day: 'numeric' };
    return date.toLocaleDateString(undefined, options);
  }

  /**
   * Update the resume date preview for a given order.
   */
  function updateResumeDate(orderId) {
    var config = getSnoozeConfig();
    var $select = $('#autoship-snooze-duration-' + orderId);
    var $resumeDate = $('#autoship-snooze-resume-date-' + orderId);
    var $customDateWrap = $('#autoship-snooze-custom-date-' + orderId);
    var $customDateInput = $('#autoship-snooze-custom-date-input-' + orderId);

    if (!$select.length || !$select.val()) {
      $resumeDate.hide();
      $customDateWrap.hide();
      return;
    }

    var value = $select.val();
    var durationType = $select.find(':selected').data('duration-type');

    // Custom date selection: show date picker, hide preview until a date is chosen.
    if ('custom' === value || 'Custom' === durationType) {
      $customDateWrap.show();

      var customDate = $customDateInput.val();
      if (customDate) {
        var date = new Date(customDate + 'T00:00:00');
        var label = config && config.i18n ? config.i18n.resumeOn : 'Your order will resume on %s';
        $resumeDate.text(label.replace('%s', formatDate(date))).show();
      } else {
        $resumeDate.hide();
      }
      return;
    }

    // Preset duration selection.
    $customDateWrap.hide();
    var presetDate = calculateResumeDate(value, durationType);
    var presetLabel = config && config.i18n ? config.i18n.resumeOn : 'Your order will resume on %s';
    $resumeDate.text(presetLabel.replace('%s', formatDate(presetDate))).show();
  }

  /**
   * Toggle the snooze form row visibility.
   */
  $(document).on('click', 'a[data-autoship-action="Snooze"]', function (e) {
    e.preventDefault();

    var orderId = $(this).data('autoship-order');
    var $row = $('#autoship-snooze-row-' + orderId);

    // Hide any other open snooze forms and any resume-early panels.
    $('.autoship-snooze-form-row').not($row).hide();
    $('.autoship-resume-early-panel-row').hide();

    // Toggle this one.
    $row.toggle();

    // If now visible, update the resume date.
    if ($row.is(':visible')) {
      updateResumeDate(orderId);
    }
  });

  /**
   * Update resume date when duration selection changes.
   */
  $(document).on('change', '.autoship-snooze-duration-select', function () {
    var orderId = $(this).closest('.autoship-snooze-form').data('order-id');
    // Clear any previous validation error on selection change.
    $('#autoship-snooze-message-' + orderId).hide().removeClass('error').text('');
    updateResumeDate(orderId);
  });

  /**
   * Update resume date when the custom date input changes.
   */
  $(document).on('change input', '.autoship-snooze-custom-date-input', function () {
    var orderId = $(this).closest('.autoship-snooze-form').data('order-id');
    $('#autoship-snooze-message-' + orderId).hide().removeClass('error').text('');
    updateResumeDate(orderId);
  });

  /**
   * Cancel (close) the snooze form.
   */
  $(document).on('click', '.autoship-snooze-cancel', function () {
    var orderId = $(this).data('order-id');
    $('#autoship-snooze-row-' + orderId).hide();
    $('#autoship-snooze-message-' + orderId).hide().text('');
  });

  /**
   * Confirm snooze submission.
   */
  $(document).on('click', '.autoship-snooze-confirm', function () {
    var config = getSnoozeConfig();
    if (!config) { return; }

    var orderId = $(this).data('order-id');
    var $form = $('#autoship-snooze-form-' + orderId);
    var $select = $('#autoship-snooze-duration-' + orderId);
    var $message = $('#autoship-snooze-message-' + orderId);
    var $button = $(this);
    var errorLabel = config.i18n.error || 'An error occurred. Please try again.';
    var selectDurationMsg = config.i18n.selectDuration || 'Please select a snooze duration before confirming.';
    var selectCustomDateMsg = config.i18n.selectCustomDate || 'Please select a resume date before confirming.';
    var customDateInPastMsg = config.i18n.customDateInPast || 'The selected date must be in the future.';

    // Validate: a duration option must be selected.
    if (!$select.length || !$select.val()) {
      $message.text(selectDurationMsg).addClass('error').show();
      return;
    }

    var value = $select.val();
    var durationType = $select.find(':selected').data('duration-type');
    var ajaxData = {
      action: 'autoship_snooze_order',
      nonce: config.nonce,
      order_id: orderId
    };

    if ('custom' === value || 'Custom' === durationType) {
      // Custom date flow.
      var $customDateInput = $('#autoship-snooze-custom-date-input-' + orderId);
      var customDate = $customDateInput.val();

      if (!customDate) {
        $message.text(selectCustomDateMsg).addClass('error').show();
        return;
      }

      var picked = new Date(customDate + 'T00:00:00');
      var today = new Date();
      today.setHours(0, 0, 0, 0);

      if (picked <= today) {
        $message.text(customDateInPastMsg).addClass('error').show();
        return;
      }

      ajaxData.custom_date = customDate;
      ajaxData.duration_type = 'Custom';
    } else {
      // Preset duration flow.
      ajaxData.duration = value;
      ajaxData.duration_type = durationType;
    }

    // The form is rendered server-side with the order's snoozed state.
    // This works on both the list page (table row) and the detail page (div),
    // unlike DOM-scraping the status element which only exists on the list.
    var isSnoozed = $form.data('is-snoozed') === true || $form.data('is-snoozed') === 'true';
    ajaxData.is_snoozed = isSnoozed ? 'true' : 'false';

    // Disable button and show processing.
    var originalText = $button.text();
    $button.prop('disabled', true).text(config.i18n.processing || 'Processing...');
    $message.hide().removeClass('error').text('');

    $.ajax({
      url: config.ajaxUrl,
      type: 'POST',
      data: ajaxData,
      success: function (response) {
        if (response.success) {
          window.location.reload();
        } else {
          $message.text(getSnoozeErrorMessage(response, errorLabel)).addClass('error').show();
          $button.prop('disabled', false).text(originalText);
        }
      },
      error: function (jqXHR) {
        $message.text(getSnoozeErrorMessage(jqXHR, errorLabel)).addClass('error').show();
        $button.prop('disabled', false).text(originalText);
      }
    });
  });

  /**
   * Handle "Resume Now" for snoozed orders.
   */
  /**
   * Toggle the Resume Early confirmation panel when the action is clicked.
   *
   * Replaces the old browser confirm() dialog with an inline panel that
   * explains the consequence of resuming early. The actual API call is
   * triggered by the panel's "Yes, Resume Now" button.
   */
  $(document).on('click', 'a[data-autoship-action="ResumeSnooze"]', function (e) {
    e.preventDefault();

    var orderId = $(this).data('autoship-order');
    var $row = $('#autoship-resume-early-row-' + orderId);

    // Hide any other open panels (snooze form + other resume-early panels).
    $('.autoship-snooze-form-row').hide();
    $('.autoship-resume-early-panel-row').not($row).hide();

    $row.toggle();
  });

  /**
   * "Keep Snoozed" — close the Resume Early panel without changing state.
   */
  $(document).on('click', '.autoship-resume-early-cancel', function () {
    var orderId = $(this).data('order-id');
    $('#autoship-resume-early-row-' + orderId).hide();
    $('#autoship-resume-early-message-' + orderId).hide().removeClass('error').text('');
  });

  /**
   * "Yes, Resume Now" — confirm the resume-early action and call the API.
   */
  $(document).on('click', '.autoship-resume-early-confirm', function () {
    var config = getSnoozeConfig();
    if (!config) { return; }

    var orderId = $(this).data('order-id');
    var $button = $(this);
    var $message = $('#autoship-resume-early-message-' + orderId);
    var errorLabel = config.i18n.error || 'An error occurred. Please try again.';
    var originalText = $button.text();

    $button.prop('disabled', true).text(config.i18n.processing || 'Processing...');
    $message.hide().removeClass('error').text('');

    $.ajax({
      url: config.ajaxUrl,
      type: 'POST',
      data: {
        action: 'autoship_cancel_snooze',
        nonce: config.nonce,
        order_id: orderId
      },
      success: function (response) {
        if (response.success) {
          window.location.reload();
        } else {
          $message.text(getSnoozeErrorMessage(response, errorLabel)).addClass('error').show();
          $button.prop('disabled', false).text(originalText);
        }
      },
      error: function (jqXHR) {
        $message.text(getSnoozeErrorMessage(jqXHR, errorLabel)).addClass('error').show();
        $button.prop('disabled', false).text(originalText);
      }
    });
  });
});
