import { useRef, useState } from '@wordpress/element';
import { useCopyToClipboard } from '@wordpress/compose';
import {
	__experimentalHeading as Heading,
	__experimentalSpacer as Spacer,
	__experimentalText as Text,
	Button,
	Flex,
	Icon,
	Modal,
	Notice,
	ProgressBar,
	Tooltip,
} from '@wordpress/components';
import { __ } from '@wordpress/i18n';
import {
	calendar,
	check,
	chevronDown,
	chevronUp,
	copySmall,
	pages,
	rotateLeft,
	shipping,
	undo,
} from '@wordpress/icons';
import { hasLabelExpired } from 'utils';
import { useLabelPurchaseContext } from 'context/label-purchase';
import { SchedulePickup } from './schedule-pickup';
import { TrackShipment } from './track-shipment';
import { RefundShipment } from './refund-shipment';
import { withBoundary } from 'components/HOC';
import { CommercialInvoice } from './commercial-invoice';
import { LegacyWarning } from './legacy-warning';
import { PrintPackingSlipButton } from '../print-packing-slip-button';
import { PrintLabelButton } from './print-label-button';
import { ReturnLabelButton } from './return-label-button';

const MORE_ACTIONS_SEEN_STORAGE_KEY_PREFIX =
	'wcshipping_label_panel_more_actions_seen';

const shouldOpenMoreActionsByDefault = ( labelId?: string | number ) => {
	if (
		! labelId ||
		typeof window === 'undefined' ||
		! window.sessionStorage
	) {
		return true;
	}

	const storageKey = `${ MORE_ACTIONS_SEEN_STORAGE_KEY_PREFIX }_${ labelId }`;

	try {
		if ( window.sessionStorage.getItem( storageKey ) ) {
			return false;
		}

		window.sessionStorage.setItem( storageKey, 'true' );
		return true;
	} catch {
		return true;
	}
};

