/**
 * WordPress dependencies.
 */
import { Panel, PanelBody } from '@wordpress/components';
import { useEffect, useState, WPElement } from '@wordpress/element';
import { __, sprintf } from '@wordpress/i18n';

/**
 * Internal dependencies.
 */

import { useSettingsScreen } from '../../settings-screen';
import { useSync } from '../../sync';
import Controls from '../components/controls';
import Indexables from '../components/types';
import Log from '../components/log';
import Objects from '../components/objects';
import Progress from '../components/progress';
import PutMapping from '../components/put-mapping';
import SyncHistory from '../components/sync-history';
import { useSyncSettings } from '../provider';

/**
 * Sync page component.
 *
 * @returns {WPElement} Sync page component.
 */
export default () => {
	const { createNotice } = useSettingsScreen();
	const {
		errorCounts,
		isComplete,
		isEpio,
		isSyncing,
		logMessage,
		startSync,
		syncHistory,
		syncTrigger,
	} = useSync();
	const { args, autoIndex } = useSyncSettings();

	/**
	 * State.
	 */
	const [isLogOpen, setIsLogOpen] = useState(false);
	const [errorCount, setErrorCount] = useState(0);

	/**
	 * Handle toggling the log panel.
	 *
	 * @param {boolean} opened Whether the panel will be open.
	 */
	const onToggleLog = (opened) => {
		setIsLogOpen(opened);
	};

	/**
	 * Display a notice when a sync is complete.
	 */
	const onCompleteDisplayNotice = () => {
		if (isComplete) {
			createNotice('success', __('Sync completed.', 'elasticprobe'));
		}
	};

	/**
	 * Handle logs and errors count when a sync is complete.
	 */
	const onComplete = () => {
		if (isComplete) {
			const newErrorCount = errorCounts.reduce((c, e) => c + e.count, 0);

			if (newErrorCount > errorCount) {
				setIsLogOpen(true);
			}

			setErrorCount(newErrorCount);
		}
	};

	/**
	 * Initialize.
	 *
	 * @returns {void}
	 */
	const onInit = () => {
		if (autoIndex) {
			startSync({ put_mapping: true, trigger: syncTrigger });
			logMessage(__('Starting delete and sync…', 'elasticprobe'), 'info');
		}
	};

	/**
	 * Handle clicking sync button.
	 *
	 * @param {Event} event Submit event.
	 * @returns {void}
	 */
	const onSync = async (event) => {
		event.preventDefault();

		const { put_mapping } = args;

		const putMapping = syncHistory.length ? put_mapping : true;
		const syncArgs = { ...args, put_mapping: putMapping, trigger: 'manual' };

		startSync(syncArgs);
		logMessage(__('Starting sync…', 'elasticprobe'), 'info');
	};

	useEffect(onCompleteDisplayNotice, [createNotice, isComplete]);
	useEffect(onComplete, [createNotice, errorCount, errorCounts, isComplete]);
	useEffect(onInit, [autoIndex, logMessage, startSync, syncTrigger]);

	return (
		<form onSubmit={onSync}>
			<p>
				{syncHistory.length
					? __(
							'If you are missing data in your search results or have recently added custom content types to your site, you should run a sync to reflect these changes.',
							'elasticprobe',
						)
					: sprintf(
							/* translators: %s: Index type. ElasticProbe.com or Elasticsearch. */
							__(
								'Run a sync to index your existing content %s. Once syncing finishes, your site is officially supercharged.',
								'elasticprobe',
							),
							isEpio
								? __('on ElasticProbe.com', 'elasticprobe')
								: __('in Elasticsearch', 'elasticprobe'),
						)}
			</p>
			<Panel className="ep-sync-panel">
				<PanelBody className="ep-sync-panel__controls">
					{isSyncing || isComplete ? <Progress /> : null}
					<Controls />
					{syncHistory.length ? <PutMapping /> : null}
				</PanelBody>
				<PanelBody onToggle={onToggleLog} opened={isLogOpen} title="Log">
					<Log />
				</PanelBody>
				{syncHistory.length ? (
					<>
						<PanelBody
							className="ep-sync-panel__advanced"
							initialOpen={false}
							title={__('Advanced options', 'elasticprobe')}
						>
							<Indexables />
							<Objects />
						</PanelBody>
						<PanelBody title={__('Sync history', 'elasticprobe')}>
							<SyncHistory />
						</PanelBody>
					</>
				) : null}
			</Panel>
		</form>
	);
};
