/**
 * Wizard step 6: apply the previewed prices (snapshot + batched write via
 * Action Scheduler), then hand off to the History screen for rollback --
 * rollback already lives there (HistoryScreen.js), not duplicated here.
 */

import { useEffect, useState } from '@wordpress/element';
import { Button, Notice } from '@wordpress/components';
import { __, sprintf } from '@wordpress/i18n';

import { applyJob, getJobProgress } from '../api';

const POLL_INTERVAL_MS = 1500;

export default function ApplyStep( { job } ) {
	const initialStage = [
		'applying',
		'applied',
		'failed',
		'rolled_back',
	].includes( job.status )
		? job.status
		: 'idle';
	const [ stage, setStage ] = useState( initialStage );
	const [ progress, setProgress ] = useState( null );
	const [ error, setError ] = useState( '' );
	const [ pollToken, setPollToken ] = useState( 0 );

	useEffect( () => {
		if ( 'applying' !== stage ) {
			return undefined;
		}

		let cancelled = false;
		let timerId = null;

		const poll = () => {
			getJobProgress( job.id )
				.then( ( result ) => {
					if ( cancelled ) {
						return;
					}

					setProgress( result );

					if ( [ 'applied', 'failed' ].includes( result.stage ) ) {
						setStage( result.stage );
						return;
					}

					if ( ! result.stalled ) {
						timerId = setTimeout( poll, POLL_INTERVAL_MS );
					}
				} )
				.catch( ( progressError ) => {
					if ( ! cancelled ) {
						setStage( 'idle' );
						setError(
							progressError?.message ||
								__(
									'Could not read application progress.',
									'emberprice'
								)
						);
					}
				} );
		};

		poll();

		return () => {
			cancelled = true;
			if ( timerId ) {
				clearTimeout( timerId );
			}
		};
	}, [ job.id, stage, pollToken ] );

	const handleApply = () => {
		setError( '' );
		setStage( 'applying' );

		applyJob( job.id )
			.then( () => setStage( 'applying' ) )
			.catch( ( applyError ) => {
				setStage( 'idle' );
				setError(
					applyError?.message ||
						__( 'Could not apply this job.', 'emberprice' )
				);
			} );
	};

	const handleRetry = () => {
		setError( '' );
		setProgress( null );
		applyJob( job.id, true )
			.then( () => {
				setStage( 'applying' );
				setPollToken( ( current ) => current + 1 );
			} )
			.catch( ( applyError ) => {
				setError(
					applyError?.message ||
						__( 'Could not retry this job.', 'emberprice' )
				);
			} );
	};

	if ( 'applied' === stage ) {
		const done = progress?.done ?? 0;
		const failed = progress?.failed ?? 0;

		return (
			<div className="embp-apply-step">
				<Notice status="success" isDismissible={ false }>
					{ failed > 0
						? sprintf(
								/* translators: 1: rows applied successfully, 2: rows that failed */
								__(
									'Applied %1$d row(s), %2$d failed -- see the History screen for details.',
									'emberprice'
								),
								done - failed,
								failed
						  )
						: sprintf(
								/* translators: %d: rows applied */
								__(
									'Applied %d row(s). Prices are live.',
									'emberprice'
								),
								done
						  ) }
				</Notice>
				<p>
					{ __(
						'A snapshot was taken before this ran, so it can be undone from the History screen.',
						'emberprice'
					) }
				</p>
				<Button
					variant="primary"
					href="admin.php?page=emberprice&view=history"
				>
					{ __( 'Go to History', 'emberprice' ) }
				</Button>
			</div>
		);
	}

	if ( 'applying' === stage ) {
		const done = progress?.done ?? 0;
		const total = progress?.total ?? 0;
		const percent = total > 0 ? Math.round( ( done / total ) * 100 ) : 0;

		return (
			<div className="embp-apply-step">
				{ progress?.stalled && (
					<Notice status="error" isDismissible={ false }>
						<p>{ progress.message }</p>
						<Button variant="secondary" onClick={ handleRetry }>
							{ __( 'Retry application', 'emberprice' ) }
						</Button>
					</Notice>
				) }
				<p>{ __( 'Applying prices…', 'emberprice' ) }</p>
				<div
					className="embp-progress"
					role="progressbar"
					aria-valuemin="0"
					aria-valuemax={ total }
					aria-valuenow={ done }
					aria-label={ __(
						'Price application progress',
						'emberprice'
					) }
				>
					<div
						className="embp-progress__bar"
						style={ { width: `${ percent }%` } }
					/>
					<span className="embp-progress__label">
						{ sprintf(
							/* translators: 1: rows applied so far, 2: total rows */
							__( '%1$d / %2$d', 'emberprice' ),
							done,
							total
						) }
					</span>
				</div>
			</div>
		);
	}

	if ( 'failed' === stage ) {
		return (
			<div className="embp-apply-step">
				<Notice status="error" isDismissible={ false }>
					{ progress?.error?.message ||
						job?.totals?.error?.message ||
						__(
							'The job stopped with errors. Prices may have been partially updated.',
							'emberprice'
						) }
				</Notice>
				<p>
					{ __(
						'Use History to inspect the failed rows and roll back the snapshot before correcting the import.',
						'emberprice'
					) }
				</p>
				<Button
					variant="primary"
					href="admin.php?page=emberprice&view=history"
				>
					{ __( 'Go to History', 'emberprice' ) }
				</Button>
			</div>
		);
	}

	if ( 'rolled_back' === stage ) {
		return (
			<Notice status="info" isDismissible={ false }>
				{ __(
					'This import has already been rolled back.',
					'emberprice'
				) }
			</Notice>
		);
	}

	return (
		<div className="embp-apply-step">
			{ error && (
				<Notice
					status="error"
					isDismissible
					onRemove={ () => setError( '' ) }
				>
					{ error }
				</Notice>
			) }
			<p>
				{ __(
					'This writes the previewed prices to your store. A snapshot is taken first, so the whole import can be rolled back afterward from the History screen.',
					'emberprice'
				) }
			</p>
			<Button variant="primary" onClick={ handleApply }>
				{ __( 'Apply now', 'emberprice' ) }
			</Button>
		</div>
	);
}
