import { Spinner } from '@woocommerce/components';
import {
	Button,
	Card,
	CardBody,
	Flex,
	FlexItem,
	Notice,
	TextControl,
} from '@wordpress/components';
import { close } from '@wordpress/icons';
import { __ } from '@wordpress/i18n';
import { useCallback, useMemo, useState } from 'react';
import { ValidationResponse, CheckoutApiError } from '../../../types';
import { sanitizeDiscountCode } from '../utils/sanitizeDiscountCode';
import { formatCurrency } from '../../../shared/utils';
import { CheckoutErrorNotice } from '../../../shared/components';

interface PriceSectionProps {
	validationResult: ValidationResponse | null;
	isValidating: boolean;
	fullAmount: number;
	initialExtras: string[];
	selectedExtras?: string[];
	discountCode: string;
	createOrderError: string | null;

	setDiscountCode: (code: string) => void;
	onApplyDiscount: (currentExtras: string[], code: string) => void;
	onCancelDiscount: (currentExtras: string[]) => void;
}

const PriceSection = ({
	validationResult,
	isValidating,
	fullAmount,
	initialExtras,
	selectedExtras = [],
	onApplyDiscount,
	onCancelDiscount,
	createOrderError,
	discountCode,
	setDiscountCode,
}: PriceSectionProps) => {
	const [showDiscountInput, setShowDiscountInput] = useState(false);

	const handleDiscountChange = useCallback((value: string | undefined) => {
		setDiscountCode(sanitizeDiscountCode(value ?? ''));
	}, []);

	const handleApplyDiscount = useCallback(() => {
		const sanitized = sanitizeDiscountCode(discountCode);
		if (sanitized)
			onApplyDiscount(initialExtras.concat(selectedExtras), sanitized);
	}, [discountCode, initialExtras, selectedExtras, onApplyDiscount]);

	const handleCloseDiscountInput = useCallback(() => {
		setShowDiscountInput(false);
		setDiscountCode('');
	}, []);

	const handleRemoveDiscount = useCallback(() => {
		setShowDiscountInput(false);
		setDiscountCode('');
		onCancelDiscount(initialExtras.concat(selectedExtras));
	}, [initialExtras, selectedExtras, onCancelDiscount]);

	const hasAppliedDiscount =
		validationResult?.success &&
		(validationResult?.price?.discount ?? 0) > 0;

	/* Price breakdown */
	const validationBreakdown = useMemo(() => {
		const basePrices =
			validationResult?.price?.breakdown?.filter((b) =>
				b.name?.startsWith('Base Price')
			) ?? [];
		const subTotal = validationResult?.price?.net ?? 0;
		const ddpItems =
			validationResult?.price?.breakdown?.filter((b) =>
				b.name.startsWith('DDP')
			) || [];
		const dutyAndTaxItems = ddpItems.filter(
			(b) => b.name.includes('DDP Duty') || b.name.includes('DDP Tax')
		);
		const otherDdpItems = ddpItems.filter(
			(b) => !b.name.includes('DDP Duty') && !b.name.includes('DDP Tax')
		);
		const dutyAndTaxTotal = dutyAndTaxItems.reduce(
			(sum, item) => sum + item.amount,
			0
		);
		return {
			basePrices,
			subTotal,
			dutyAndTaxItems,
			otherDdpItems,
			dutyAndTaxTotal,
		};
	}, [validationResult]);

	return (
		<Flex direction="column" gap={2}>
			{validationResult?.warnings?.length > 0 && (
				<Notice status="warning" isDismissible={false}>
					{validationResult?.warnings[0].title}
				</Notice>
			)}
			<h3 style={{ margin: 0, fontSize: '1rem', fontWeight: 600 }}>
				{__('Price', 'parcel2go-shipping')}
			</h3>

			{hasAppliedDiscount ? (
				<Flex
					gap={2}
					align="center"
					justify="flex-start"
					style={{ marginBottom: 8 }}
				>
					<span style={{ fontSize: 14 }}>
						{__('Discount code', 'parcel2go-shipping')}:{' '}
						<strong>{discountCode}</strong>
					</span>
					<Button
						variant="tertiary"
						icon={close}
						iconSize={20}
						onClick={handleRemoveDiscount}
						label={__('Remove discount code', 'parcel2go-shipping')}
						style={{ minWidth: 24, padding: 4 }}
					/>
				</Flex>
			) : !showDiscountInput ? (
				<Button
					variant="link"
					onClick={() => setShowDiscountInput(true)}
					style={{ padding: 0, height: 'auto', marginBottom: 8 }}
				>
					{__('Got a discount code?', 'parcel2go-shipping')}
				</Button>
			) : (
				<Flex direction="column" gap={1}>
					<span
						style={{
							fontSize: 13,
							fontWeight: 600,
							display: 'block',
						}}
					>
						{__('Discount code', 'parcel2go-shipping')}
					</span>
					<Flex gap={2} align="center" justify="flex-start">
						<FlexItem style={{ flex: 1, minWidth: 0 }}>
							<TextControl
								__nextHasNoMarginBottom
								value={discountCode}
								onChange={handleDiscountChange}
								placeholder={__(
									'Enter discount code',
									'parcel2go-shipping'
								)}
								label=""
								hideLabelFromVision
							/>
						</FlexItem>
						<Button
							variant="primary"
							onClick={handleApplyDiscount}
							disabled={isValidating}
							isBusy={isValidating}
						>
							{__('Apply', 'parcel2go-shipping')}
						</Button>
						<Button
							variant="secondary"
							onClick={handleCloseDiscountInput}
							isBusy={isValidating}
							disabled={isValidating}
						>
							{__('Cancel', 'parcel2go-shipping')}
						</Button>
					</Flex>
				</Flex>
			)}

			{hasAppliedDiscount && (
				<Notice status="success" isDismissible={false}>
					{__(
						'Discount code applied successfully.',
						'parcel2go-shipping'
					)}
				</Notice>
			)}

			{/* Price breakdown */}
			{isValidating && !validationResult ? (
				<Flex
					direction="column"
					gap={2}
					align="center"
					style={{ padding: '16px 0' }}
				>
					<Spinner />
					<span style={{ color: '#757575', fontSize: 13 }}>
						{__('Calculating price...', 'parcel2go-shipping')}
					</span>
				</Flex>
			) : validationResult?.error ? (
			<CheckoutErrorNotice
				error={validationResult.error as unknown as CheckoutApiError}
			/>
			) : validationResult ? (
				<>
					{validationBreakdown.basePrices.map((price) => {
						if (price.amount !== validationBreakdown.subTotal) {
							return (
								<Flex justify="space-between" key={price.name}>
									<span>
										{price.metadata?.name ?? price.name}
									</span>
									<span>
										{formatCurrency(price.amount / 100)}
									</span>
								</Flex>
							);
						}
						return null;
					})}
					{validationBreakdown.dutyAndTaxItems?.length > 0 && (
						<Flex
							direction="column"
							gap={2}
							style={{ fontSize: 14 }}
						>
							<Flex justify="space-between">
								<span>
									{__(
										'Duty and Local Tax',
										'parcel2go-shipping'
									)}
								</span>
								<span>
									{formatCurrency(
										validationBreakdown.dutyAndTaxTotal /
											100
									)}
								</span>
							</Flex>
						</Flex>
					)}
					{validationBreakdown.otherDdpItems?.map((item) => (
						<Flex
							direction="column"
							gap={2}
							style={{ fontSize: 14 }}
							key={item.name}
						>
							<Flex justify="space-between">
								<span>{item.metadata?.name ?? item.name}</span>
								<span>{formatCurrency(item.amount / 100)}</span>
							</Flex>
						</Flex>
					))}
					{validationResult.price?.tax > 0 && (
						<Flex
							direction="column"
							gap={2}
							style={{ fontSize: 14 }}
						>
							<Flex justify="space-between">
								<span>{__('VAT', 'parcel2go-shipping')}</span>
								<span>
									{formatCurrency(
										validationResult.price.tax / 100
									)}
								</span>
							</Flex>
						</Flex>
					)}
					{validationResult.price?.discount > 0 && (
						<Flex
							direction="column"
							gap={2}
							style={{ fontSize: 14 }}
						>
							<Flex justify="space-between">
								<span>
									{__(
										'Discount applied',
										'parcel2go-shipping'
									)}
								</span>
								<span>
									-
									{formatCurrency(
										validationResult.price.discount / 100
									)}
								</span>
							</Flex>
						</Flex>
					)}
					<Flex
						justify="space-between"
						style={{ fontWeight: 600, marginTop: 4 }}
					>
						<span>{__('Total', 'parcel2go-shipping')}</span>
						<span>{formatCurrency(fullAmount)}</span>
					</Flex>
				</>
			) : null}

			{createOrderError && (
				<Notice status="error" isDismissible={false}>
					{createOrderError}
				</Notice>
			)}
		</Flex>
	);
};

export default PriceSection;
