import { LabelPurchaseContext } from './context';
import { getCurrentOrderItems } from 'utils';
import CurrencyFactory from '@woocommerce/currency';
import {
	useEssentialDetails,
	useAccountState,
	useTotalWeight,
	useShipmentState,
	useRatesState,
	usePackageState,
	useHazmatState,
	useCustomsState,
	useLabelsState,
} from 'components/label-purchase/hooks';

interface Props {
	children: React.JSX.Element | React.JSX.Element[];
	orderId: number;
	nextDesign?: boolean;
}

export const LabelPurchaseContextProvider = ( {
	children,
	nextDesign = false,
}: Props ): React.JSX.Element => {
	const orderItems = getCurrentOrderItems();
	const storeCurrency = CurrencyFactory();

	const {
		shipments,
		setShipments,
		getShipmentWeight,
		resetSelections,
		selections,
		setSelection,
		currentShipmentId,
		setCurrentShipmentId,
		getShipmentItems,
		getSelectionItems,
		setShipmentOrigin,
		getShipmentOrigin,
		getShipmentDestination,
		revertLabelShipmentIdsToUpdate,
		labelShipmentIdsToUpdate,
		getShipmentPurchaseOrigin,
		hasVariations,
		hasMultipleShipments,
		isExtraLabelPurchaseValid,
		resetShipmentAndSelection,
		isShipmentAutogeneratedFromLabel,
		setCurrentShipmentDate,
		getCurrentShipmentDate,
		getCurrentShipmentIsReturn,
		getCurrentShipmentParentId,
		setReturnShipments,
		returnShipments,
		isReturnShipment,
		getShipmentType,
	} = useShipmentState();

	const { getShipmentTotalWeight, setShipmentTotalWeight } = useTotalWeight( {
		shipmentWeight: getShipmentWeight(),
		currentShipmentId,
	} );

	const totalWeight = getShipmentTotalWeight();

	const {
		getShipmentHazmat,
		setShipmentHazmat,
		applyHazmatToPackage,
		isHazmatSpecified,
	} = useHazmatState( currentShipmentId );

	const packages = usePackageState(
		currentShipmentId,
		shipments,
		totalWeight,
		returnShipments,
		setShipmentTotalWeight
	);

	const customs = useCustomsState(
		currentShipmentId,
		shipments,
		selections,
		getShipmentItems,
		getSelectionItems,
		getShipmentOrigin,
		getShipmentDestination
	);

	const {
		selectedRates,
		selectRates,
		selectRate,
		getSelectedRate,
		removeSelectedRate,
		isFetching,
		userRateFetchNonce,
		updateRates,
		fetchRates,
		resetRates,
		sortRates,
		errors,
		setErrors,
		matchAndSelectRate,
		availableRates,
		preselectRateBasedOnLastSelections,
		getSelectedRateOptions,
		selectedRateOptions,
		selectRateOption,
	} = useRatesState( {
		currentShipmentId,
		currentPackageTab: packages.currentPackageTab,
		applyHazmatToPackage,
		getPackageForRequest: packages.getPackageForRequest,
		totalWeight,
		customs,
		getShipmentOrigin,
		getCurrentShipmentDate,
		getCurrentShipmentIsReturn,
	} );

	const labels = useLabelsState( {
		currentShipmentId,
		totalWeight,
		getPackageForRequest: packages.getPackageForRequest,
		getShipmentItems,
		getSelectionItems,
		getShipmentHazmat,
		isFetching,
		userRateFetchNonce,
		resetRates,
		getShipmentOrigin,
		getCurrentShipmentIsReturn,
		getCurrentShipmentParentId,
		customs,
		shipments,
		returnShipments,
		applyHazmatToPackage,
		getSelectedRateOptions,
		getCurrentShipmentDate,
	} );

	const account = useAccountState();
	const essentialDetails = useEssentialDetails();

	const value = {
		orderItems,
		shipment: {
			shipments,
			setShipments,
			selections,
			setSelection,
			resetSelections,
			currentShipmentId,
			getShipmentItems,
			getSelectionItems,
			setShipmentOrigin,
			getShipmentOrigin,
			getShipmentDestination,
			getShipmentType,
			setCurrentShipmentId,
			revertLabelShipmentIdsToUpdate,
			labelShipmentIdsToUpdate,
			getShipmentPurchaseOrigin,
			hasVariations,
			hasMultipleShipments,
			isExtraLabelPurchaseValid,
			resetShipmentAndSelection,
			isShipmentAutogeneratedFromLabel,
			setCurrentShipmentDate,
			getCurrentShipmentDate,
			getCurrentShipmentIsReturn,
			getCurrentShipmentParentId,
			returnShipments,
			setReturnShipments,
			isReturnShipment,
		},
		hazmat: {
			getShipmentHazmat,
			setShipmentHazmat,
			applyHazmatToPackage,
			isHazmatSpecified,
		},
		packages,
		storeCurrency,
		rates: {
			selectedRates,
			selectRates,
			selectRate,
			getSelectedRate,
			removeSelectedRate,
			isFetching,
			userRateFetchNonce,
			fetchRates,
			resetRates,
			errors,
			setErrors,
			updateRates,
			sortRates,
			matchAndSelectRate,
			availableRates,
			preselectRateBasedOnLastSelections,
			selectedRateOptions,
			selectRateOption,
			getSelectedRateOptions,
		},
		weight: {
			getShipmentWeight,
			getShipmentTotalWeight,
			setShipmentTotalWeight,
		},
		customs,
		labels,
		account,
		essentialDetails,
		nextDesign,
	};

	return (
		<LabelPurchaseContext.Provider value={ value }>
			{ children }
		</LabelPurchaseContext.Provider>
	);
};
