/**
 * External dependencies
 */
import { render, useEffect, useState } from '@wordpress/element';
import { __ } from '@wordpress/i18n';
import { TourKit, TourKitTypes } from '@woocommerce/components';
import { recordEvent } from '@woocommerce/tracks';
import qs from 'qs';

/**
 * Internal dependencies
 */
import { useTmceIframeFocusStyle } from './use-tmce-iframe-focus-style';
import { useActiveEditorType } from './use-active-editor-type';
import {
	bindEnableGuideModeClickEvent,
	waitUntilElementTopNotChange,
} from './utils';
import {
	ProductTourStepName,
	useProductStepChange,
} from './use-product-step-change';
import { useTrackPublishButton } from './use-track-publish-button';

const getTourConfig = ( {
	isExcerptEditorTmceActive,
	isContentEditorTmceActive,
	closeHandler,
	onNextStepHandler,
}: {
	isExcerptEditorTmceActive: boolean;
	isContentEditorTmceActive: boolean;
	closeHandler: TourKitTypes.CloseHandler;
	onNextStepHandler: ( currentStepIndex: number ) => void;
} ): TourKitTypes.WooConfig => {
	return {
		placement: 'bottom-start',
		options: {
			effects: {
				spotlight: {
					interactivity: {
						enabled: true,
						rootElementSelector: '#wpwrap',
					},
				},
				arrowIndicator: true,
				autoScroll: {
					behavior: 'auto',
					block: 'center',
				},
			},
			popperModifiers: [
				{
					name: 'arrow',
					options: {
						padding: ( {
							popper,
						}: {
							popper: { width: number };
						} ) => {
							return {
								// Align the arrow to the left of the popper.
								right: popper.width - 34,
							};
						},
					},
				},
			],
			callbacks: {
				onNextStep: onNextStepHandler,
			},
		},
		steps: [
			{
				referenceElements: {
					desktop: '#title',
				},
				focusElement: {
					desktop: '#title',
				},
				meta: {
					name: 'product-name',
					heading: __( 'Product name', 'woocommerce' ),
					descriptions: {
						desktop: __(
							'Start typing your new product name here. This will be what your customers will see in your store.',
							'woocommerce'
						),
					},
				},
			},
			{
				referenceElements: {
					desktop: '#postdivrich',
				},
				focusElement: {
					iframe: isContentEditorTmceActive
						? '#content_ifr'
						: undefined,
					desktop: isContentEditorTmceActive
						? '#tinymce'
						: '#wp-content-editor-container > .wp-editor-area',
				},
				meta: {
					name: 'product-description',
					heading: __(
						'Add your product description',
						'woocommerce'
					),
					descriptions: {
						desktop: __(
							'Start typing your new product name here. Add your full product description here. Describe your product in detail.',
							'woocommerce'
						),
					},
				},
			},
			{
				referenceElements: {
					desktop: '#woocommerce-product-data',
				},
				focusElement: {
					desktop: '#_regular_price',
				},
				meta: {
					name: 'product-data',
					heading: __( 'Add your product data', 'woocommerce' ),
					descriptions: {
						desktop: __(
							'Use the tabs to switch between sections and insert product details. Start by adding your product price.',
							'woocommerce'
						),
					},
				},
			},
			{
				referenceElements: {
					desktop: '#postexcerpt',
				},
				focusElement: {
					iframe: isExcerptEditorTmceActive
						? '#excerpt_ifr'
						: undefined,
					desktop: isExcerptEditorTmceActive
						? '#tinymce'
						: '#wp-excerpt-editor-container > .wp-editor-area',
				},
				meta: {
					name: 'product-short-description',
					heading: __(
						'Add your short product description',
						'woocommerce'
					),
					descriptions: {
						desktop: __(
							'Type a quick summary for your product here. This will appear on the product page right under the product name.',
							'woocommerce'
						),
					},
				},
			},
			{
				referenceElements: {
					desktop: '#postimagediv',
				},
				focusElement: {
					desktop: '#set-post-thumbnail',
				},
				meta: {
					name: 'product-image',
					heading: __( 'Add your product image', 'woocommerce' ),
					descriptions: {
						desktop: __(
							'Upload an image to your product here. Ideally a JPEG or PNG about 600 px wide or bigger. This image will be shown in your store’s catalog.',
							'woocommerce'
						),
					},
				},
			},
			{
				referenceElements: {
					desktop: '#tagsdiv-product_tag',
				},
				focusElement: {
					desktop: '#new-tag-product_tag',
				},
				meta: {
					name: 'product-tags',
					heading: __( 'Add your product tags', 'woocommerce' ),
					descriptions: {
						desktop: __(
							'Add your product tags here. Tags are a method of labeling your products to make them easier for customers to find. For example, if you sell clothing, and you have a lot of cat prints, you could make a tag for “cat.”',
							'woocommerce'
						),
					},
				},
			},
			{
				referenceElements: {
					desktop: '#product_catdiv',
				},
				meta: {
					name: 'product-categories',
					heading: __( 'Add your product categories', 'woocommerce' ),
					descriptions: {
						desktop: __(
							'Add your product categories here. Assign categories to your products to make them easier to browse through and find in your store.',
							'woocommerce'
						),
					},
				},
			},
			{
				referenceElements: {
					desktop: '#submitdiv',
				},
				focusElement: {
					desktop: '#submitdiv',
				},
				meta: {
					name: 'publish',
					heading: __( 'Publish your product 🎉', 'woocommerce' ),
					descriptions: {
						desktop: __(
							'Good work! Now you can publish your product to your store by hitting the “Publish” button or keep editing it.',
							'woocommerce'
						),
					},
					primaryButton: {
						text: __( 'Keep editing', 'woocommerce' ),
					},
				},
			},
		],
		closeHandler,
	};
};