export const PurchaseNotice = withBoundary( () => {
	const {
		labels: {
			isPurchasing,
			isUpdatingStatus,
			isRefunding,
			hasPurchasedLabel,
			updatePurchaseStatus,
			getCurrentShipmentLabel,
			labelStatusUpdateErrors,
			isAnyRequestInProgress,
		},
		shipment: { isShipmentAutogeneratedFromLabel },
		rates: { getSelectedRate },
		shipment: {
			shipments,
			setShipments,
			currentShipmentId,
			setCurrentShipmentId,
			getShipmentOrigin,
			getShipmentDestination,
			setReturnShipments,
			returnShipments,
			selections,
			setSelection,
			getCurrentShipmentIsReturn,
		},
		packages,
		nextDesign,
	} = useLabelPurchaseContext();

	const selectedLabel = getCurrentShipmentLabel();
	const isReturn = getCurrentShipmentIsReturn();
	const hasLabel = hasPurchasedLabel();
	const [ isMoreActionsOpen, setIsMoreActionsOpen ] = useState( () =>
		shouldOpenMoreActionsByDefault( selectedLabel?.labelId )
	);
	const selectedRate = getSelectedRate();

	const serviceName =
		selectedLabel?.serviceName ??
		selectedRate?.rate?.title ??
		__( 'Shipping label', 'woocommerce-shipping' );
	const trackingNumber = selectedLabel?.tracking ?? '';
	const hasCommercialInvoice = Boolean( selectedLabel?.commercialInvoiceUrl );

	const refreshStatus = async () => {
		if ( ! selectedLabel ) {
			return;
		}
		await updatePurchaseStatus( selectedLabel.labelId );
	};

	const purchaseResultTitleText: string = __(
		'There was an issue processing your purchase',
		'woocommerce-shipping'
	);
	const shouldShowPurchaseResultHeading =
		isPurchasing ||
		isUpdatingStatus ||
		! hasLabel ||
		labelStatusUpdateErrors.length > 0;

	const isDomesticShipment = () => {
		const origin = getShipmentOrigin();
		const destination = getShipmentDestination();
		return origin?.country === 'US' && destination?.country === 'US';
	};

	const [ hasCopiedTracking, setHasCopiedTracking ] = useState( false );
	const copiedResetTimeout = useRef< ReturnType< typeof setTimeout > >();

	const copyTrackingRef = useCopyToClipboard( trackingNumber, () => {
		setHasCopiedTracking( true );

		if ( copiedResetTimeout.current ) {
			clearTimeout( copiedResetTimeout.current );
		}

		copiedResetTimeout.current = setTimeout( () => {
			setHasCopiedTracking( false );
		}, 2000 );
	} );

	return nextDesign && isAnyRequestInProgress ? (
		<>
			{
				// TODO: We need to use inline classes because we don't load css files on next-admin.
				// One way to solve this is including the classes in next admin,
				// and use those classes in the shipping plugin.
			 }
			<style>
				{ `
				.woocommerce-shipping__progressbar {
					width: 307.2px;
				}
			` }
			</style>
			<Modal
				onRequestClose={ () => {
					/* noop */
				} }
				isDismissible={ false }
				size="medium"
				__experimentalHideHeader
				shouldCloseOnClickOutside={ false }
				shouldCloseOnEsc={ false }
			>
				<Flex
					align="center"
					justify="center"
					gap={ 4 }
					direction="column"
					style={ { padding: '100px 0' } }
				>
					<Text size={ 15 } weight={ 500 } lineHeight={ '20px' }>
						{ __(
							'Processing your order',
							'woocommerce-shipping'
						) }
					</Text>
					<ProgressBar className="woocommerce-shipping__progressbar" />
					<Text size={ 13 } weight={ 400 } lineHeight={ '20px' }>
						{ __(
							"This won't take long!",
							'woocommerce-shipping'
						) }
					</Text>
				</Flex>
			</Modal>
		</>
	) : (
		<>
			{ shouldShowPurchaseResultHeading && (
				<>
					<Heading level={ 3 }>
						{ isPurchasing || isUpdatingStatus
							? __(
									'Please wait while we process your shipping label purchase',
									'woocommerce-shipping'
							  )
							: purchaseResultTitleText }
					</Heading>
					<Spacer margin={ 7 } />
				</>
			) }
			{ isShipmentAutogeneratedFromLabel() && (
				<>
					<p className="description">
						{ __(
							'This shipping label was created via the mobile app and may include item differences. All original order items are still included in this shipment.',
							'woocommerce-shipping'
						) }
					</p>
					<Spacer margin={ 7 } />
				</>
			) }
			{ hasLabel ? (
				<>
					<section className="purchase-label-panel">
						<Heading
							level={ 3 }
							className="purchase-label-panel__heading"
						>
							{ __( 'Shipping label', 'woocommerce-shipping' ) }
						</Heading>
						<div className="purchase-label-panel__card">
							<div className="purchase-label-panel__summary">
								<div className="purchase-label-panel__summary-copy">
									<Heading
										level={ 4 }
										className="purchase-label-panel__service"
									>
										{ serviceName }
									</Heading>
									{ trackingNumber && (
										<div className="purchase-label-panel__tracking">
											<span className="purchase-label-panel__tracking-label">
												{ __(
													'Tracking',
													'woocommerce-shipping'
												) }
											</span>
											<span className="purchase-label-panel__tracking-number">
												{ trackingNumber }
											</span>
											<Button
												ref={ copyTrackingRef }
												variant="tertiary"
												icon={
													hasCopiedTracking
														? check
														: copySmall
												}
												label={
													hasCopiedTracking
														? __(
																'Copied tracking number',
																'woocommerce-shipping'
														  )
														: __(
																'Copy tracking number',
																'woocommerce-shipping'
														  )
												}
												className="purchase-label-panel__copy-tracking"
											/>
										</div>
									) }
								</div>
								<span className="purchase-label-panel__status">
									{ __(
										'Ready to print',
										'woocommerce-shipping'
									) }
								</span>
							</div>
							<div className="purchase-label-panel__print-actions">
								<Tooltip
									placement="top"
									text={
										hasLabelExpired( selectedLabel )
											? __(
													'Label images older than 180 days are deleted by our technology partners for general security and data privacy concerns.',
													'woocommerce-shipping'
											  )
											: ''
									}
								>
									<PrintLabelButton />
								</Tooltip>
								<PrintPackingSlipButton />
							</div>
							<div className="purchase-label-panel__action-grid purchase-label-panel__action-grid--primary">
								<TrackShipment
									label={ selectedLabel }
									className="purchase-label-panel__action"
								>
									<Icon icon={ shipping } size={ 18 } />
									<span>
										{ __(
											'Track shipment',
											'woocommerce-shipping'
										) }
									</span>
								</TrackShipment>
								{ ! isReturn && (
									<SchedulePickup
										selectedLabel={ selectedLabel }
										className="purchase-label-panel__action"
									>
										<Icon icon={ calendar } size={ 18 } />
										<span>
											{ __(
												'Schedule pickup',
												'woocommerce-shipping'
											) }
										</span>
									</SchedulePickup>
								) }
							</div>
							<Button
								variant="tertiary"
								className="purchase-label-panel__more-toggle"
								onClick={ () =>
									setIsMoreActionsOpen(
										( isOpen ) => ! isOpen
									)
								}
								aria-expanded={ isMoreActionsOpen }
							>
								<span>
									{ __(
										'More actions',
										'woocommerce-shipping'
									) }
								</span>
								<Icon
									icon={
										isMoreActionsOpen
											? chevronUp
											: chevronDown
									}
									size={ 20 }
								/>
							</Button>
							{ isMoreActionsOpen && (
								<div className="purchase-label-panel__action-grid purchase-label-panel__action-grid--secondary">
									<RefundShipment
										label={ selectedLabel }
										selectedRate={ selectedRate }
										isBusy={ isRefunding }
										isDisabled={
											isRefunding ||
											isPurchasing ||
											isUpdatingStatus
										}
										className="purchase-label-panel__action"
									>
										<Icon icon={ undo } size={ 18 } />
										<span>
											{ __(
												'Request refund',
												'woocommerce-shipping'
											) }
										</span>
									</RefundShipment>
									{ ! isReturn && (
										<ReturnLabelButton
											isDomesticShipment={ isDomesticShipment() }
											shipments={ shipments }
											currentShipmentId={
												currentShipmentId
											}
											setShipments={ setShipments }
											setCurrentShipmentId={
												setCurrentShipmentId
											}
											setReturnShipments={
												setReturnShipments
											}
											returnShipments={ returnShipments }
											packages={ packages }
											selections={ selections }
											setSelection={ setSelection }
											className="purchase-label-panel__action"
										>
											<Icon
												icon={ rotateLeft }
												size={ 18 }
											/>
											<span>
												{ __(
													'Return label',
													'woocommerce-shipping'
												) }
											</span>
										</ReturnLabelButton>
									) }
									{ hasCommercialInvoice && (
										<CommercialInvoice
											label={ selectedLabel }
											className="purchase-label-panel__action"
										>
											<Icon icon={ pages } size={ 18 } />
											<span>
												{ __(
													'Print customs form',
													'woocommerce-shipping'
												) }
											</span>
										</CommercialInvoice>
									) }
								</div>
							) }
							<p className="purchase-label-panel__note">
								{ __(
									'Note: Reusing a printed label is a violation of our terms of service and may result in criminal charges.',
									'woocommerce-shipping'
								) }
							</p>
						</div>
					</section>
					{ selectedLabel?.isLegacy && <LegacyWarning /> }
				</>
			) : (
				<>
					<Notice
						status="warning"
						className="purchase-notice"
						isDismissible={ false }
						spokenMessage={
							/**
							 * We need to override the default spoken message so that the children are not conditionally rendered via a hook.
							 * Conditional hooks are not allowed in React and cause an error.
							 */
							__(
								'You have successfully requested to purchase a shipping label.',
								'woocommerce-shipping'
							)
						}
					>
						<Flex direction="column">
							<p>
								{ __(
									'You have purchased a label, but the purchase status is still pending. Please wait a few minutes and refresh the purchase status. If the status is still pending, please contact support.',
									'woocommerce-shipping'
								) }
							</p>
							<div className="purchase-notice-actions">
								<Button
									variant="secondary"
									onClick={ refreshStatus }
									isBusy={ isPurchasing || isUpdatingStatus }
									aria-busy={
										isPurchasing || isUpdatingStatus
									}
									disabled={
										isPurchasing || isUpdatingStatus
									}
								>
									{ __(
										'Refresh purchase status',
										'woocommerce-shipping'
									) }
								</Button>
							</div>
							{ labelStatusUpdateErrors &&
								labelStatusUpdateErrors.length > 0 && (
									<Notice
										status="error"
										isDismissible={ false }
										className="purchase-error-notice"
									>
										{ labelStatusUpdateErrors.map(
											( message, index ) => (
												<p key={ index }>{ message }</p>
											)
										) }
									</Notice>
								) }
						</Flex>
						{ selectedLabel?.isLegacy && <LegacyWarning /> }
					</Notice>
					<Flex>
						<p className="label-purchase-note">
							{ __(
								'Note: Reusing a printed label is a violation of our terms of service and may result in criminal charges.',
								'woocommerce-shipping'
							) }
						</p>
					</Flex>
				</>
			) }
		</>
	);
} )( 'PurchaseNotice' );
