/**
 * WordPress dependencies
 */
import { PanelBody } from '@safe-wordpress/components';
import { useDispatch, useSelect } from '@safe-wordpress/data';
import { useEffect } from '@safe-wordpress/element';
import { _x } from '@safe-wordpress/i18n';

/**
 * External dependencies
 */
import { store as NAB_EXPERIMENTS } from '@nab/experiments';
import { createScopeRule } from '@nab/utils';
import type {
	CustomPhpScopeRule,
	CustomUrlScopeRule,
	ScopeRule,
	TestedUrlWithQueryArgsScopeRule,
} from '@nab/types';

/**
 * Internal dependencies
 */
import './style.scss';
import { CustomUrlScope } from './custom-url-scope';
import { ConsistencyScope } from './consistency-scope';
import { ProductConsistencyScope } from './product-consistency-scope';
import { TestedUrlWithQueryArgsScope } from './tested-url-with-query-args-scope';
import { store as NAB_EDITOR } from '../../../store';
import { UrlsOrPhpScope } from './urls-or-php-scope';

export const Scope = (): JSX.Element | null => {
	const rules = useRules();
	const scopeSupport = useScopeSupport();
	const testAgainstExistingContent = useTestAgainstExistingContent();
	const { setScopeRules } = useDispatch( NAB_EDITOR );

	useEffect( () => {
		if (
			'tested-post-with-consistency' === scopeSupport &&
			testAgainstExistingContent
		) {
			void setScopeRules( [
				createScopeRule( { type: 'tested-post' } ),
			] );
		}
	}, [ scopeSupport, testAgainstExistingContent, setScopeRules ] );

	if ( ! scopeSupport ) {
		return null;
	}

	if ( testAgainstExistingContent ) {
		return null;
	}

	switch ( scopeSupport ) {
		case 'tested-post-with-consistency':
			return (
				<PanelBody
					className="nab-experiment-scope"
					title={ _x( 'Test Scope', 'text', 'nelio-ab-testing' ) }
				>
					<ConsistencyScope rules={ rules } />
				</PanelBody>
			);

		case 'tested-product-with-consistency':
			return (
				<PanelBody
					className="nab-experiment-scope"
					title={ _x( 'Test Scope', 'text', 'nelio-ab-testing' ) }
				>
					<ProductConsistencyScope rules={ rules } />
				</PanelBody>
			);

		case 'tested-url-with-query-args':
			return (
				<PanelBody
					className="nab-experiment-scope"
					title={ _x( 'Test Scope', 'text', 'nelio-ab-testing' ) }
				>
					<TestedUrlWithQueryArgsScope
						rules={ rules.filter(
							isTestedUrlWithQueryArgsScopeRule
						) }
					/>
				</PanelBody>
			);

		case 'urls':
		case 'urls-with-tested-post':
			return (
				<PanelBody
					className="nab-experiment-scope"
					title={ _x( 'Test Scope', 'text', 'nelio-ab-testing' ) }
				>
					<CustomUrlScope
						rules={ rules.filter( isCustomUrlScopeRule ) }
						scopeSupport={ scopeSupport }
					/>
				</PanelBody>
			);

		case 'urls-or-php':
			return (
				<PanelBody
					className="nab-experiment-scope"
					title={ _x( 'Test Scope', 'text', 'nelio-ab-testing' ) }
				>
					<UrlsOrPhpScope
						rules={ rules.filter(
							( r ) =>
								isCustomUrlScopeRule( r ) ||
								isCustomPhpScopeRule( r )
						) }
					/>
				</PanelBody>
			);
	}
};

// =====
// HOOKS
// =====

const useRules = () =>
	useSelect( ( select ) => select( NAB_EDITOR ).getScope(), [] );

const useScopeSupport = () =>
	useSelect( ( select ) => {
		const { getExperimentSupport } = select( NAB_EXPERIMENTS );
		const { getExperimentType } = select( NAB_EDITOR );
		return getExperimentSupport( getExperimentType(), 'scope' );
	}, [] );

const useTestAgainstExistingContent = () =>
	useSelect( ( select ) => {
		const control = select( NAB_EDITOR ).getAlternative( 'control' );
		return !! control?.attributes.testAgainstExistingContent;
	}, [] );

// =======
// HELPERS
// =======

export const isTestedUrlWithQueryArgsScopeRule = (
	r: ScopeRule
): r is TestedUrlWithQueryArgsScopeRule =>
	'tested-url-with-query-args' === r.attributes.type;

const CHECKER: Record< CustomUrlScopeRule[ 'attributes' ][ 'type' ], true > = {
	exact: true,
	partial: true,
	'partial-not-included': true,
	different: true,
};
export const isCustomUrlScopeRule = ( r: ScopeRule ): r is CustomUrlScopeRule =>
	( CHECKER as Record< string, boolean > )[ r.attributes.type ] || false;

export const isCustomPhpScopeRule = ( r: ScopeRule ): r is CustomPhpScopeRule =>
	'php-snippet' === r.attributes.type;
