/**
 * Wizard shell: 6-step stepper (upload, mapping, review, rules, preview, apply).
 */

import { useEffect, useState } from '@wordpress/element';
import {
	Card,
	CardHeader,
	CardBody,
	Notice,
	Spinner,
} from '@wordpress/components';
import { __ } from '@wordpress/i18n';

import { getJob } from '../api';
import StepIndicator from './StepIndicator';
import UploadStep from './UploadStep';
import MappingStep from './MappingStep';
import ReviewStep from './ReviewStep';
import RulesStep from './RulesStep';
import PreviewStep from './PreviewStep';
import ApplyStep from './ApplyStep';

export default function Wizard() {
	const [ currentStep, setCurrentStep ] = useState( 0 );
	const [ job, setJob ] = useState( null );
	const [ mapping, setMapping ] = useState( {} );
	const [ preview, setPreview ] = useState( [] );
	const [ supplier, setSupplier ] = useState( null );
	const [ headers, setHeaders ] = useState( [] );
	const [ mappingSource, setMappingSource ] = useState( '' );
	const [ mappingStale, setMappingStale ] = useState( false );
	const [ isResuming, setIsResuming ] = useState( false );
	const [ resumeError, setResumeError ] = useState( '' );

	const stepForJob = ( currentJob ) => {
		const failedStage = currentJob?.totals?.error?.stage;

		if ( 'mapping' === currentJob.status ) {
			return 1;
		}

		if (
			'matching' === currentJob.status ||
			'review' === currentJob.status ||
			'matching' === failedStage
		) {
			return 2;
		}

		if ( 'ready' === currentJob.status || 'preview' === failedStage ) {
			return 4;
		}

		if (
			[ 'applying', 'applied', 'rolled_back' ].includes(
				currentJob.status
			) ||
			[ 'apply', 'rollback' ].includes( failedStage )
		) {
			return 5;
		}

		return 0;
	};

	const putJobInUrl = ( jobId ) => {
		const url = new URL( window.location.href );
		url.searchParams.set( 'job_id', jobId );
		window.history.replaceState( {}, '', url );
	};

	useEffect( () => {
		const jobId = new URLSearchParams( window.location.search ).get(
			'job_id'
		);

		if ( ! jobId ) {
			return;
		}

		setIsResuming( true );
		getJob( jobId )
			.then( ( result ) => {
				setJob( result.job );
				setMapping( result.mapping || {} );
				setPreview( result.preview || [] );
				setSupplier( result.supplier || null );
				setHeaders( result.headers || [] );
				setMappingSource( result.mapping_source || '' );
				setMappingStale( Boolean( result.mapping_stale ) );
				setCurrentStep( stepForJob( result.job ) );
				setIsResuming( false );
			} )
			.catch( ( error ) => {
				setResumeError(
					error?.message ||
						__( 'This import could not be resumed.', 'emberprice' )
				);
				setIsResuming( false );
			} );
		// Resume exactly once from the server-side URL state.
		// eslint-disable-next-line react-hooks/exhaustive-deps
	}, [] );

	const handleUploaded = ( result ) => {
		setJob( result.job );
		setMapping( result.mapping );
		setPreview( result.preview );
		setSupplier( result.supplier || null );
		setHeaders( result.headers || [] );
		setMappingSource( result.mapping_source || '' );
		setMappingStale( Boolean( result.mapping_stale ) );
		putJobInUrl( result.job.id );
		setCurrentStep( 1 );
	};

	const handleMapped = ( result ) => {
		setJob( result.job );
		setCurrentStep( 2 );
	};

	const handleReviewed = ( currentJob ) => {
		setJob( currentJob );
		setCurrentStep( 3 );
	};

	const handleRulesSaved = ( currentJob ) => {
		setJob( currentJob );
		setCurrentStep( 4 );
	};

	const handlePreviewContinue = ( currentJob ) => {
		setJob( currentJob );
		setCurrentStep( 5 );
	};

	const renderStepContent = () => {
		if ( isResuming ) {
			return <Spinner />;
		}

		if ( resumeError ) {
			return (
				<Notice status="error" isDismissible={ false }>
					{ resumeError }
				</Notice>
			);
		}

		if ( 0 === currentStep ) {
			return <UploadStep onUploaded={ handleUploaded } />;
		}

		if ( 1 === currentStep ) {
			return (
				<MappingStep
					job={ job }
					mapping={ mapping }
					preview={ preview }
					headers={ headers }
					initialHasIva={ Boolean( supplier?.settings?.has_iva ) }
					mappingSource={ mappingSource }
					mappingStale={ mappingStale }
					onMapped={ handleMapped }
				/>
			);
		}

		if ( 2 === currentStep ) {
			return <ReviewStep job={ job } onReviewed={ handleReviewed } />;
		}

		if ( 3 === currentStep ) {
			return <RulesStep job={ job } onRulesSaved={ handleRulesSaved } />;
		}

		if ( 4 === currentStep ) {
			return (
				<PreviewStep
					job={ job }
					onBack={ () => setCurrentStep( 2 ) }
					onContinue={ handlePreviewContinue }
				/>
			);
		}

		return <ApplyStep job={ job } />;
	};

	return (
		<Card className="embp-wizard">
			<CardHeader>
				<StepIndicator currentStep={ currentStep } />
			</CardHeader>

			<CardBody>{ renderStepContent() }</CardBody>
		</Card>
	);
}
