import Alpine from 'alpinejs';
import { loadStyles, addXCloakStyle } from '../utils.js';

export class RewardsPanel extends HTMLElement {
	constructor() {
		super();
		this.attachShadow( { mode: 'open' } );

		// Bind event handlers
		this.handleToggleWidget = this.handleToggleWidget.bind( this );
	}

	async connectedCallback() {
		// Get the template from the page using data-template-id attribute (unique per render).
		// Falls back to default ID for backwards compatibility.
		const templateId = this.getAttribute( 'data-template-id' ) || 'rewards-panel';
		const template = document.getElementById( templateId );
		if ( ! template ) {
			throw new Error( `Template not found: ${ templateId }` );
		}

		// Clone and append the template content
		const content = template.content.cloneNode( true );

		// Load styles first
		await loadStyles( this.shadowRoot );
		addXCloakStyle( this.shadowRoot );

		// Append content to shadow DOM
		this.shadowRoot.appendChild( content );

		// Add event listener for toggle events
		window.addEventListener( 'toggle-widget', this.handleToggleWidget );

		// Wait for next tick to ensure DOM is ready
		requestAnimationFrame( () => {
			// Register redeemManager Alpine component for redeem functionality
			if ( window.Alpine && !window.Alpine._data?.redeemManager ) {
			window.Alpine.data('redeemManager', () => {
				return {
				redeemStates: {},
				// Initialize user data from component attributes or global fallback
				userData: (() => {
					const host = document.querySelector('rewards-panel');
					const attrPoints = host ? host.getAttribute('data-user-points') : null;
					const points = attrPoints !== null ? parseInt(attrPoints, 10) : (window.rewardswpMainVars?.userPoints || 0);
					return { points: Number.isFinite(points) ? points : 0 };
				})(),

				init() {
					// Listen for member-joined event to update points
					window.addEventListener('member-joined', (event) => {
						if (event.detail && event.detail.pointsBalance !== undefined) {
							this.userData.points = event.detail.pointsBalance || 0;
						}
					});
				},

			async redeemPointsForCoupon(actionType, actionId, actionKey) {
					// Get reference to shadowRoot for event dispatching
					const shadowRoot = document.querySelector('rewards-panel')?.shadowRoot;

						// Check if we're in admin preview mode by checking for the rwp-admin-preview class
						// Look in both the shadow DOM and the main document
						const hasClassInShadow = shadowRoot?.querySelector('.rwp-admin-preview') !== null;
						const hasClassInDocument = document.querySelector('.rwp-admin-preview') !== null;
						const isAdminPreview = hasClassInShadow || hasClassInDocument;

						if (isAdminPreview) {
							// Show toast notification instead of processing redemption
							window.dispatchEvent(new CustomEvent('rewardswp-toast', {
								detail: {
									message: 'Points cannot be redeemed in admin preview',
									type: 'info'
								}
							}));

							return;
						}

						// Initialize state for this action if not exists
						if (!this.redeemStates[actionKey]) {
							this.redeemStates[actionKey] = {
								redeeming: false,
								success: false,
								error: false,
								errorMessage: ''
							};
						}

						const state = this.redeemStates[actionKey];

						if (state.redeeming) return;

						// Reset states
						state.success = false;
						state.error = false;
						state.errorMessage = '';
						state.redeeming = true;

						try {
							const host = document.querySelector('rewards-panel');
							const ajaxUrl = host ? (host.getAttribute('data-ajax-url') || '') : (window.rewardswpMainVars?.ajaxUrl || '');
							const nonce = host ? (host.getAttribute('data-share-points-nonce') || '') : (window.rewardswpMainVars?.sharePointsNonce || '');
							const formData = new FormData();
							formData.append('action', 'rewardswp_redeem_points_for_coupon');
							formData.append('_ajax_nonce', nonce);
							formData.append('spend_action_type', actionType);
							formData.append('spend_action_id', actionId);

							// Add type-specific data
							if (actionType === 'fixed_discount') {
								formData.append('discount_amount', 1); // $1 discount
							} else if (actionType === 'percentage_discount') {
								formData.append('discount_percentage', 1); // 1% discount
							}

							const response = await fetch(ajaxUrl, {
								method: 'POST',
								body: formData
							});

							// Parse JSON even for non-200 responses to get error messages from backend.
							const result = await response.json();

							// Handle network-level errors (no valid JSON response).
							if (!response.ok && !result) {
								throw new Error(`HTTP error! status: ${response.status}`);
							}

					if (result.success) {
						// Get the host element (the custom element itself)
						const hostElement = document.querySelector('rewards-panel');

						// The Alpine component is INSIDE the shadow DOM, not outside
						let parentElement = null;

					if (shadowRoot) {
						// Look for Alpine component inside shadow DOM
						parentElement = shadowRoot.querySelector('[x-data*="rewardsPanelWidget"]');

						if (!parentElement) {
							// Try generic x-data
							parentElement = shadowRoot.querySelector('[x-data]');
						}
					}

					if (parentElement && parentElement._x_dataStack && parentElement._x_dataStack[0]) {
						if (parentElement._x_dataStack[0].userData) {
							parentElement._x_dataStack[0].userData.points = result.data.new_balance;
						}

						// Don't call refreshRewardsData here - the show-redeem-success event handler will do it
					}

						// Show success screen by dispatching event to parent
						const successEvent = new CustomEvent('show-redeem-success', {
							detail: {
								couponCode: result.data.coupon_code,
							pointsSpent: result.data.points_spent,
							newBalance: result.data.new_balance,
							message: result.data.message,
							iconHtml: result.data.icon_html || '',
							title: result.data.title || '',
							pointsLabel: result.data.points_label || 'points',
							couponTerms: result.data.coupon_terms || '',
							expiryText: result.data.expiry_text || '',
								isApplied: result.data.is_applied || false,
								rewardId: result.data.reward_id || 0,
								rewardType: actionType || '',
								limitReached: result.data.limit_reached || false,
								actionId: result.data.action_id || '',
								freeProductId: result.data.free_product_id || null,
								minimumOrderAmount: result.data.minimum_order_amount || 0,
								freeProductPrice: result.data.free_product_price || 0
							},
							bubbles: true,
							composed: true
						});

							// Dispatch to window - Alpine handler will catch it
							window.dispatchEvent(successEvent);

							// Clear state since we're showing success screen
							state.success = false;
							state.error = false;
							state.redeeming = false;
							} else {
								state.error = true;
								state.errorMessage = result.data?.message || 'Failed to redeem points. Please try again.';
							}
						} catch (error) {
							state.error = true;
							state.errorMessage = 'Network error. Please try again.';
						} finally {
							state.redeeming = false;
						}
					}
				};
				});
			}

			// Initialize Alpine within the shadow DOM
			// We need to use the global Alpine instance that has our components registered
			if ( window.Alpine ) {
				window.Alpine.initTree( this.shadowRoot );
			} else {
				console.error( 'Alpine is not available on window' );
			}
		} );
	}

	disconnectedCallback() {
		// Remove event listener
		window.removeEventListener( 'toggle-widget', this.handleToggleWidget );

		// Clean up Alpine
		if ( window.Alpine ) {
			window.Alpine.destroyTree( this.shadowRoot );
		}
	}

	handleToggleWidget( event ) {
		// Forward the event to the shadow DOM
		const shadowEvent = new CustomEvent( 'toggle-widget', {
			detail: event.detail,
			bubbles: true,
			composed: true
		} );
		this.shadowRoot.dispatchEvent( shadowEvent );
	}
}

