/**
 * External dependencies
 */
import Select from 'react-select';
import { isArray } from 'lodash';
import { COLORS } from '@nab/utils';
import type { Props as SelectProps, StylesConfig } from 'react-select';

/**
 * Internal dependencies
 */
import './style.scss';

export const DEFAULT_STYLE: StylesConfig< unknown, boolean > = {
	control: ( _, state ) => ( {
		...getControlBorder( state ),
		background: state.isDisabled
			? COLORS.nabBackgroundLightGrey
			: COLORS.nabBackgroundWhite,
		boxShadow: undefined,
		display: 'flex',
		flexDirection: 'row',
		fontSize: '13px',
		height: ! state.isMulti ? '40px' : undefined,
		margin: '0',
		marginBottom: '1em',
		padding: '0 6px 0 12px',
		paddingLeft: state.isMulti ? '0' : undefined,
	} ),

	singleValue: ( style, state ) => ( {
		...style,
		color: state.isDisabled ? COLORS.nabTextLightGrey : COLORS.nabText,
	} ),

	input: ( style ) => ( {
		...style,
		marginTop: '-3px',
	} ),

	groupHeading: ( style ) => ( {
		...style,
		padding: '1em',
	} ),

	loadingIndicator: () => ( {
		display: 'none',
	} ),

	indicatorSeparator: () => ( {
		display: 'none',
	} ),

	dropdownIndicator: () => ( {
		display: 'flex',
		color: 'transparent',
		width: '1.5em',
		height: '100%',
		background:
			'url(\'data:image/svg+xml,<svg viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg" width="18" height="18"><path d="M17.5 11.6L12 16l-5.5-4.4.9-1.2L12 14l4.5-3.6 1 1.2z"></path></svg>\') center no-repeat',
	} ),

	menuPortal: ( style ) => {
		const margin = 14;
		const width = Math.min( document.body.clientWidth - 2 * margin, 300 );
		const sl: unknown = isArray( style.left )
			? style.left[ 0 ]
			: style.left;
		const styleLeft = numberify( sl );

		const overflowX = Math.abs(
			Math.min(
				0,
				document.body.clientWidth - ( styleLeft + width + 14 )
			)
		);
		const left = styleLeft - overflowX;

		return {
			...style,
			zIndex: '999999',
			width,
			left,
			right: left + width - margin,
		};
	},

	menu: ( style ) => ( {
		...style,
		borderRadius: 0,
	} ),

	option: ( style, state ) => ( {
		...style,
		...getOptionColor( state ),
		padding: '0.5em 1em',
	} ),
};

export function StylizedSelectControl< OptionType, IsMulti extends boolean >( {
	className = '',
	styles = {},
	// eslint-disable-next-line @typescript-eslint/no-unused-vars
	menuPortalTarget,
	...props
}: SelectProps< OptionType, IsMulti > ): JSX.Element {
	return (
		<Select
			className={ `nab-stylized-select-control ${ className }` }
			/* eslint-disable-next-line @typescript-eslint/no-unsafe-assignment, @typescript-eslint/no-explicit-any */
			styles={ { ...DEFAULT_STYLE, ...styles } as any }
			menuPortalTarget={ document.body }
			{ ...{ menuPlacement: 'auto', ...props } }
		></Select>
	);
}

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

const getControlBorder = ( {
	isDisabled,
	isFocused,
}: Partial< {
	isDisabled: boolean;
	isFocused: boolean;
} > = {} ) => {
	let color = COLORS.nabBorder;

	if ( isFocused ) {
		color = COLORS.wpComponentsColorAccent;
	}

	if ( isDisabled ) {
		color = COLORS.nabBorderLighter;
	}

	return {
		border: `1px solid ${ color }`,
		borderRadius: '2px',
	};
};

const getOptionColor = ( {
	isSelected,
	isFocused,
}: Partial< {
	isSelected: boolean;
	isFocused: boolean;
} > = {} ) => {
	let color = COLORS.nabText;
	let background = COLORS.nabBackgroundWhite;

	if ( isSelected ) {
		background = COLORS.nabBackgroundLightGrey;
	}

	if ( isFocused ) {
		color = COLORS.nabBackgroundWhite;
		background = COLORS.wpComponentsColorAccent;
	}

	return { background, color };
};

const numberify = ( x: unknown ): number => {
	if ( 'number' === typeof x ) {
		return x;
	}
	return 'string' === typeof x ? Number.parseInt( x ) || 0 : 0;
};
