import { useEffect, useState } from 'react';
import {
	Box,
	Button,
	Card,
	Checkbox,
	Dialog,
	DialogActions,
	DialogContent,
	DialogTitle,
	FormControlLabel,
	InputAdornment,
	MenuItem,
	Radio,
	RadioGroup,
	Select,
	Skeleton,
	TextField,
	Typography,
	Grid,
	Divider,
} from '@mui/material';
import { initialState } from '../redux/features/boxSizes/boxSizesSlice';
import {
	useGetGlobalSettingsQuery,
	useSaveGlobalSettingsMutation,
} from '../redux/Actions/GlobalSettingsAction';
import {
	useGetBoxesQuery,
	useSaveBoxMutation,
	useDeleteBoxMutation,
} from '../redux/Actions/BoxSizesCRUDAction';
import { useDispatch, useSelector } from 'react-redux';
import { setAlert } from '../redux/features/providers/providersSlice';
import { dispatchAlert } from '../redux/Actions/ProvidersAction';
import { useUpdateBoxSizesPlanMutation } from '../redux/Actions/PlanActions';
import { useGetMultiPackageProductsQuery } from '../redux/Actions/WooCommerceDataAction';
import { Spinner, BoxSizeModal, BoxSizesTable, MultiPackageItems } from '../components';

const splitOptions = {
	ml: 4,
	mt: 1,
	mb: 1,
	p: 2,
	maxWidth: 640,
	border: '1px solid',
	borderColor: 'divider',
	borderRadius: 1,
	bgcolor: '#fafafa',
};

