/**
 * AffiliateWP — Bulk-pay drawer store
 *
 * Drives the Referrals bulk-pay drawer. open(ids) fetches the grouped-payout
 * preview (rendered server-side by the SAME renderer as the Pay Affiliates screen)
 * and injects it via x-html; pay() creates a real payout batch and hands off to the
 * batch drawer, keeping the admin on the Referrals screen.
 *
 * The drawer shell + footer markup come from includes/admin/payouts/bulk-pay-drawer.php.
 *
 * @package affiliate-wp
 * @since   2.33.0
 */

( function () {
	'use strict';

	const data = window.affwpBulkPayDrawer || {};
	const L    = data.labels || {};

	function register() {
		if ( ! window.Alpine || Alpine.store( 'bulkPayDrawer' ) ) {
			return;
		}

		Alpine.store( 'bulkPayDrawer', {
			isOpen: false,
			isLoading: false,
			isProcessing: false,
			title: '',
			subtitle: '',
			bodyHtml: '',
			totalLabel: '',
			confirmLabel: '',
			errors: {},
			count: 0,
			hasBlocking: false,
			payableIds: [],
			skippedItems: [],
			selectedIds: [],

			/**
			 * Open the drawer for a hand-picked set of referral IDs and load the preview.
			 *
			 * @param {Array} ids Selected referral IDs.
			 */
			open( ids ) {
				this.payableIds   = [];
				this.skippedItems = [];
				this.bodyHtml     = '';
				this.errors       = {};
				this.count        = 0;
				this.hasBlocking  = false;
				this.totalLabel   = '';
				this.confirmLabel = L.confirmDefault || 'Pay';
				this.title        = L.loadingTitle || 'Pay referrals';
				this.isProcessing = false;
				this.isLoading    = true;
				this.isOpen       = true;

				const selected = ( ids || [] ).map( ( id ) => parseInt( id, 10 ) ).filter( Boolean );
				this.selectedIds = selected;

				if ( ! selected.length || ! data.ajaxUrl || ! data.nonce ) {
					this.isLoading = false;
					this.errors    = { general: L.error || 'Something went wrong.' };
					return;
				}

				const body = new URLSearchParams();
				body.set( 'action', 'affwp_bulk_pay_drawer_preview' );
				body.set( 'nonce', data.nonce );
				selected.forEach( ( id ) => body.append( 'referral_ids[]', id ) );

				fetch( data.ajaxUrl, {
					method: 'POST',
					credentials: 'same-origin',
					headers: { 'Content-Type': 'application/x-www-form-urlencoded; charset=UTF-8' },
					body: body.toString()
				} )
					.then( ( r ) => r.json() )
					.then( ( res ) => {
						if ( ! res || ! res.success || ! res.data ) {
							throw new Error( ( res && res.data && res.data.message ) || L.error );
						}
						const d = res.data;
						this.bodyHtml     = d.body_html || '';
						this.title        = d.title || this.title;
						this.totalLabel   = d.total_label || '';
						this.confirmLabel = d.confirm_label || this.confirmLabel;
						this.count        = parseInt( d.count, 10 ) || 0;
						this.hasBlocking  = !! d.has_blocking;
						this.payableIds   = Array.isArray( d.payable_ids ) ? d.payable_ids.map( String ) : [];
						this.skippedItems = Array.isArray( d.skipped_items ) ? d.skipped_items : [];
						this.isLoading    = false;
					} )
					.catch( ( err ) => {
						this.isLoading = false;
						this.errors    = { general: ( err && err.message ) || L.networkError || 'Network error.' };
					} );
			},

			close() {
				this.isOpen = false;
			},

			/**
			 * Drawer-to-drawer swap into the payout drawer (mirrors batchDrawer.openPayout):
			 * close this drawer and open the payout drawer with a returnTo so its header shows a
			 * "Back to selection" breadcrumb that re-opens this drawer with the same selection.
			 * One drawer visible at a time — no overlap.
			 *
			 * @param {number} payoutId Payout ID to open.
			 */
			openPayout( payoutId ) {
				const payoutDrawer = window.Alpine && Alpine.store && Alpine.store( 'payoutDrawer' );
				if ( ! payoutDrawer || typeof payoutDrawer.openFor !== 'function' ) {
					return;
				}
				const returnTo = { type: 'bulkPay', ids: this.selectedIds.slice() };
				this.close();
				payoutDrawer.openFor( parseInt( payoutId, 10 ), { returnTo } );
			},

			/**
			 * Create a real payout batch from the payable subset, then hand off to the batch
			 * drawer to track it — same outcome as the Pay Affiliates screen, without leaving
			 * the Referrals list. The batch drawer polls to completion and fires its own toast.
			 */
			pay() {
				if ( this.isProcessing || ! this.count || this.hasBlocking || ! this.payableIds.length ) {
					return;
				}
				this.isProcessing = true;
				this.errors       = {};

				const body = new URLSearchParams();
				body.set( 'action', 'affwp_bulk_pay_create_batch' );
				body.set( 'nonce', data.nonce );
				this.payableIds.forEach( ( id ) => body.append( 'referral_ids[]', id ) );

				fetch( data.ajaxUrl, {
					method: 'POST',
					credentials: 'same-origin',
					headers: { 'Content-Type': 'application/x-www-form-urlencoded; charset=UTF-8' },
					body: body.toString()
				} )
					.then( ( r ) => r.json() )
					.then( ( res ) => {
						if ( ! res || ! res.success || ! res.data || ! res.data.batch_id ) {
							throw new Error( ( res && res.data && res.data.message ) || L.error );
						}
						const batchId = parseInt( res.data.batch_id, 10 );
						this.isProcessing = false;
						this.close();

						// Hand off to the batch drawer (same screen) to watch it process + retry.
						const batchDrawer = window.Alpine && Alpine.store && Alpine.store( 'batchDrawer' );
						if ( batchDrawer && typeof batchDrawer.openFor === 'function' ) {
							batchDrawer.openFor( batchId );
						} else if ( data.batchesUrl ) {
							// No batch-drawer store on this screen: fall back to the Batches tab.
							window.location.href = data.batchesUrl + '&batch_id=' + batchId;
						} else {
							window.location.reload();
						}
					} )
					.catch( ( err ) => {
						this.isProcessing = false;
						this.errors       = { general: ( err && err.message ) || L.networkError || 'Network error.' };
					} );
			}
		} );
	}

	if ( window.Alpine ) {
		register();
	} else {
		document.addEventListener( 'alpine:init', register );
	}
} )();