const ProductTour = () => {
	const [ showTour, setShowTour ] = useState< boolean >( false );
	const { setIsLoaded, hasUpdatedInfo } = useProductStepChange();

	const { isTmce: isContentEditorTmceActive } = useActiveEditorType( {
		editorWrapSelector: '#wp-content-wrap',
	} );
	const { isTmce: isExcerptEditorTmceActive } = useActiveEditorType( {
		editorWrapSelector: '#wp-excerpt-wrap',
	} );

	const { style: contentTmceIframeFocusStyle } = useTmceIframeFocusStyle( {
		isActive: showTour && isContentEditorTmceActive,
		iframeSelector: '#content_ifr',
	} );
	const { style: excerptTmceIframeFocusStyle } = useTmceIframeFocusStyle( {
		isActive: showTour && isExcerptEditorTmceActive,
		iframeSelector: '#excerpt_ifr',
	} );

	const tourConfig = getTourConfig( {
		isContentEditorTmceActive,
		isExcerptEditorTmceActive,
		closeHandler: ( steps, stepIndex ) => {
			setShowTour( false );
			if ( steps.length - 1 === stepIndex ) {
				recordEvent( 'walkthrough_product_completed' );
			} else {
				recordEvent( 'walkthrough_product_dismissed', {
					step_name: steps[ stepIndex ].meta.name,
				} );
			}
		},
		onNextStepHandler: ( stepIndex ) => {
			const stepName = tourConfig.steps[ stepIndex ].meta.name;

			// This records all "next" steps and ignores the final "publish" step.
			recordEvent( 'walkthrough_product_step_completed', {
				step_name: stepName,
				added_info: hasUpdatedInfo( stepName as ProductTourStepName )
					? 'yes'
					: 'no',
			} );
		},
	} );

	useEffect( () => {
		bindEnableGuideModeClickEvent( ( e ) => {
			e.preventDefault();
			setShowTour( true );
			recordEvent( 'walkthrough_product_enable_button_click' );
		} );

		const query = qs.parse( window.location.search.slice( 1 ) );
		if ( query && query.tutorial === 'true' ) {
			const intervalId = waitUntilElementTopNotChange(
				tourConfig.steps[ 0 ].referenceElements?.desktop || '',
				() => {
					setShowTour( true );
					recordEvent( 'walkthrough_product_view', {
						spotlight: 'yes',
						product_template: 'physical',
					} );
					setIsLoaded( true );
				},
				500
			);
			return () => clearInterval( intervalId );
		}
		// only run once
		// eslint-disable-next-line react-hooks/exhaustive-deps
	}, [] );

	useTrackPublishButton( showTour );

	if ( ! showTour ) {
		return null;
	}

	return (
		<>
			<style>
				{ contentTmceIframeFocusStyle }
				{ excerptTmceIframeFocusStyle }
				{ `.wp-editor-area:focus {
						border: 1.5px solid #007CBA;
					}` }
			</style>
			<TourKit config={ tourConfig } />
		</>
	);
};

const root = document.createElement( 'div' );
root.setAttribute( 'id', 'product-tour-root' );
render( <ProductTour />, document.body.appendChild( root ) );
