/**
 * Wizard step 2: preview parsed rows, confirm the column mapping.
 */

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

import { confirmMapping } from '../api';

const ROLE_OPTIONS = [
	{ label: __( 'Ignore', 'emberprice' ), value: '' },
	{ label: __( 'Code', 'emberprice' ), value: 'code' },
	{ label: __( 'Description', 'emberprice' ), value: 'description' },
	{ label: __( 'Price', 'emberprice' ), value: 'price' },
];

function initialColumnMap( mapping, columnCount ) {
	const initial = {};

	for ( let column = 0; column < columnCount; column++ ) {
		initial[ column ] = mapping[ column ] || '';
	}

	return initial;
}

export default function MappingStep( {
	job,
	mapping,
	preview,
	headers,
	initialHasIva,
	mappingSource,
	mappingStale,
	onMapped,
} ) {
	const columnCount = Math.max(
		headers?.length || 0,
		...preview.map( ( row ) => row.length ),
		0
	);

	const [ columnMap, setColumnMap ] = useState( () =>
		initialColumnMap( mapping, columnCount )
	);
	const [ hasIva, setHasIva ] = useState( initialHasIva );
	const [ isSaving, setIsSaving ] = useState( false );
	const [ error, setError ] = useState( '' );

	const handleRoleChange = ( columnIndex, role ) => {
		setColumnMap( ( previous ) => {
			const next = { ...previous };

			if ( role ) {
				Object.keys( next ).forEach( ( index ) => {
					if (
						String( index ) !== String( columnIndex ) &&
						next[ index ] === role
					) {
						next[ index ] = '';
					}
				} );
			}

			next[ columnIndex ] = role;
			return next;
		} );
	};

	const roles = Object.values( columnMap );
	const canSubmit =
		1 === roles.filter( ( role ) => 'price' === role ).length &&
		1 === roles.filter( ( role ) => 'description' === role ).length &&
		roles.filter( ( role ) => 'code' === role ).length <= 1 &&
		! isSaving;

	const handleSubmit = () => {
		setError( '' );
		setIsSaving( true );

		const cleanedMap = {};
		Object.keys( columnMap ).forEach( ( index ) => {
			if ( columnMap[ index ] ) {
				cleanedMap[ index ] = columnMap[ index ];
			}
		} );

		confirmMapping( job.id, cleanedMap, hasIva )
			.then( ( result ) => {
				setIsSaving( false );
				onMapped( result );
			} )
			.catch( ( mappingError ) => {
				setIsSaving( false );
				setError(
					mappingError?.message ||
						__(
							'Something went wrong saving the mapping.',
							'emberprice'
						)
				);
			} );
	};

	return (
		<div className="embp-mapping-step">
			{ error && (
				<Notice status="error" isDismissible={ false }>
					{ error }
				</Notice>
			) }

			{ 'saved' === mappingSource && (
				<Notice status="info" isDismissible={ false }>
					{ __(
						'A saved mapping was reused because this file has the same column template.',
						'emberprice'
					) }
				</Notice>
			) }

			{ mappingStale && (
				<Notice status="warning" isDismissible={ false }>
					{ __(
						'This supplier changed its column template, so the old saved mapping was not reused. Review every role before continuing.',
						'emberprice'
					) }
				</Notice>
			) }

			<CheckboxControl
				label={ __(
					'Supplier list prices already include VAT',
					'emberprice'
				) }
				checked={ hasIva }
				onChange={ setHasIva }
			/>

			<div className="embp-mapping-table-wrap">
				<table className="embp-mapping-table">
					<thead>
						<tr>
							{ Array.from( { length: columnCount } ).map(
								( _unused, columnIndex ) => (
									<th key={ columnIndex } scope="col">
										<span className="embp-mapping-table__header">
											{ headers?.[ columnIndex ] ||
												sprintf(
													/* translators: %d: column number. */
													__(
														'Column %d',
														'emberprice'
													),
													columnIndex + 1
												) }
										</span>
										<SelectControl
											label={ sprintf(
												/* translators: %d: column number. */
												__(
													'Role for column %d',
													'emberprice'
												),
												columnIndex + 1
											) }
											hideLabelFromVision
											value={
												columnMap[ columnIndex ] || ''
											}
											options={ ROLE_OPTIONS }
											onChange={ ( role ) =>
												handleRoleChange(
													columnIndex,
													role
												)
											}
											__next40pxDefaultSize
											__nextHasNoMarginBottom
										/>
									</th>
								)
							) }
						</tr>
					</thead>
					<tbody>
						{ preview.map( ( row, rowIndex ) => (
							<tr key={ rowIndex }>
								{ Array.from( { length: columnCount } ).map(
									( _unused, columnIndex ) => (
										<td key={ columnIndex }>
											{ row[ columnIndex ] || '' }
										</td>
									)
								) }
							</tr>
						) ) }
					</tbody>
				</table>
			</div>

			<Button
				variant="primary"
				disabled={ ! canSubmit }
				onClick={ handleSubmit }
			>
				{ isSaving
					? __( 'Saving…', 'emberprice' )
					: __( 'Continue', 'emberprice' ) }
			</Button>
		</div>
	);
}
