import $ from 'jquery'
import ctEvents from 'ct-events'

let mounted = false

let addedToCart = false

const fragmentedSelectors = [
	'.ct-suggested-products--mini-cart',
	'.ct-shipping-progress-mini-cart',
]

// A WooCommerce fragment can be re-applied from the localStorage cache long
// after the feature that produced it was turned off in the Customizer. When
// that happens its dynamic style is no longer registered server-side, so the
// markup lands on the page completely unstyled. Detect that case (an element
// present with no registered dynamic style covering it) and drop the leftover.
const removeUnstyledFragments = () => {
	if (!ct_localizations.dynamic_styles_selectors) {
		return
	}

	fragmentedSelectors.forEach((selector) => {
		;[...document.querySelectorAll(selector)].forEach((el) => {
			const hasRegisteredStyles =
				ct_localizations.dynamic_styles_selectors.some((descriptor) =>
					el.matches(descriptor.selector)
				)

			if (hasRegisteredStyles) {
				return
			}

			el.remove()
		})
	})
}

export const mount = (el, { event }) => {
	if (!$) return

	const maybeCartLink = el.querySelector('.ct-cart-item')

	if (
		el.matches('.ct-header-cart') &&
		maybeCartLink &&
		!maybeCartLink.classList.contains('ct-offcanvas-trigger') &&
		event &&
		event.type === 'touchstart'
	) {
		location.href = maybeCartLink.getAttribute('href')
		return
	}

	const selector = '.ct-header-cart, .ct-shortcuts-bar [data-id="cart"]'

	if (mounted) {
		return
	}

	mounted = true

	// This chunk loads lazily (on cart hover/touch), which can happen after the
	// fragments were already applied from cache on page load — so run a cleanup
	// pass right away, before the panel opens, in addition to the events below.
	removeUnstyledFragments()

	$(document.body).on('adding_to_cart', () =>
		[...document.querySelectorAll(selector)].map((cart) => {
			if (!cart.closest('.ct-shortcuts-bar')) {
				cart = cart.firstElementChild
			}

			cart.classList.remove('ct-added')
			cart.classList.add('ct-adding')
		})
	)

	$(document.body).on('wc_fragments_loaded', () => {
		setTimeout(() => ctEvents.trigger('blocksy:frontend:init'))
	})

	$(document.body).on('wc_cart_button_updated', (data, buttons) => {
		if (
			window.wc_add_to_cart_params &&
			window.wc_add_to_cart_params.i18n_view_cart_with_icon &&
			buttons &&
			buttons.length > 0
		) {
			const button = buttons[0]

			if (button.closest('[data-products]')) {
				button.nextElementSibling.innerHTML =
					wc_add_to_cart_params.i18n_view_cart_with_icon
			}
		}
	})

	const autoOpenCart = () => {
		;[...document.querySelectorAll(selector)].map((cart, index) => {
			if (index > 0) {
				return
			}

			if (
				!document.querySelector('#ct-compare-modal.active') &&
				!document.querySelector('.quick-view-modal.active') &&
				!document.querySelector('#woo-cart-panel.active') &&
				((!document.body.classList.contains('single-product') &&
					!document.body.classList.contains('woocommerce-cart') &&
					!document.body.classList.contains('woocommerce-checkout') &&
					cart.querySelector('[data-auto-open*="archive"]')) ||
					(document.body.classList.contains('single-product') &&
						cart.querySelector('[data-auto-open*="product"]')))
			) {
				cart.querySelector('[data-auto-open]').focusDisabled = true
				cart.querySelector('[data-auto-open]').click()
			}
		})
	}

	$(document.body).on(
		'added_to_cart',
		(_, fragments, __, button, quantity) => {
			button = button[0]
			;[...document.querySelectorAll(selector)].map((cart, index) => {
				let elForOpen = cart

				if (!cart.closest('.ct-shortcuts-bar')) {
					elForOpen = cart.firstElementChild
				}

				elForOpen.classList.remove('ct-adding')
				elForOpen.classList.add('ct-added')
			})

			if (Object.keys(fragments).length > 0) {
				autoOpenCart()
			} else {
				addedToCart = true
			}
		}
	)

	$(document.body).on('wc_fragments_refreshed', () => {
		if (addedToCart) {
			autoOpenCart()
		}

		addedToCart = false
		setTimeout(() => {
			ctEvents.trigger('blocksy:frontend:init')
			clearCartContent()
		})
	})

	$(document).on('uael_quick_view_loader_stop', () => {
		ctEvents.trigger('ct:add-to-cart:quantity')
	})

	$(document).on('facetwp-loaded', () => {
		ctEvents.trigger('ct:custom-select:init')
	})

	const clearCartContent = () => {
		let maybeCartContent = document.querySelector(
			'.ct-header-cart .ct-cart-content'
		)

		if (maybeCartContent) {
			maybeCartContent.removeAttribute('style')
		}
	}

	$(document.body).on('wc_fragments_loaded', () => {
		setTimeout(() => {
			ctEvents.trigger('blocksy:frontend:init')

			clearCartContent()
		})
	})

	;['wc_fragments_loaded', 'wc_fragments_refreshed'].forEach((event) => {
		$(document.body).on(event, () => {
			setTimeout(() => removeUnstyledFragments())
		})
	})

	$(document.body).on('click', '.remove_from_cart_button', {}, (e) => {
		const maybeItem = e.target.closest('.woocommerce-mini-cart-item')

		if (maybeItem) {
			maybeItem.classList.add('processing')
		}
	})

	$(document.body).on('removed_from_cart', (_, __, ___, button) => {
		;[...document.querySelectorAll(selector)].map((cart) => {
			if (!button) return

			try {
				if (button[0].closest('.updating')) {
					button[0].closest('.updating').classList.remove('updating')
				}

				button[0].closest('li').remove()
			} catch (e) {}
		})

		$(document).trigger('wc_update_cart')
		$(document.body).trigger('update_checkout')
	})

	$(document.body).on('click', '.remove_from_cart_button', (e) => {
		if (!e.target.closest('[data-placement]')) {
			return
		}

		window.blocksySkippedFragments = [e.target.closest('[data-placement]')]
	})

	const originalReplaceWith = jQuery.fn.replaceWith

	jQuery.fn.replaceWith = function () {
		let content = arguments[0]

		// Normalize content
		if (content && typeof content !== 'string') {
			// jQuery object or array-like
			if (content.jquery || content.length !== undefined) {
				content = content[0]
			}

			// DOM element → convert to HTML
			if (content instanceof Element) {
				content = content.outerHTML
			}
		}

		if (
			window.blocksySkippedFragments &&
			window.blocksySkippedFragments.includes(this[0])
		) {
			const div = document.createElement('div')
			div.innerHTML = content

			this[0].innerHTML = div.firstElementChild.innerHTML
			;[...div.firstElementChild.attributes].forEach(
				({ name, value }) => {
					this[0].setAttribute(name, value)
				}
			)

			ctFrontend.preloadAssetsForContent(content)

			return this
		}

		if (typeof content === 'string') {
			ctFrontend.preloadAssetsForContent(content)
		}

		return originalReplaceWith.apply(this, arguments)
	}
}