const BoxSizes = () => {
	const admin_obj = eniture_rtsq || {};
	const [boxSizesSettings, setBoxSizesSettings] = useState(initialState);
	const [nextSubcribedPackage, setNextSubcribedPackage] = useState('disable');
	const [openBoxModal, setOpenBoxModal] = useState(false);
	const [selectedBox, setSelectedBox] = useState(null);
	const [openDeleteModal, setOpenDeleteModal] = useState(false);
	const [boxToDelete, setBoxToDelete] = useState(null);
	const [isMultiPackageBox, setIsMultiPackageBox] = useState(false);
	const [selectedProduct, setSelectedProduct] = useState(null);

	const { data, isLoading, isFetching } = useGetGlobalSettingsQuery(
		{ url: admin_obj?.eniture_rtsq_rest_url, action: 'get_box_sizes_settings' },
		{ refetchOnMountOrArgChange: true }
	);
	const {
		data: boxesData,
		isLoading: isLoadingBoxes,
		isFetching: isFetchingBoxes,
	} = useGetBoxesQuery(admin_obj?.eniture_rtsq_rest_url);
	const {
		data: multiPackageProductsData,
		isLoading: isLoadingMultiPackageProducts,
		isFetching: isFetchingMultiPackageProducts,
	} = useGetMultiPackageProductsQuery({ url: admin_obj?.eniture_rtsq_rest_url });
	const [saveGlobalSettings, { isLoading: isSaving }] = useSaveGlobalSettingsMutation();
	const [updateBoxSizesPlan, { isLoading: isUpdating }] = useUpdateBoxSizesPlanMutation();
	const [saveBox, { isLoading: isSavingBox }] = useSaveBoxMutation();
	const [deleteBox, { isLoading: isDeletingBox }] = useDeleteBoxMutation();
	const dispatch = useDispatch();
	const { planInfo } = useSelector(state => state.plan);
	const { installedProviders } = useSelector(state => state.providers);
	const fedexSmallActive = (installedProviders || []).some(
		provider => provider?.code === 'FedexSmall' && +provider?.status === 1
	);
	const fedexOneRateBoxes = admin_obj?.fedex_one_rate_boxes || [];

	useEffect(() => {
		if (isLoading || isFetching) return;

		setBoxSizesSettings(prevState => ({
			...prevState,
			...data?.data,
		}));

		const nextSubPckg = data?.data?.status?.nextSubcribedPackage?.nextSubscriptionSCAC;
		const nextToBeChargedStatus = data?.data?.status?.nextSubcribedPackage
			? Number(data?.data?.status?.nextSubcribedPackage?.nextToBeChargedStatus)
			: 0;
		setNextSubcribedPackage(nextToBeChargedStatus ? nextSubPckg : 'disable');
	}, [isLoading, isFetching, data?.data]);

	const handleChange = (name, value) => {
		setBoxSizesSettings(prevState => ({
			...prevState,
			[name]: value,
		}));
	};

	const handleCustomMaxWeightChange = value => {
		const digitsAndDot = value.replace(/[^0-9.]/g, '');
		const [whole, ...decimals] = digitsAndDot.split('.');
		const weight = decimals.length ? `${whole}.${decimals.join('')}` : whole;

		handleChange('package_split_max_weight_custom', weight.slice(0, 5));
	};

	const handlePlanChange = selectedPlan => {
		if (!selectedPlan || selectedPlan === '0') return;

		if (selectedPlan !== 'TR' && planInfo?.name && planInfo?.name?.toLowerCase() === 'trial') {
			dispatch(
				setAlert(
					dispatchAlert(
						true,
						'You must subscribe to the paid plan for the Real-time Shipping Quotes to buy the Add-on',
						'error'
					)
				)
			);

			const nextSubPckg = boxSizesSettings?.status?.nextSubcribedPackage?.nextSubscriptionSCAC;
			const nextToBeChargedStatus = boxSizesSettings?.status?.nextSubcribedPackage
				? Number(boxSizesSettings?.status?.nextSubcribedPackage?.nextToBeChargedStatus)
				: 0;
			setNextSubcribedPackage(nextToBeChargedStatus ? nextSubPckg : 'disable');

			return;
		}

		const payload = {
			action: 'update_box_sizes_plan',
			url: admin_obj?.eniture_rtsq_rest_url,
			selected_plan: selectedPlan,
		};

		dispatch(setAlert(dispatchAlert(true, 'Updating plan...', 'info')));
		updateBoxSizesPlan(payload)
			.unwrap()
			.then(resp => {
				dispatch(
					setAlert(dispatchAlert(true, resp?.message, resp.error ? 'error' : 'success'))
				);

				setBoxSizesSettings(prevState => ({
					...prevState,
					...resp,
				}));
				// if the option is disabled, reset the nextSubcribedPackage state
				if (!resp?.error && selectedPlan === 'disable') setNextSubcribedPackage('disable');
			})
			.catch(error => {
				console.error('Failed to update plan:', error);
				dispatch(setAlert(dispatchAlert(true, 'Failed to update plan', 'error')));
			});
	};

	const handleSubmit = () => {
		const payload = {
			action: 'save_box_sizes_settings',
			url: admin_obj?.eniture_rtsq_rest_url,
			...boxSizesSettings,
		};

		saveGlobalSettings(payload)
			.unwrap()
			.then(resp => {
				dispatch(
					setAlert(dispatchAlert(true, resp?.message, resp.error ? 'error' : 'success'))
				);
			})
			.catch(error => {
				console.error('Failed to save settings:', error);
				dispatch(setAlert(dispatchAlert(true, 'Failed to save settings', 'error')));
			});
	};

	// Box CRUD handlers
	const handleAddNew = () => {
		setSelectedBox(null);
		setIsMultiPackageBox(false);
		setSelectedProduct(null);
		setOpenBoxModal(true);
	};

	const handleEditBox = box => {
		setSelectedBox(box);
		setIsMultiPackageBox(box?.is_multi_item_box == 1);
		setSelectedProduct(box?.product_id ? { id: box.product_id } : null);
		setOpenBoxModal(true);
	};

	const handleDeleteBox = box => {
		setBoxToDelete(box);
		setOpenDeleteModal(true);
	};

	// Multi-package box handlers
	const handleAddMultiPackageBox = product => {
		setSelectedBox(null);
		setIsMultiPackageBox(true);
		setSelectedProduct(product);
		setOpenBoxModal(true);
	};

	const handleEditMultiPackageBox = box => {
		setSelectedBox(box);
		setIsMultiPackageBox(true);
		setSelectedProduct(box?.product_id ? { id: box.product_id } : null);
		setOpenBoxModal(true);
	};

	const handleDeleteMultiPackageBox = box => {
		setBoxToDelete(box);
		setOpenDeleteModal(true);
	};

	const handleSaveBox = formData => {
		const payload = {
			url: admin_obj?.eniture_rtsq_rest_url,
			...formData,
		};

		saveBox(payload)
			.unwrap()
			.then(resp => {
				dispatch(
					setAlert(dispatchAlert(true, resp?.message, resp.error ? 'error' : 'success'))
				);
				if (!resp.error) {
					setOpenBoxModal(false);
					setSelectedBox(null);
				}
			})
			.catch(error => {
				console.error('Failed to save box:', error);
				dispatch(setAlert(dispatchAlert(true, 'Failed to save box', 'error')));
			});
	};

	const handleConfirmDelete = () => {
		if (!boxToDelete) return;

		const payload = {
			url: admin_obj?.eniture_rtsq_rest_url,
			id: boxToDelete.id,
		};

		deleteBox(payload)
			.unwrap()
			.then(resp => {
				dispatch(
					setAlert(dispatchAlert(true, resp?.message, resp.error ? 'error' : 'success'))
				);
				if (!resp.error) {
					setOpenDeleteModal(false);
					setBoxToDelete(null);
				}
			})
			.catch(error => {
				console.error('Failed to delete box:', error);
				dispatch(setAlert(dispatchAlert(true, 'Failed to delete box', 'error')));
			});
	};

	const formatPlanInfo = plan => {
		const hits =
			plan?.pHits && Number(plan.pHits)
				? parseInt(plan.pHits, 10).toLocaleString()
				: plan?.pHits || 0;

		return `${hits}/${plan?.pPeriod?.toLocaleLowerCase().slice(0, 2)} ($${plan?.pCost})`;
	};

	const formatCurrentPlan = () => {
		const planStatus = boxSizesSettings?.status || null;
		const subPkg = planStatus?.subscribedPackage || null;
		if (!planStatus || !subPkg) return 'Not subscribed';

		if (isPlanExpired()) return 'Your current subscription is expired.';

		const pkgHits =
			subPkg?.packageHits === 'Unlimited'
				? 'Unlimited'
				: parseInt(subPkg?.packageHits || 0, 10).toLocaleString();
		const planInfo = `${pkgHits}/${
			subPkg?.packageDuration?.toLowerCase()?.slice(0, 2) || 0
		} ($${subPkg?.packageCost || 0})`;
		const startDate = planStatus?.subscriptionInfo?.subscriptionTime
			? getFormattedDate(planStatus?.subscriptionInfo?.subscriptionTime)
			: 'N/A';
		const endDate = planStatus?.subscriptionInfo?.expiryTime
			? getFormattedDate(planStatus?.subscriptionInfo?.expiryTime)
			: 'N/A';

		let markup = '';
		for (let i = 0; i < 3; i++) {
			markup += `<Typography variant='body2'>${
				i === 0
					? `${planInfo}`
					: i === 1
					? `Start date: ${startDate}`
					: `End date: ${endDate}`
			}</Typography> <br />`;
		}

		return markup;
	};

	const getFormattedDate = dateStr => {
		const date = new Date(dateStr.replace(' ', 'T'));
		const options = { month: 'short', day: 'numeric', year: 'numeric' };
		let formatted = date.toLocaleDateString('en-US', options);
		formatted = formatted.replace(',', '');

		return formatted;
	};

	const formatCurrentUsage = () => {
		const planStatus = boxSizesSettings?.status || null;
		if (!planStatus || isPlanExpired()) return 'Not available';

		const subPkgHits = planStatus?.subscribedPackageHitsStatus || {};
		const consumedHitsPrcent = subPkgHits?.consumedHitsPrcent
			? subPkgHits?.consumedHitsPrcent + '%'
			: '';
		return `${subPkgHits?.consumedHits || 0}/${
			subPkgHits?.packageHits || 0
		} ${consumedHitsPrcent}`;
	};

	const isPlanExpired = () => {
		const planStatus = boxSizesSettings?.status || null;
		const expiryDate = new Date(planStatus?.subscriptionInfo?.expiryTime.replace(' ', 'T'));
		expiryDate.setHours(23, 59, 59, 999);

		const planExpired =
			planStatus &&
			(!Number(planStatus?.subscriptionInfo?.subscriptionStatus) || Date.now() > expiryDate);

		return planExpired;
	};

	return (
		<>
			{isLoading || isFetching ? (
				<Skeleton variant='rectangular' animation='wave' height={500} />
			) : (
				<>
					<Card variant='elevation' sx={{ p: 2, minWidth: 600 }} component={Box}>
					<Typography variant='h6' fontWeight='bold' mb={2}>
						Box Sizes
					</Typography>

					<Typography
						variant='body2'
						color='textSecondary'
						mb={3}>
						The Box Sizes feature calculates the optimal packaging solution based on your
						standard box sizes. The solution is available graphically to assist order
						fulfillment. The next subscription begins when the current one expires or is
						depleted, which ever comes first. Refer to the{' '}
						<a href="https://eniture.com/woocommerce-real-time-shipping-quotes/" target="_blank" rel="noopener noreferrer">User's Guide</a>{' '}
						for more detailed information.
					</Typography>

					<Box mb={2}>
						{/* Auto-renew */}
						<Typography variant='body1' fontWeight='bold' mb={1}>
							Auto-renew
						</Typography>
						<Select
							size='small'
							title='Auto-renew'
							defaultValue='disable'
							value={nextSubcribedPackage || 'disable'}
							onChange={e => {
								setNextSubcribedPackage(e.target.value);
								handlePlanChange(e.target.value);
							}}
							sx={{ minWidth: '25vw', width: '25vw' }}
							disabled={isSaving || isUpdating}>
							<MenuItem value='disable'>Disable (default)</MenuItem>
							{Number(boxSizesSettings?.trialAvailable) && (
								<MenuItem value='TR'>Trial (100/15 days) (Free)</MenuItem>
							)}

							{/* Plans list */}
							{boxSizesSettings?.ListOfPackages?.Info?.map((plan, index) => (
								<MenuItem key={index} value={plan.pSCAC}>
									{formatPlanInfo(plan)}
								</MenuItem>
							))}
						</Select>

						{/* Plan info */}
						<Box my={2}>
							<Typography variant='body1' fontWeight='bold'>
								Current plan
							</Typography>

							<Typography
								variant='body2'
								dangerouslySetInnerHTML={{ __html: formatCurrentPlan() }}
							/>
						</Box>

						{/* Usage info */}
						<Box my={2}>
							<Typography variant='body1' fontWeight='bold'>
								Current usage
							</Typography>
							<Typography variant='body2'>{formatCurrentUsage()}</Typography>
						</Box>

						<FormControlLabel
							control={<Checkbox />}
							label='Suspend use'
							title='Suspend use'
							checked={boxSizesSettings?.eniture_suspend_box_sizes_use || false}
							onChange={e => handleChange('eniture_suspend_box_sizes_use', e.target.checked)}
						/>
					</Box>

					<Divider />

					{/* Optimization mode */}
					<Grid container spacing={2} mb={2} mt={2}>
						<Grid item xs={12} md={4}>
							<Typography variant='body1' fontWeight='bold'>
								Optimization mode
							</Typography>
						</Grid>

						<Grid item xs={12} md={8}>
							<RadioGroup
								aria-labelledby='optimization-mode-label'
								name='optimization-mode'
								defaultValue='maximize_space'
								value={boxSizesSettings?.eniture_optimization_mode || 'maximize_space'}
								onChange={e => handleChange('eniture_optimization_mode', e.target.value)}>
								<FormControlLabel
									value='maximize_space'
									control={<Radio />}
									label='Maximize space utilization'
									title='Maximize space utilization'
								/>
								<Typography
									variant='body2'
									color='textSecondary'
									sx={{ ml: 4, mb: 1 }}>
									Prioritizes the choice of boxes to minimize the amount of unused space.
								</Typography>

								<FormControlLabel
									value='minimize_packages'
									control={<Radio />}
									label='Minimize the number of packages'
									title='Minimize the number of packages'
								/>
								<Typography
									variant='body2'
									color='textSecondary'
									sx={{ ml: 4, mb: 1 }}>
									Use the fewest number of boxes for the packaging solution.
								</Typography>
							</RadioGroup>
						</Grid>
					</Grid>

					<Divider />

					{/* Packaging method */}
					<Grid container spacing={2} mb={2} mt={2}>
						<Grid item xs={12} md={4}>
							<Typography variant='body1' fontWeight='bold'>
								Packaging method when standard box sizes is disabled
							</Typography>
						</Grid>

						<Grid item xs={12} md={8}>
							<RadioGroup
								aria-labelledby='packaging-method-label'
								name='packaging-method'
								defaultValue='ship_alone'
								value={boxSizesSettings?.package_rating_method || 'ship_alone'}
								onChange={e => handleChange('package_rating_method', e.target.value)}>
								<FormControlLabel
									value='ship_alone'
									control={<Radio />}
									label='Quote each item as shipping as its own package'
								/>
								<FormControlLabel
									value='ship_combine_and_alone'
									control={<Radio />}
									label='Combine the weight of all items without dimensions and quote them as one package while quoting each item with dimensions as shipping as its own package'
								/>
								<FormControlLabel
									value='split_combined_weight'
									control={<Radio />}
									label='Split the combined weight into packages'
								/>

								{boxSizesSettings?.package_rating_method ===
									'split_combined_weight' && (
									<Box sx={splitOptions}>
										<Typography variant='body2' fontWeight='bold'>
											Maximum package weight
										</Typography>

										<RadioGroup
											row
											aria-labelledby='split-max-weight-label'
											name='split-max-weight'
											value={
												boxSizesSettings?.package_split_max_weight || '70'
											}
											onChange={e =>
												handleChange(
													'package_split_max_weight',
													e.target.value
												)
											}>
											<FormControlLabel
												value='70'
												control={<Radio size='small' />}
												label='70 LB'
											/>
											<FormControlLabel
												value='150'
												control={<Radio size='small' />}
												label='150 LB'
											/>
											<FormControlLabel
												value='custom'
												control={<Radio size='small' />}
												label='Custom'
											/>
										</RadioGroup>

										{boxSizesSettings?.package_split_max_weight ===
											'custom' && (
											<TextField
												id='en-rtsq-split-custom-weight'
												size='small'
												title='Custom maximum package weight'
												placeholder='Weight'
												sx={{ mt: 1, width: 140 }}
												InputProps={{
													endAdornment: (
														<InputAdornment position='end'>
															LB
														</InputAdornment>
													),
												}}
												value={
													boxSizesSettings?.package_split_max_weight_custom ||
													''
												}
												onChange={e =>
													handleCustomMaxWeightChange(e.target.value)
												}
											/>
										)}

										<Typography variant='body2' fontWeight='bold' mt={2}>
											Weight distribution
										</Typography>

										<RadioGroup
											aria-labelledby='split-weight-distribution-label'
											name='split-weight-distribution'
											value={
												boxSizesSettings?.package_split_weight_distribution ||
												'maximize'
											}
											onChange={e =>
												handleChange(
													'package_split_weight_distribution',
													e.target.value
												)
											}>
											<FormControlLabel
												value='equal'
												control={<Radio size='small' />}
												label='Distribute the total weight evenly among packages'
											/>
											<FormControlLabel
												value='maximize'
												control={<Radio size='small' />}
												label='Fill each package to its maximum before creating the next package'
											/>
										</RadioGroup>
									</Box>
								)}
							</RadioGroup>
						</Grid>
					</Grid>

					<Box mt={2} display='flex' justifyContent='flex-end'>
						<Button
							title='Save'
							sx={{ textTransform: 'capitalize' }}
							disabled={isSaving}
							onClick={handleSubmit}
							variant='contained'>
							{isSaving ? <Spinner size={25} /> : 'Save'}
						</Button>
					</Box>
			</Card>

			<Card variant='elevation' sx={{ p: 2, minWidth: 600, mt: 3 }} component={Box}>
					{/* Box Sizes CRUD Section */}
					<Box>
					<Box display='flex' justifyContent='flex-end' mb={2}>
						<Button
							variant='contained'
							color='primary'
							onClick={handleAddNew}
							sx={{ textTransform: 'capitalize' }}>
							Add Box
						</Button>
					</Box>

					<BoxSizesTable
						boxes={(boxesData?.data || []).filter(box => box.is_multi_item_box != 1)}
						onEdit={handleEditBox}
						onDelete={handleDeleteBox}
						fedexOneRateBoxes={fedexOneRateBoxes}
						isLoading={isLoadingBoxes || isFetchingBoxes}
					/>
				</Box>

				<Divider sx={{ my: 3 }} />

				{/* Multi-package Items Section */}
				<MultiPackageItems
					products={multiPackageProductsData?.data || []}
					boxes={boxesData?.data || []}
					onAddBox={handleAddMultiPackageBox}
					onEditBox={handleEditMultiPackageBox}
					onDeleteBox={handleDeleteMultiPackageBox}
					isLoading={isLoadingMultiPackageProducts || isFetchingMultiPackageProducts}
				/>

			</Card>

			{/* Box Size Modal */}
			<BoxSizeModal
				open={openBoxModal}
				onClose={() => {
					setOpenBoxModal(false);
					setSelectedBox(null);
					setIsMultiPackageBox(false);
					setSelectedProduct(null);
				}}
				onSave={handleSaveBox}
				boxData={selectedBox}
				isSaving={isSavingBox}
				isMultiPackageBox={isMultiPackageBox}
				selectedProduct={selectedProduct}
				fedexOneRateBoxes={fedexOneRateBoxes}
				showFedexOneRateBoxes={fedexSmallActive}
			/>

			{/* Delete Confirmation Modal */}
			<Dialog
				open={openDeleteModal}
				onClose={() => {
					setOpenDeleteModal(false);
					setBoxToDelete(null);
				}}
				maxWidth='sm'
				fullWidth>
				<DialogTitle>
					Delete {boxToDelete?.is_multi_package == 1 ? 'Multi-Package Item' : 'Box Size'}
				</DialogTitle>
				<DialogContent>
					<Typography>
						Are you sure you want to delete "{boxToDelete?.nickname}"? This action cannot be undone.
					</Typography>
				</DialogContent>
				<DialogActions>
					<Button
						onClick={() => {
							setOpenDeleteModal(false);
							setBoxToDelete(null);
						}}
						disabled={isDeletingBox}>
						Cancel
					</Button>
					<Button
						onClick={handleConfirmDelete}
						variant='contained'
						color='error'
						disabled={isDeletingBox}>
						{isDeletingBox ? <Spinner size={20} /> : 'Delete'}
					</Button>
				</DialogActions>
			</Dialog>
			</>
		)}
		</>
	);
};

export default BoxSizes;
