/**
 * Wizard step 4: the supplier's default pricing rule + per-category
 * overrides (SPEC §5).
 */

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

import {
	listProductCategories,
	listSuppliers,
	updateSupplierRule,
} from '../api';
import RuleFields from './RuleFields';

const DEFAULT_RULE = {
	marginType: 'percentage',
	marginValue: 30,
	vatRate: 21,
	roundingMode: 'none',
	roundingDecimals: 2,
	roundingEnding: 0.99,
	roundingMultiple: 100,
	salePricePolicy: 'keep',
	guardrailsMaxChangePercent: 40,
	guardrailsMode: 'both',
};

function round2( value ) {
	return Math.round( value * 100 ) / 100;
}

// The backend stores ratios (0.30 = 30%); the form shows whole percentages.
function ruleFromApi( rule ) {
	rule = rule || {};
	const rounding = rule.rounding || {};
	const guardrails = rule.guardrails || {};
	const marginType = rule.margin_type || 'percentage';

	return {
		marginType,
		marginValue:
			'percentage' === marginType
				? round2(
						( rule.margin_value ??
							DEFAULT_RULE.marginValue / 100 ) * 100
				  )
				: rule.margin_value ?? 0,
		vatRate: round2(
			( rule.vat_rate ?? DEFAULT_RULE.vatRate / 100 ) * 100
		),
		roundingMode: rounding.mode || 'none',
		roundingDecimals: rounding.decimals ?? 2,
		roundingEnding: rounding.ending ?? 0.99,
		roundingMultiple: rounding.multiple ?? 100,
		salePricePolicy: rule.sale_price_policy || 'keep',
		guardrailsMaxChangePercent: round2(
			( guardrails.max_change_percent ??
				DEFAULT_RULE.guardrailsMaxChangePercent / 100 ) * 100
		),
		guardrailsMode: guardrails.mode || 'both',
	};
}

function ruleToApi( rule ) {
	return {
		margin_type: rule.marginType,
		margin_value:
			'percentage' === rule.marginType
				? rule.marginValue / 100
				: rule.marginValue,
		vat_rate: rule.vatRate / 100,
		rounding: {
			mode: rule.roundingMode,
			decimals: rule.roundingDecimals,
			ending: rule.roundingEnding,
			multiple: rule.roundingMultiple,
		},
		sale_price_policy: rule.salePricePolicy,
		guardrails: {
			max_change_percent: rule.guardrailsMaxChangePercent / 100,
			mode: rule.guardrailsMode,
		},
	};
}

export default function RulesStep( { job, onRulesSaved } ) {
	const [ isLoading, setIsLoading ] = useState( true );
	const [ isSaving, setIsSaving ] = useState( false );
	const [ error, setError ] = useState( '' );
	const [ rule, setRule ] = useState( DEFAULT_RULE );
	const [ overrides, setOverrides ] = useState( [] );
	const [ categories, setCategories ] = useState( [] );

	useEffect( () => {
		Promise.all( [
			listSuppliers(),
			listProductCategories().catch( () => [] ),
		] )
			.then( ( [ suppliers, productCategories ] ) => {
				const supplier = suppliers.find(
					( item ) => String( item.id ) === String( job.supplier_id )
				);
				const defaultRule = supplier?.default_rule || {};

				setRule( ruleFromApi( defaultRule.rule ) );
				setOverrides(
					Object.entries( defaultRule.category_overrides || {} ).map(
						( [ categoryId, overrideRule ] ) => ( {
							categoryId,
							rule: ruleFromApi( overrideRule ),
						} )
					)
				);
				setCategories( productCategories );
				setIsLoading( false );
			} )
			.catch( ( loadError ) => {
				setIsLoading( false );
				setError(
					loadError?.message ||
						__( 'Could not load the pricing rule.', 'emberprice' )
				);
			} );
		// eslint-disable-next-line react-hooks/exhaustive-deps
	}, [ job.supplier_id ] );

	const addOverride = () => {
		setOverrides( ( current ) => [
			...current,
			{
				categoryId: categories[ 0 ] ? String( categories[ 0 ].id ) : '',
				rule: { ...DEFAULT_RULE },
			},
		] );
	};

	const removeOverride = ( index ) => {
		setOverrides( ( current ) =>
			current.filter( ( _item, itemIndex ) => itemIndex !== index )
		);
	};

	const updateOverride = ( index, changes ) => {
		setOverrides( ( current ) =>
			current.map( ( item, itemIndex ) =>
				itemIndex === index ? { ...item, ...changes } : item
			)
		);
	};

	const handleSave = () => {
		setError( '' );

		const categoryIds = overrides
			.map( ( override ) => override.categoryId )
			.filter( Boolean );

		if ( new Set( categoryIds ).size !== categoryIds.length ) {
			setError(
				__( 'Each category can only have one override.', 'emberprice' )
			);
			return;
		}

		setIsSaving( true );

		const categoryOverrides = {};
		overrides.forEach( ( override ) => {
			if ( override.categoryId ) {
				categoryOverrides[ override.categoryId ] = ruleToApi(
					override.rule
				);
			}
		} );

		updateSupplierRule( job.supplier_id, {
			rule: ruleToApi( rule ),
			category_overrides: categoryOverrides,
		} )
			.then( () => {
				setIsSaving( false );
				onRulesSaved( job );
			} )
			.catch( ( saveError ) => {
				setIsSaving( false );
				setError(
					saveError?.message ||
						__( 'Could not save the pricing rule.', 'emberprice' )
				);
			} );
	};

	if ( isLoading ) {
		return <Spinner />;
	}

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

			<h3>{ __( 'Default rule', 'emberprice' ) }</h3>
			<RuleFields value={ rule } onChange={ setRule } />

			<h3>{ __( 'Category overrides', 'emberprice' ) }</h3>

			{ overrides.map( ( override, index ) => (
				<div key={ index } className="embp-rule-override">
					<SelectControl
						label={ __( 'Category', 'emberprice' ) }
						value={ override.categoryId }
						options={ categories.map( ( category ) => ( {
							label: category.name,
							value: String( category.id ),
						} ) ) }
						onChange={ ( categoryId ) =>
							updateOverride( index, { categoryId } )
						}
						__next40pxDefaultSize
						__nextHasNoMarginBottom
					/>
					<RuleFields
						value={ override.rule }
						onChange={ ( newRule ) =>
							updateOverride( index, { rule: newRule } )
						}
					/>
					<Button
						variant="link"
						isDestructive
						onClick={ () => removeOverride( index ) }
					>
						{ __( 'Remove override', 'emberprice' ) }
					</Button>
				</div>
			) ) }

			<Button
				variant="secondary"
				onClick={ addOverride }
				disabled={ 0 === categories.length }
			>
				{ __( 'Add category override', 'emberprice' ) }
			</Button>

			<div className="embp-rules-step__actions">
				<Button
					variant="primary"
					isBusy={ isSaving }
					disabled={ isSaving }
					onClick={ handleSave }
				>
					{ isSaving
						? __( 'Saving…', 'emberprice' )
						: __( 'Save and continue', 'emberprice' ) }
				</Button>
			</div>
		</div>
	);
}
