// @vitest-environment jsdom
import { afterEach, describe, expect, it, vi } from 'vitest';
import { addRecommendedVariationToCart } from './woocommerceCart';

function mountForm() {
	document.body.innerHTML = `
		<form class="variations_form">
			<select name="attribute_pa_size"><option value="s">S</option><option value="m">M</option></select>
			<input class="variation_id" value="" />
			<button type="button" class="single_add_to_cart_button">Add</button>
		</form>`;
	const form = document.querySelector( 'form' ) as HTMLFormElement;
	const select = document.querySelector( 'select' ) as HTMLSelectElement;
	const variant = document.querySelector( 'input' ) as HTMLInputElement;
	const button = document.querySelector( 'button' ) as HTMLButtonElement;
	return { form, select, variant, button };
}

describe( 'addRecommendedVariationToCart', () => {
	afterEach( () => {
		document.body.innerHTML = '';
		vi.useRealTimers();
	} );

	it( 'dispatches the complete selection and clicks only after Woo resolves the exact variant', async () => {
		const { select, variant, button } = mountForm();
		const click = vi.spyOn( button, 'click' );
		select.addEventListener( 'change', () => { variant.value = '123'; } );

		await expect( addRecommendedVariationToCart( '123', { attribute_pa_size: 'm' } ) ).resolves.toBe( true );
		expect( select.value ).toBe( 'm' );
		expect( click ).toHaveBeenCalledOnce();
	} );

	it.each( [ undefined, {} ] )( 'rejects a missing or empty selection: %j', async ( selection ) => {
		mountForm();
		await expect( addRecommendedVariationToCart( '123', selection ) ).resolves.toBe( false );
	} );

	it( 'rejects absent controls and impossible option values without mutating variation_id', async () => {
		expect( await addRecommendedVariationToCart( '123', { size: 'm' } ) ).toBe( false );
		const { variant } = mountForm();
		expect( await addRecommendedVariationToCart( '123', { missing: 'm' } ) ).toBe( false );
		expect( await addRecommendedVariationToCart( '123', { attribute_pa_size: 'xl' } ) ).toBe( false );
		expect( variant.value ).toBe( '' );
	} );

	it( 'does not click when Woo leaves the button disabled through the resolution deadline', async () => {
		vi.useFakeTimers();
		const { variant, button } = mountForm();
		variant.value = '123';
		button.disabled = true;
		const click = vi.spyOn( button, 'click' );
		const pending = addRecommendedVariationToCart( '123', { attribute_pa_size: 'm' } );
		await vi.advanceTimersByTimeAsync( 2100 );
		await expect( pending ).resolves.toBe( false );
		expect( click ).not.toHaveBeenCalled();
	} );

	it( 'does not click a form detached while Woo resolves the variation', async () => {
		const { form, select, variant, button } = mountForm();
		const click = vi.spyOn( button, 'click' );
		select.addEventListener( 'change', () => {
			variant.value = '123';
			form.remove();
		} );
		await expect( addRecommendedVariationToCart( '123', { attribute_pa_size: 'm' } ) ).resolves.toBe( false );
		expect( click ).not.toHaveBeenCalled();
	} );
} );
