/**
 * Wizard step 5: compute the price preview (RuleEngine + Guardrails), show
 * the diff table, and export it to CSV.
 */

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

import { exportJob, getJobRows, previewJob } from '../api';

export default function PreviewStep( { job, onBack, onContinue } ) {
	const [ isComputing, setIsComputing ] = useState( true );
	const [ previewReady, setPreviewReady ] = useState( false );
	const [ error, setError ] = useState( '' );
	const [ rowsData, setRowsData ] = useState( {
		rows: [],
		total: 0,
		per_page: 50,
	} );
	const [ page, setPage ] = useState( 1 );
	const [ isLoadingRows, setIsLoadingRows ] = useState( false );
	const [ isExporting, setIsExporting ] = useState( false );

	useEffect( () => {
		setIsComputing( true );
		previewJob( job.id )
			.then( () => {
				setPreviewReady( true );
				setIsComputing( false );
			} )
			.catch( ( previewError ) => {
				setIsComputing( false );
				setError(
					previewError?.message ||
						__(
							'Could not compute the price preview.',
							'emberprice'
						)
				);
			} );
		// eslint-disable-next-line react-hooks/exhaustive-deps
	}, [ job.id ] );

	useEffect( () => {
		if ( isComputing || ! previewReady ) {
			return;
		}

		setIsLoadingRows( true );
		getJobRows( job.id, { status: '', page } )
			.then( ( result ) => {
				setIsLoadingRows( false );
				setRowsData( result );
			} )
			.catch( ( loadError ) => {
				setIsLoadingRows( false );
				setError(
					loadError?.message ||
						__( 'Could not load rows.', 'emberprice' )
				);
			} );
	}, [ job.id, page, isComputing, previewReady ] );

	const handleExport = () => {
		setIsExporting( true );

		exportJob( job.id )
			.then( ( result ) => {
				setIsExporting( false );

				const blob = new Blob( [ result.csv ], {
					type: 'text/csv;charset=utf-8;',
				} );
				const url = URL.createObjectURL( blob );
				const link = document.createElement( 'a' );
				link.href = url;
				link.download = result.filename;
				document.body.appendChild( link );
				link.click();
				document.body.removeChild( link );
				URL.revokeObjectURL( url );
			} )
			.catch( ( exportError ) => {
				setIsExporting( false );
				setError(
					exportError?.message ||
						__( 'Could not export the CSV.', 'emberprice' )
				);
			} );
	};

	if ( isComputing ) {
		return (
			<div className="embp-preview-step">
				<p>{ __( 'Computing the price preview…', 'emberprice' ) }</p>
				<Spinner />
			</div>
		);
	}

	const pricedRows = rowsData.rows.filter(
		( row ) => null !== row.new_price
	);
	const totalPages = Math.max(
		1,
		Math.ceil( rowsData.total / rowsData.per_page )
	);

	return (
		<div className="embp-preview-step">
			{ error && (
				<Notice
					status="error"
					isDismissible
					onRemove={ () => setError( '' ) }
				>
					{ error }
				</Notice>
			) }

			{ ! previewReady && (
				<Button variant="secondary" onClick={ onBack }>
					{ __( 'Back to review', 'emberprice' ) }
				</Button>
			) }

			<Button
				variant="secondary"
				isBusy={ isExporting }
				disabled={ isExporting || ! previewReady }
				onClick={ handleExport }
			>
				{ __( 'Export CSV', 'emberprice' ) }
			</Button>

			{ isLoadingRows ? (
				<Spinner />
			) : (
				<div className="embp-preview-table-wrap">
					<table className="embp-preview-table">
						<thead>
							<tr>
								<th scope="col">
									{ __( 'Product', 'emberprice' ) }
								</th>
								<th scope="col">
									{ __( 'Old price', 'emberprice' ) }
								</th>
								<th scope="col">
									{ __( 'New price', 'emberprice' ) }
								</th>
								<th scope="col">
									{ __( 'Change', 'emberprice' ) }
								</th>
								<th scope="col">
									{ __( 'Flags', 'emberprice' ) }
								</th>
								<th scope="col">
									{ __( 'Status', 'emberprice' ) }
								</th>
							</tr>
						</thead>
						<tbody>
							{ pricedRows.map( ( row ) => {
								const changePercent = row.old_price
									? ( ( row.new_price - row.old_price ) /
											row.old_price ) *
									  100
									: null;

								return (
									<tr key={ row.id }>
										<td>
											{ row.matched_product
												? row.matched_product.name
												: row.parsed?.name }
										</td>
										<td>{ row.old_price?.toFixed( 2 ) }</td>
										<td>{ row.new_price?.toFixed( 2 ) }</td>
										<td>
											{ null !== changePercent
												? `${ changePercent.toFixed(
														2
												  ) }%`
												: '—' }
										</td>
										<td>
											{ row.flags && row.flags.length > 0
												? row.flags.join( ', ' )
												: '—' }
										</td>
										<td>{ row.status }</td>
									</tr>
								);
							} ) }
						</tbody>
					</table>
					{ 0 === pricedRows.length && (
						<p>
							{ __(
								'No priced rows on this page. Try another page, or go back to review more rows.',
								'emberprice'
							) }
						</p>
					) }
				</div>
			) }

			<div className="embp-preview-pagination">
				<Button
					variant="secondary"
					disabled={ page <= 1 }
					onClick={ () => setPage( ( current ) => current - 1 ) }
				>
					{ __( 'Previous', 'emberprice' ) }
				</Button>
				<span>
					{ sprintf(
						/* translators: 1: current page, 2: total pages */
						__( 'Page %1$d of %2$d', 'emberprice' ),
						page,
						totalPages
					) }
				</span>
				<Button
					variant="secondary"
					disabled={ page >= totalPages }
					onClick={ () => setPage( ( current ) => current + 1 ) }
				>
					{ __( 'Next', 'emberprice' ) }
				</Button>
			</div>

			<Button
				variant="primary"
				disabled={ ! previewReady }
				onClick={ () => onContinue( job ) }
			>
				{ __( 'Continue', 'emberprice' ) }
			</Button>
		</div>
	);
}
