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

/**
 * External dependencies
 */
import { map } from 'lodash';
import { EMPTY_ARRAY } from '@nelio-content/constants';
import { store as NC_DATA } from '@nelio-content/data';
import { hasHead, PUBLISHED } from '@nelio-content/utils';
import type { PostStatusSlug } from '@nelio-content/types';

/**
 * Internal dependencies
 */
import { useIsDisabled } from '../hooks';
import { store as NC_POST_EDITOR } from '../store';

export const StatusSelector = (): JSX.Element => {
	const [ status, setStatus ] = usePostStatus();
	const options = usePostStatuses();
	const disabled = useIsDisabled();
	const published = useIsAlreadyPublished();

	return (
		<div className="nelio-content-post-quick-editor__status">
			<SelectControl
				disabled={ disabled || published }
				value={ status }
				onChange={ setStatus }
				options={ options }
			/>
		</div>
	);
};

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

const usePostStatus = () => {
	const statuses = map( usePostStatuses(), 'value' );
	const status = useSelect(
		( select ) => select( NC_POST_EDITOR ).getPostStatus(),
		[]
	);
	const { setPostStatus } = useDispatch( NC_POST_EDITOR );

	useEffect( () => {
		if ( ! hasHead( statuses ) ) {
			return;
		}
		if ( ! status || ! statuses.includes( status ) ) {
			void setPostStatus( statuses[ 0 ] );
		}
	}, [ statuses, status, setPostStatus ] );

	return [ status, setPostStatus ] as const;
};

const usePostStatuses = (): ReadonlyArray< {
	readonly value: PostStatusSlug;
	readonly label: string;
	readonly disabled?: boolean;
} > => {
	const published = useIsAlreadyPublished();

	const { rawStatuses, canPublish } = useSelect( ( select ) => {
		const postType = select( NC_POST_EDITOR ).getPostType();
		const post = select( NC_DATA ).getPost(
			select( NC_POST_EDITOR ).getId()
		);

		return {
			rawStatuses: postType
				? select( NC_DATA ).getPostStatuses( postType )
				: EMPTY_ARRAY,
			canPublish: select( NC_DATA ).canCurrentUserPublishPost( post ),
		};
	}, [] );

	return useMemo( () => {
		const validStatuses = rawStatuses.filter(
			( { slug } ) => slug !== 'nelio-content-unscheduled'
		);

		const statuses = validStatuses.map(
			( { slug, name, available, flags = [] } ) => ( {
				value: slug,
				label: name,
				disabled:
					! available ||
					flags.includes( 'disabled-in-editor' ) ||
					( slug === 'future' && ! canPublish ),
			} )
		);

		if ( published ) {
			return [
				statuses.find( ( s ) => s.value === PUBLISHED ) ?? {
					value: PUBLISHED,
					label: _x( 'Published', 'text', 'nelio-content' ),
					disabled: true,
				},
			];
		}

		return statuses.filter(
			( { value } ) => value !== 'publish' && value !== 'trash'
		);
	}, [ rawStatuses, canPublish, published ] );
};

const useIsAlreadyPublished = () =>
	useSelect( ( select ) => {
		const postId = select( NC_POST_EDITOR ).getId();
		const post = select( NC_DATA ).getPost( postId );
		return 'publish' === post?.status;
	}, [] );
