/**
 * Lucrativeit Subscription Plus — admin app scripts.
 */
( function ( $ ) {
	'use strict';

	$( function () {
		// Filter toolbars: submit on select change (no inline onchange).
		$( document ).on( 'change', 'select.lucrsure-auto-submit', function () {
			if ( this.form ) {
				this.form.submit();
			}
		} );

		// Destructive forms: confirm before submit (no inline onsubmit).
		$( document ).on( 'submit', 'form.lucrsure-confirm-submit', function ( e ) {
			var message = $( this ).attr( 'data-lucrsure-confirm' ) || '';
			if ( message && ! window.confirm( message ) ) {
				e.preventDefault();
			}
		} );

		// Reports chart bars: height from data attribute (no inline style).
		$( '.lucrsure-chart-bar[data-lucrsure-height]' ).each( function () {
			var height = parseInt( $( this ).attr( 'data-lucrsure-height' ), 10 );
			if ( height > 0 ) {
				this.style.setProperty( '--lucrsure-chart-bar-height', height + 'px' );
			}
		} );

		// Subscription form: show the relevant payment behaviour note.
		var $gateway = $( '#lucrsure-gateway-select' );

		function toggleGatewayNote() {
			var auto = $gateway.find( 'option:selected' ).data( 'auto' ) === 1 ||
				$gateway.find( 'option:selected' ).data( 'auto' ) === '1';
			$( '.lucrsure-gateway-note-auto' ).toggle( !! auto );
			$( '.lucrsure-gateway-note-invoice' ).toggle( ! auto );
		}

		if ( $gateway.length ) {
			toggleGatewayNote();
			$gateway.on( 'change', toggleGatewayNote );
		}

		// Engine choice: highlight selected card.
		$( '.lucrsure-engine-option input' ).on( 'change', function () {
			$( '.lucrsure-engine-option' ).removeClass( 'is-selected' );
			$( this ).closest( '.lucrsure-engine-option' ).addClass( 'is-selected' );
		} );

		// Auto-generate slug from name on create forms.
		$( 'input[name="name"]' ).on( 'blur', function () {
			var $slug = $( 'input[name="slug"]' );
			if ( $slug.length && '' === $slug.val() ) {
				$slug.val(
					$( this ).val().toLowerCase().replace( /[^a-z0-9]+/g, '-' ).replace( /^-|-$/g, '' )
				);
			}
		} );

		// New subscription 3-step wizard.
		var $wizard = $( '#lucrsure-subscription-wizard' );
		if ( $wizard.length ) {
			var currentStep = 1;
			var $planInput = $( '#lucrsure-wizard-plan' );
			var $customerInput = $( '#lucrsure-wizard-customer' );
			var selectedPlan = { name: '', price: '' };
			var selectedCustomer = { name: '', email: '' };

			function goToStep( step ) {
				currentStep = step;
				$wizard.find( '.lucrsure-wizard-step' ).each( function () {
					var s = parseInt( $( this ).data( 'step' ), 10 );
					$( this ).toggleClass( 'is-active', s === step );
					$( this ).toggleClass( 'is-done', s < step );
				} );
				$wizard.find( '.lucrsure-wizard-panel' ).each( function () {
					var s = parseInt( $( this ).data( 'step' ), 10 );
					var active = s === step;
					$( this ).toggleClass( 'is-active', active );
					$( this ).prop( 'hidden', ! active );
				} );
				if ( 3 === step ) {
					updateSummary();
				}
			}

			function updateSummary() {
				var planText = selectedPlan.name
					? selectedPlan.name + ' — ' + selectedPlan.price
					: '—';
				var customerText = selectedCustomer.name
					? selectedCustomer.name + ' (' + selectedCustomer.email + ')'
					: '—';
				$( '#lucrsure-summary-plan' ).text( planText );
				$( '#lucrsure-summary-customer' ).text( customerText );
			}

			$wizard.on( 'click', '.lucrsure-select-card[data-type="plan"]', function () {
				var $card = $( this );
				$wizard.find( '.lucrsure-select-card[data-type="plan"]' ).removeClass( 'is-selected' );
				$card.addClass( 'is-selected' );
				$planInput.val( $card.data( 'id' ) );
				selectedPlan = {
					name: $card.data( 'name' ),
					price: $card.data( 'price' )
				};
				$wizard.find( '.lucrsure-wizard-panel[data-step="1"] .lucrsure-wizard-next' ).prop( 'disabled', false );
			} );

			$wizard.on( 'click', '.lucrsure-select-card[data-type="customer"]', function () {
				var $card = $( this );
				$wizard.find( '.lucrsure-select-card[data-type="customer"]' ).removeClass( 'is-selected' );
				$card.addClass( 'is-selected' );
				$customerInput.val( $card.data( 'id' ) );
				selectedCustomer = {
					name: $card.data( 'name' ),
					email: $card.data( 'email' )
				};
				$wizard.find( '.lucrsure-wizard-panel[data-step="2"] .lucrsure-wizard-next' ).prop( 'disabled', false );
			} );

			$wizard.on( 'click', '.lucrsure-wizard-next', function () {
				var next = parseInt( $( this ).data( 'next' ), 10 );
				if ( 2 === next && ! $planInput.val() ) {
					return;
				}
				if ( 3 === next && ! $customerInput.val() ) {
					return;
				}
				goToStep( next );
			} );

			$wizard.on( 'click', '.lucrsure-wizard-back', function () {
				goToStep( parseInt( $( this ).data( 'back' ), 10 ) );
			} );

			$( '#lucrsure-customer-search' ).on( 'input', function () {
				var q = $( this ).val().toLowerCase().trim();
				var visible = 0;
				$( '#lucrsure-customer-grid .lucrsure-customer-card' ).each( function () {
					var match = ! q || String( $( this ).data( 'search' ) ).indexOf( q ) !== -1;
					$( this ).toggle( match );
					if ( match ) {
						visible++;
					}
				} );
				$( '#lucrsure-customer-no-results' ).prop( 'hidden', visible > 0 || ! q );
			} );

			// Pre-selected plan from URL (?plan=).
			var $preselected = $wizard.find( '.lucrsure-select-card[data-type="plan"].is-selected' );
			if ( $preselected.length ) {
				selectedPlan = {
					name: $preselected.data( 'name' ),
					price: $preselected.data( 'price' )
				};
			}

			function escapeHtml( text ) {
				return String( text || '' )
					.replace( /&/g, '&amp;' )
					.replace( /</g, '&lt;' )
					.replace( />/g, '&gt;' )
					.replace( /"/g, '&quot;' );
			}

			function selectPlanCard( $card ) {
				$wizard.find( '.lucrsure-select-card[data-type="plan"]' ).removeClass( 'is-selected' );
				$card.addClass( 'is-selected' );
				$planInput.val( $card.data( 'id' ) );
				selectedPlan = {
					name: $card.data( 'name' ),
					price: $card.data( 'price' )
				};
				$wizard.find( '.lucrsure-wizard-panel[data-step="1"] .lucrsure-wizard-next' ).prop( 'disabled', false );
			}

			function selectCustomerCard( $card ) {
				$wizard.find( '.lucrsure-select-card[data-type="customer"]' ).removeClass( 'is-selected' );
				$card.addClass( 'is-selected' );
				$customerInput.val( $card.data( 'id' ) );
				selectedCustomer = {
					name: $card.data( 'name' ),
					email: $card.data( 'email' )
				};
				$wizard.find( '.lucrsure-wizard-panel[data-step="2"] .lucrsure-wizard-next' ).prop( 'disabled', false );
			}

			function buildPlanCard( plan ) {
				var desc = plan.description
					? '<p class="lucrsure-muted">' + escapeHtml( plan.description ) + '</p>'
					: '';
				var trial = plan.trial_days > 0 && plan.trial_label
					? '<p class="lucrsure-plan-trial">' + escapeHtml( plan.trial_label ) + '</p>'
					: '';
				return $(
					'<button type="button" class="lucrsure-select-card lucrsure-plan-card" data-type="plan"' +
					' data-id="' + escapeHtml( plan.id ) + '"' +
					' data-name="' + escapeHtml( plan.name ) + '"' +
					' data-price="' + escapeHtml( plan.price ) + '">' +
					'<div class="lucrsure-plan-top"><strong>' + escapeHtml( plan.name ) + '</strong>' +
					'<span class="lucrsure-select-check" aria-hidden="true">&#10003;</span></div>' +
					'<div class="lucrsure-plan-price">' + escapeHtml( plan.price ) +
					'<span>/' + escapeHtml( plan.interval ) + '</span></div>' +
					desc + trial + '</button>'
				);
			}

			function buildCustomerCard( customer ) {
				var company = customer.company
					? '<span class="lucrsure-customer-company">' + escapeHtml( customer.company ) + '</span>'
					: '';
				return $(
					'<button type="button" class="lucrsure-select-card lucrsure-customer-card" data-type="customer"' +
					' data-id="' + escapeHtml( customer.id ) + '"' +
					' data-name="' + escapeHtml( customer.name ) + '"' +
					' data-email="' + escapeHtml( customer.email ) + '"' +
					' data-search="' + escapeHtml( customer.search ) + '">' +
					'<div class="lucrsure-customer-card-top">' +
					'<span class="lucrsure-avatar lucrsure-avatar-lg">' + escapeHtml( customer.initials ) + '</span>' +
					'<span class="lucrsure-select-check" aria-hidden="true">&#10003;</span></div>' +
					'<strong>' + escapeHtml( customer.name ) + '</strong>' +
					'<span class="lucrsure-muted">' + escapeHtml( customer.email ) + '</span>' +
					company +
					'<span class="lucrsure-pill lucrsure-status-' + escapeHtml( customer.status ) + '">' +
					escapeHtml( customer.status ) + '</span></button>'
				);
			}

			var $openModal = null;

			function openModal( name ) {
				$openModal = $( '#lucrsure-modal-' + name );
				if ( ! $openModal.length ) {
					return;
				}
				$openModal.prop( 'hidden', false );
				$( 'body' ).addClass( 'lucrsure-modal-open' );
				$openModal.find( '.lucrsure-modal-error' ).prop( 'hidden', true ).text( '' );
				$openModal.find( 'input[type="text"], input[type="email"], input[type="number"], textarea' ).first().trigger( 'focus' );
			}

			function closeModal() {
				if ( $openModal && $openModal.length ) {
					$openModal.prop( 'hidden', true );
					$openModal.find( 'form' )[0].reset();
				}
				$openModal = null;
				$( 'body' ).removeClass( 'lucrsure-modal-open' );
			}

			$wizard.on( 'click', '[data-open-modal]', function () {
				openModal( $( this ).data( 'open-modal' ) );
			} );

			$( document ).on( 'click', '[data-close-modal]', function () {
				closeModal();
			} );

			$( document ).on( 'keydown', function ( e ) {
				if ( 27 === e.keyCode && $openModal && $openModal.length ) {
					closeModal();
				}
			} );

			$( '#lucrsure-quick-plan-form' ).on( 'submit', function ( e ) {
				e.preventDefault();
				var $form = $( this );
				var $error = $( '#lucrsure-plan-modal-error' );
				var $submit = $form.find( 'button[type="submit"]' );

				$error.prop( 'hidden', true );
				$submit.prop( 'disabled', true );

				$.post( LUCRSURE.ajaxUrl, $form.serialize() + '&action=lucrsure_quick_create_plan&nonce=' + encodeURIComponent( LUCRSURE.nonce ) )
					.done( function ( response ) {
						if ( ! response || ! response.success ) {
							$error.text( response && response.data && response.data.message ? response.data.message : 'Error' ).prop( 'hidden', false );
							return;
						}
						var plan = response.data;
						var $card = buildPlanCard( plan );
						$card.insertBefore( '#lucrsure-plan-grid .lucrsure-add-card' );
						$( '#lucrsure-plan-empty' ).prop( 'hidden', true );
						selectPlanCard( $card );
						closeModal();
					} )
					.fail( function () {
						$error.text( 'Request failed. Please try again.' ).prop( 'hidden', false );
					} )
					.always( function () {
						$submit.prop( 'disabled', false );
					} );
			} );

			$( '#lucrsure-quick-customer-form' ).on( 'submit', function ( e ) {
				e.preventDefault();
				var $form = $( this );
				var $error = $( '#lucrsure-customer-modal-error' );
				var $submit = $form.find( 'button[type="submit"]' );

				$error.prop( 'hidden', true );
				$submit.prop( 'disabled', true );

				$.post( LUCRSURE.ajaxUrl, $form.serialize() + '&action=lucrsure_quick_create_customer&nonce=' + encodeURIComponent( LUCRSURE.nonce ) )
					.done( function ( response ) {
						if ( ! response || ! response.success ) {
							$error.text( response && response.data && response.data.message ? response.data.message : 'Error' ).prop( 'hidden', false );
							return;
						}
						var customer = response.data;
						var $card = buildCustomerCard( customer );
						$card.insertBefore( '#lucrsure-customer-grid .lucrsure-add-card' );
						$( '#lucrsure-customer-empty' ).prop( 'hidden', true );
						$( '#lucrsure-customer-search-wrap' ).prop( 'hidden', false );
						selectCustomerCard( $card );
						closeModal();
					} )
					.fail( function () {
						$error.text( 'Request failed. Please try again.' ).prop( 'hidden', false );
					} )
					.always( function () {
						$submit.prop( 'disabled', false );
					} );
			} );
		}

		// Dashboard revenue trend line chart.
		var $trendChart = $( '#lucrsure-revenue-trend-chart' );
		if ( $trendChart.length ) {
			var raw = $trendChart.attr( 'data-series' );
			var series = [];
			try {
				series = raw ? JSON.parse( raw ) : [];
			} catch ( e ) {
				series = [];
			}
			renderRevenueTrendChart( $trendChart[0], series );
		}

		function niceCeil( max ) {
			if ( max <= 0 ) {
				return 1000;
			}
			var exp = Math.pow( 10, Math.floor( Math.log10( max ) ) );
			var f = max / exp;
			var nice = f <= 1 ? 1 : f <= 2 ? 2 : f <= 5 ? 5 : 10;
			return nice * exp;
		}

		function formatTrendAxis( value ) {
			if ( value >= 1000 ) {
				return '$' + Math.round( value / 1000 ) + 'K';
			}
			return '$' + Math.round( value );
		}

		function smoothTrendPath( points ) {
			if ( ! points.length ) {
				return '';
			}
			if ( 1 === points.length ) {
				return 'M ' + points[0].x + ' ' + points[0].y;
			}
			var d = 'M ' + points[0].x + ' ' + points[0].y;
			for ( var i = 0; i < points.length - 1; i++ ) {
				var p0 = points[ i - 1 ] || points[ i ];
				var p1 = points[ i ];
				var p2 = points[ i + 1 ];
				var p3 = points[ i + 2 ] || p2;
				var cp1x = p1.x + ( p2.x - p0.x ) / 6;
				var cp1y = p1.y + ( p2.y - p0.y ) / 6;
				var cp2x = p2.x - ( p3.x - p1.x ) / 6;
				var cp2y = p2.y - ( p3.y - p1.y ) / 6;
				d += ' C ' + cp1x + ' ' + cp1y + ', ' + cp2x + ' ' + cp2y + ', ' + p2.x + ' ' + p2.y;
			}
			return d;
		}

		function renderRevenueTrendChart( el, series ) {
			var width = 640;
			var height = 260;
			var padL = 52;
			var padR = 16;
			var padT = 16;
			var padB = 32;
			var chartW = width - padL - padR;
			var chartH = height - padT - padB;
			var baseY = padT + chartH;

			var values = series.map( function ( item ) {
				return parseFloat( item.value ) || 0;
			} );
			var maxVal = Math.max.apply( null, values.concat( [ 0 ] ) );
			var yMax = niceCeil( maxVal );
			var ticks = 5;

			var points = series.map( function ( item, index ) {
				var x = padL + ( index / Math.max( 1, series.length - 1 ) ) * chartW;
				var y = padT + chartH - ( ( parseFloat( item.value ) || 0 ) / yMax ) * chartH;
				return { x: x, y: y };
			} );

			var linePath = smoothTrendPath( points );
			var areaPath = linePath;
			if ( points.length ) {
				areaPath += ' L ' + points[ points.length - 1 ].x + ' ' + baseY;
				areaPath += ' L ' + points[ 0 ].x + ' ' + baseY + ' Z';
			}

			var svg = '<svg viewBox="0 0 ' + width + ' ' + height + '" preserveAspectRatio="xMidYMid meet" xmlns="http://www.w3.org/2000/svg">';
			svg += '<defs><linearGradient id="lspTrendFill" x1="0" y1="0" x2="0" y2="1">';
			svg += '<stop offset="0%" stop-color="#e05252" stop-opacity="0.22"/>';
			svg += '<stop offset="100%" stop-color="#e05252" stop-opacity="0.02"/>';
			svg += '</linearGradient></defs>';

			for ( var t = 0; t <= ticks; t++ ) {
				var tickVal = ( yMax / ticks ) * t;
				var ty = padT + chartH - ( tickVal / yMax ) * chartH;
				svg += '<line class="lucrsure-trend-grid" x1="' + padL + '" y1="' + ty + '" x2="' + ( width - padR ) + '" y2="' + ty + '"/>';
				svg += '<text class="lucrsure-trend-axis" x="' + ( padL - 8 ) + '" y="' + ( ty + 4 ) + '" text-anchor="end">' + formatTrendAxis( tickVal ) + '</text>';
			}

			series.forEach( function ( item, index ) {
				var lx = padL + ( index / Math.max( 1, series.length - 1 ) ) * chartW;
				svg += '<text class="lucrsure-trend-axis" x="' + lx + '" y="' + ( height - 8 ) + '" text-anchor="middle">' + item.label + '</text>';
			} );

			if ( areaPath ) {
				svg += '<path class="lucrsure-trend-area" d="' + areaPath + '"/>';
			}
			if ( linePath ) {
				svg += '<path class="lucrsure-trend-line" d="' + linePath + '"/>';
			}

			el.innerHTML = svg;
		}

		// Email branding: media library logo picker.
		var $brandingForm = $( '.lucrsure-branding-form' );
		if ( $brandingForm.length && typeof wp !== 'undefined' && wp.media ) {
			var noLogoText = ( window.LUCRSURE && LUCRSURE.i18n && LUCRSURE.i18n.noLogo ) ? LUCRSURE.i18n.noLogo : 'No logo selected';

			$brandingForm.on( 'click', '.lucrsure-branding-upload', function ( e ) {
				e.preventDefault();
				var frame = wp.media( {
					title: ( LUCRSURE.i18n && LUCRSURE.i18n.selectLogo ) ? LUCRSURE.i18n.selectLogo : 'Select Logo',
					button: { text: ( LUCRSURE.i18n && LUCRSURE.i18n.useLogo ) ? LUCRSURE.i18n.useLogo : 'Use Logo' },
					multiple: false,
					library: { type: 'image' },
				} );

				frame.on( 'select', function () {
					var attachment = frame.state().get( 'selection' ).first().toJSON();
					$( '#lucrsure-branding-logo-id' ).val( attachment.id );
					$brandingForm.find( '.lucrsure-branding-logo-preview' ).html(
						'<img src="' + attachment.url + '" alt="" />'
					);
					$brandingForm.find( '.lucrsure-branding-remove' ).removeClass( 'is-hidden' );
				} );

				frame.open();
			} );

			$brandingForm.on( 'click', '.lucrsure-branding-remove', function ( e ) {
				e.preventDefault();
				$( '#lucrsure-branding-logo-id' ).val( '' );
				$brandingForm.find( '.lucrsure-branding-logo-preview' ).html(
					'<span class="lucrsure-muted">' + noLogoText + '</span>'
				);
				$( this ).addClass( 'is-hidden' );
			} );
		}

		// PDF invoice branding: media library logo picker.
		var $pdfForm = $( '.lucrsure-pdf-branding-form' );
		if ( $pdfForm.length && typeof wp !== 'undefined' && wp.media ) {
			var pdfNoLogo = ( window.LUCRSURE && LUCRSURE.i18n && LUCRSURE.i18n.noLogo ) ? LUCRSURE.i18n.noLogo : 'No logo selected';

			$pdfForm.on( 'click', '.lucrsure-pdf-branding-upload', function ( e ) {
				e.preventDefault();
				var frame = wp.media( {
					title: ( LUCRSURE.i18n && LUCRSURE.i18n.selectLogo ) ? LUCRSURE.i18n.selectLogo : 'Select Logo',
					button: { text: ( LUCRSURE.i18n && LUCRSURE.i18n.useLogo ) ? LUCRSURE.i18n.useLogo : 'Use Logo' },
					multiple: false,
					library: { type: 'image' },
				} );

				frame.on( 'select', function () {
					var attachment = frame.state().get( 'selection' ).first().toJSON();
					$( '#lucrsure-pdf-logo-id' ).val( attachment.id );
					$pdfForm.find( '.lucrsure-pdf-logo-preview' ).html(
						'<img src="' + attachment.url + '" alt="" />'
					);
					$pdfForm.find( '.lucrsure-pdf-branding-remove' ).removeClass( 'is-hidden' );
				} );

				frame.open();
			} );

			$pdfForm.on( 'click', '.lucrsure-pdf-branding-remove', function ( e ) {
				e.preventDefault();
				$( '#lucrsure-pdf-logo-id' ).val( '' );
				$pdfForm.find( '.lucrsure-pdf-logo-preview' ).html(
					'<span class="lucrsure-muted">' + pdfNoLogo + '</span>'
				);
				$( this ).addClass( 'is-hidden' );
			} );
		}

		// Plan form: media library thumbnail picker.
		var $planThumbForm = $( '.lucrsure-plan-thumbnail-form' );
		if ( $planThumbForm.length && typeof wp !== 'undefined' && wp.media ) {
			var noThumbText = ( window.LUCRSURE && LUCRSURE.i18n && LUCRSURE.i18n.noThumbnail ) ? LUCRSURE.i18n.noThumbnail : 'No thumbnail selected';

			$planThumbForm.on( 'click', '.lucrsure-plan-thumbnail-upload', function ( e ) {
				e.preventDefault();
				var frame = wp.media( {
					title: ( LUCRSURE.i18n && LUCRSURE.i18n.selectThumbnail ) ? LUCRSURE.i18n.selectThumbnail : 'Select Thumbnail',
					button: { text: ( LUCRSURE.i18n && LUCRSURE.i18n.useThumbnail ) ? LUCRSURE.i18n.useThumbnail : 'Use Image' },
					multiple: false,
					library: { type: 'image' },
				} );

				frame.on( 'select', function () {
					var attachment = frame.state().get( 'selection' ).first().toJSON();
					$( '#lucrsure-plan-thumbnail-id' ).val( attachment.id );
					$planThumbForm.find( '.lucrsure-plan-thumbnail-preview' ).html(
						'<img src="' + attachment.url + '" alt="" />'
					);
					$planThumbForm.find( '.lucrsure-plan-thumbnail-remove' ).removeClass( 'is-hidden' );
				} );

				frame.open();
			} );

			$planThumbForm.on( 'click', '.lucrsure-plan-thumbnail-remove', function ( e ) {
				e.preventDefault();
				$( '#lucrsure-plan-thumbnail-id' ).val( '' );
				$planThumbForm.find( '.lucrsure-plan-thumbnail-preview' ).html(
					'<span class="lucrsure-muted">' + noThumbText + '</span>'
				);
				$( this ).addClass( 'is-hidden' );
			} );
		}

		// Branch form: media library image picker.
		var $branchImageForm = $( '.lucrsure-branch-image-form' );
		if ( $branchImageForm.length && typeof wp !== 'undefined' && wp.media ) {
			var noImageText = ( window.LUCRSURE && LUCRSURE.i18n && LUCRSURE.i18n.noImage ) ? LUCRSURE.i18n.noImage : 'No image selected';

			$branchImageForm.on( 'click', '.lucrsure-branch-image-upload', function ( e ) {
				e.preventDefault();
				var frame = wp.media( {
					title: ( LUCRSURE.i18n && LUCRSURE.i18n.selectImage ) ? LUCRSURE.i18n.selectImage : 'Select Branch Image',
					button: { text: ( LUCRSURE.i18n && LUCRSURE.i18n.useImage ) ? LUCRSURE.i18n.useImage : 'Use Image' },
					multiple: false,
					library: { type: 'image' },
				} );

				frame.on( 'select', function () {
					var attachment = frame.state().get( 'selection' ).first().toJSON();
					$( '#lucrsure-branch-image-id' ).val( attachment.id );
					$branchImageForm.find( '.lucrsure-branch-image-preview' ).html(
						'<img src="' + attachment.url + '" alt="" />'
					);
					$branchImageForm.find( '.lucrsure-branch-image-remove' ).removeClass( 'is-hidden' );
				} );

				frame.open();
			} );

			$branchImageForm.on( 'click', '.lucrsure-branch-image-remove', function ( e ) {
				e.preventDefault();
				$( '#lucrsure-branch-image-id' ).val( '' );
				$branchImageForm.find( '.lucrsure-branch-image-preview' ).html(
					'<span class="lucrsure-muted">' + noImageText + '</span>'
				);
				$( this ).addClass( 'is-hidden' );
			} );
		}

		// Frontend settings form.
		var $frontendSettingsForm = $( '.lucrsure-frontend-settings-form' );
		if ( $frontendSettingsForm.length ) {
			var $frontendTabs = $frontendSettingsForm.find( '.lucrsure-frontend-tabs' );
			if ( $frontendTabs.length ) {
				function activateFrontendTab( tab ) {
					$frontendTabs.find( '.lucrsure-frontend-tab' ).each( function () {
						var $btn = $( this );
						var active = $btn.data( 'tab' ) === tab;
						$btn.toggleClass( 'is-active', active ).attr( 'aria-selected', active ? 'true' : 'false' );
					} );
					$frontendSettingsForm.find( '.lucrsure-frontend-tab-panel' ).each( function () {
						var $panel = $( this );
						$panel.toggleClass( 'is-active', $panel.data( 'panel' ) === tab );
					} );
				}

				$frontendTabs.on( 'click', '.lucrsure-frontend-tab', function ( e ) {
					e.preventDefault();
					var tab = $( this ).data( 'tab' );
					activateFrontendTab( tab );
					if ( tab && window.history && window.history.replaceState ) {
						window.history.replaceState( null, '', window.location.pathname + window.location.search + '#' + tab );
					}
				} );

				var hashTab = window.location.hash.replace( /^#/, '' );
				if ( hashTab && $frontendTabs.find( '.lucrsure-frontend-tab[data-tab="' + hashTab + '"]' ).length ) {
					activateFrontendTab( hashTab );
				}
			}

			$frontendSettingsForm.on( 'change', 'input[name="plans_template"]', function () {
				$frontendSettingsForm.find( '.lucrsure-template-option' ).removeClass( 'is-selected' );
				$( this ).closest( '.lucrsure-template-option' ).addClass( 'is-selected' );
			} );

			if ( typeof wp !== 'undefined' && wp.media ) {
			var noHeroImageText = ( window.LUCRSURE && LUCRSURE.i18n && LUCRSURE.i18n.noImage ) ? LUCRSURE.i18n.noImage : 'No image selected';

			$frontendSettingsForm.on( 'click', '.lucrsure-hero-image-upload', function ( e ) {
				e.preventDefault();
				var frame = wp.media( {
					title: ( LUCRSURE.i18n && LUCRSURE.i18n.selectHeroImage ) ? LUCRSURE.i18n.selectHeroImage : 'Select Hero Image',
					button: { text: ( LUCRSURE.i18n && LUCRSURE.i18n.useImage ) ? LUCRSURE.i18n.useImage : 'Use Image' },
					multiple: false,
					library: { type: 'image' },
				} );

				frame.on( 'select', function () {
					var attachment = frame.state().get( 'selection' ).first().toJSON();
					$( '#lucrsure-hero-image-id' ).val( attachment.id );
					$frontendSettingsForm.find( '.lucrsure-hero-image-preview' ).html(
						'<img src="' + attachment.url + '" alt="" />'
					);
					$frontendSettingsForm.find( '.lucrsure-hero-image-remove' ).removeClass( 'is-hidden' );
				} );

				frame.open();
			} );

			$frontendSettingsForm.on( 'click', '.lucrsure-hero-image-remove', function ( e ) {
				e.preventDefault();
				$( '#lucrsure-hero-image-id' ).val( '' );
				$frontendSettingsForm.find( '.lucrsure-hero-image-preview' ).html(
					'<span class="lucrsure-muted">' + noHeroImageText + '</span>'
				);
				$( this ).addClass( 'is-hidden' );
			} );
			}
		}

		// Frontend settings: copy shortcode to clipboard.
		$( document ).on( 'click', '.lucrsure-copy-shortcode', function ( e ) {
			e.preventDefault();
			var $btn = $( this );
			var shortcode = $btn.data( 'shortcode' );
			var originalLabel = $btn.text();
			var copiedLabel = ( window.LUCRSURE && LUCRSURE.i18n && LUCRSURE.i18n.copied ) ? LUCRSURE.i18n.copied : 'Copied!';

			function showCopied() {
				$btn.text( copiedLabel ).addClass( 'is-copied' );
				setTimeout( function () {
					$btn.text( originalLabel ).removeClass( 'is-copied' );
				}, 1500 );
			}

			if ( navigator.clipboard && navigator.clipboard.writeText ) {
				navigator.clipboard.writeText( shortcode ).then( showCopied );
			} else {
				var $temp = $( '<textarea readonly></textarea>' ).val( shortcode ).appendTo( document.body );
				$temp[ 0 ].select();
				document.execCommand( 'copy' );
				$temp.remove();
				showCopied();
			}
		} );

		// Frontend settings: FAQ repeater.
		var $faqRepeater = $( '#lucrsure-faq-repeater' );
		if ( $faqRepeater.length ) {
			var faqItemLabel = ( window.LUCRSURE && LUCRSURE.i18n && LUCRSURE.i18n.faqItem ) ? LUCRSURE.i18n.faqItem : 'FAQ Item %d';
			var newFaqLabel = ( window.LUCRSURE && LUCRSURE.i18n && LUCRSURE.i18n.newFaqItem ) ? LUCRSURE.i18n.newFaqItem : 'New FAQ Item';

			function setFaqRowOpen( $row, open ) {
				$row.toggleClass( 'is-open', open );
				$row.find( '.lucrsure-faq-row-toggle' ).attr( 'aria-expanded', open ? 'true' : 'false' );
				$row.find( '.lucrsure-faq-row-body' ).prop( 'hidden', ! open );
			}

			function updateFaqRowTitle( $row ) {
				var question = $.trim( $row.find( 'input[name="faq_question[]"]' ).first().val() );
				var index = $faqRepeater.find( '.lucrsure-faq-row' ).index( $row ) + 1;
				var fallback = faqItemLabel.replace( '%d', index );
				$row.find( '.lucrsure-faq-row-title' ).text( question || fallback );
			}

			$faqRepeater.on( 'click', '.lucrsure-faq-row-toggle', function ( e ) {
				e.preventDefault();
				var $row = $( this ).closest( '.lucrsure-faq-row' );
				var open = $row.hasClass( 'is-open' );
				$faqRepeater.find( '.lucrsure-faq-row' ).not( $row ).each( function () {
					setFaqRowOpen( $( this ), false );
				} );
				setFaqRowOpen( $row, ! open );
			} );

			$faqRepeater.on( 'input', 'input[name="faq_question[]"]', function () {
				updateFaqRowTitle( $( this ).closest( '.lucrsure-faq-row' ) );
			} );

			$( '#lucrsure-faq-add' ).on( 'click', function ( e ) {
				e.preventDefault();
				var $template = $( '#lucrsure-faq-row-template' );
				if ( ! $template.length ) {
					return;
				}
				$faqRepeater.find( '.lucrsure-faq-row' ).each( function () {
					setFaqRowOpen( $( this ), false );
				} );
				$faqRepeater.append( $template.html() );
				var $newRow = $faqRepeater.find( '.lucrsure-faq-row' ).last();
				$newRow.find( '.lucrsure-faq-row-title' ).text( newFaqLabel );
				setFaqRowOpen( $newRow, true );
				$newRow.find( 'input[name="faq_question[]"]' ).first().trigger( 'focus' );
			} );

			$faqRepeater.on( 'click', '.lucrsure-faq-remove', function ( e ) {
				e.preventDefault();
				var $rows = $faqRepeater.find( '.lucrsure-faq-row' );
				var $row = $( this ).closest( '.lucrsure-faq-row' );
				if ( $rows.length <= 1 ) {
					$row.find( 'input, textarea' ).val( '' );
					$row.find( '.lucrsure-faq-row-title' ).text( newFaqLabel );
					setFaqRowOpen( $row, true );
					return;
				}
				var wasOpen = $row.hasClass( 'is-open' );
				$row.remove();
				if ( wasOpen ) {
					setFaqRowOpen( $faqRepeater.find( '.lucrsure-faq-row' ).first(), true );
				}
				$faqRepeater.find( '.lucrsure-faq-row' ).each( function () {
					updateFaqRowTitle( $( this ) );
				} );
			} );
		}

		// Setup wizard: category selection + staged demo import.
		var $setupWizard = $( '#lucrsure-setup-wizard' );
		if ( $setupWizard.length ) {
			var $importBtn = $( '#lucrsure-import-demo-btn' );
			var $dismissBtn = $( '#lucrsure-setup-dismiss-btn' );
			var $categoryInputs = $( '.lucrsure-setup-category-input' );
			var $progressWrap = $( '#lucrsure-setup-progress' );
			var $wizardFoot = $( '#lucrsure-setup-wizard-foot' );
			var $chooseStep = $( '.lucrsure-setup-step-choose' );
			var $progressLabel = $( '#lucrsure-demo-import-label' );
			var $progressPercent = $( '#lucrsure-demo-import-percent' );
			var $progressFill = $( '#lucrsure-demo-import-bar-fill' );
			var $progressStatus = $( '#lucrsure-demo-import-status' );
			var i18nDemo = ( window.LUCRSURE && window.LUCRSURE.i18n ) || {};
			var dashboardUrl = ( window.LUCRSURE && window.LUCRSURE.dashboardUrl ) || '/wp-admin/admin.php?page=lucrativeit-subscription-recurring-billing';
			var importing = false;

			function updateProgress( percent, message ) {
				$progressLabel.text( message );
				$progressPercent.text( percent + '%' );
				$progressFill.css( 'width', percent + '%' );
				$progressStatus.text( message );
			}

			function getSelectedCategories() {
				return $categoryInputs.filter( ':checked' ).map( function () {
					return $( this ).val();
				} ).get();
			}

			function runStep( step, isStart, categories ) {
				return $.post(
					( window.LUCRSURE && window.LUCRSURE.ajaxUrl ) || '/wp-admin/admin-ajax.php',
					{
						action: 'lucrsure_import_demo_step',
						nonce: window.LUCRSURE ? window.LUCRSURE.nonce : '',
						step: step || '',
						start: isStart ? '1' : '0',
						categories: categories || []
					}
				);
			}

			function processChain( step, isStart, categories ) {
				return runStep( step, isStart, categories ).then( function ( response ) {
					if ( ! response || ! response.success ) {
						var msg = response && response.data && response.data.message
							? response.data.message
							: ( i18nDemo.importFailed || 'Import failed.' );
						throw new Error( msg );
					}

					var data = response.data;
					updateProgress( data.percent || 0, data.message || '' );

					if ( data.done ) {
						updateProgress( 100, i18nDemo.importComplete || 'Import complete!' );
						setTimeout( function () {
							var url = ( data.redirect )
								? data.redirect
								: ( ( window.LUCRSURE && window.LUCRSURE.dashboardUrl ) || dashboardUrl );
							window.location.href = url;
						}, 900 );
						return;
					}

					if ( data.next_step ) {
						return processChain( data.next_step, false, categories );
					}
				} );
			}

			$dismissBtn.on( 'click', function () {
				if ( importing ) {
					return;
				}

				$dismissBtn.prop( 'disabled', true );

				$.post(
					( window.LUCRSURE && window.LUCRSURE.ajaxUrl ) || '/wp-admin/admin-ajax.php',
					{
						action: 'lucrsure_dismiss_onboarding_ajax',
						nonce: window.LUCRSURE ? window.LUCRSURE.nonce : ''
					}
				).always( function ( response ) {
					var redirect = response && response.data && response.data.redirect
						? response.data.redirect
						: dashboardUrl;
					window.location.href = redirect;
				} );
			} );

			$importBtn.on( 'click', function () {
				var categories = getSelectedCategories();
				if ( ! categories.length ) {
					window.alert( i18nDemo.selectCategory || 'Please select at least one category.' );
					return;
				}

				importing = true;
				$importBtn.prop( 'disabled', true ).addClass( 'is-loading' );
				$dismissBtn.prop( 'disabled', true );
				$chooseStep.prop( 'hidden', true );
				$progressWrap.prop( 'hidden', false );
				$wizardFoot.prop( 'hidden', true );
				updateProgress( 0, i18nDemo.importStarting || 'Starting import…' );

				processChain( '', true, categories ).catch( function ( err ) {
					importing = false;
					updateProgress( 0, err.message || i18nDemo.importFailed || 'Import failed.' );
					$chooseStep.prop( 'hidden', false );
					$progressWrap.prop( 'hidden', true );
					$wizardFoot.prop( 'hidden', false );
					$importBtn.prop( 'disabled', false ).removeClass( 'is-loading' );
					$dismissBtn.prop( 'disabled', false );
				} );
			} );
		}
	} );
} )( jQuery );
