import {
	Button,
	CardDivider,
	Modal,
	__experimentalText as Text,
	__experimentalSpacer as Spacer,
	Card,
	CardBody,
	Flex,
} from '@wordpress/components';
import { __ } from '@wordpress/i18n';
import { useCollapsibleCard } from '../internal/useCollapsibleCard';
import { addressStore } from 'data/address';
import { ADDRESS_TYPES } from 'data/constants';
import { dispatch, useSelect } from '@wordpress/data';
import { useLabelPurchaseContext } from 'context/label-purchase';
import { useEffect, useRef, useState } from '@wordpress/element';
import {
	addressToString,
	areAddressesClose,
	composeName,
	formatAddressFields,
} from 'utils';
import { AddressVerifiedIcon } from 'components/address-verified-icon';
import { AddressStep } from 'components/address-step';
import { close, edit } from '@wordpress/icons';
import { Badge } from 'components/wp';
import { Destination, Order, OriginAddress } from 'types';
import { ShipFromSelectV2 } from '../internal/ship-from-select-v2';

const firstFilled = ( arr: ( string | undefined )[] ) => {
	for ( const item of arr ) {
		if ( item && item.trim().length > 0 ) {
			return item;
		}
	}
	return '';
};

const AddressBlock = ( {
	address,
	children,
}: {
	address: Destination | OriginAddress;
	children?: React.ReactNode;
} ) => (
	<Flex direction={ 'column' } gap={ 1 }>
		<Text weight={ 500 }>
			{ address &&
				firstFilled( [
					address.company,
					composeName( {
						first_name:
							address.firstName ??
						( address as any ).first_name ?? // eslint-disable-line
							'',
						last_name:
						address.lastName ?? ( address as any ).last_name ?? '', // eslint-disable-line
						name: address.name ?? '',
					} ),
					__( '(no name provided)', 'woocommerce-shipping' ),
				] ) }
		</Text>
		<Text weight={ 400 }>
			{ address &&
				firstFilled( [
					address.phone,
					__( '(no phone provided)', 'woocommerce-shipping' ),
				] ) }
		</Text>
		<Flex
			direction={ 'row' }
			align="flex-end"
			justify="flex-start"
			gap={ 2 }
			wrap={ false }
		>
			<Text truncate numberOfLines={ 2 }>
				{ address
					? addressToString( address )
					: '(no address provided)' }
			</Text>
			{ children }
		</Flex>
	</Flex>
);

export const AddressesCard = ( {
	order,
	destinationAddress,
}: {
	order: Order;
	destinationAddress: Destination | OriginAddress;
} ) => {
	const [ isAddressModalOpen, setIsAddressModalOpen ] = useState( false );
	const [ isRecipientAddressHovered, setIsRecipientAddressHovered ] =
		useState( false );

	const isDestinationAddressVerified = useSelect(
		( select ) =>
			select( addressStore ).getIsAddressVerified(
				ADDRESS_TYPES.DESTINATION
			),
		[]
	);
	const normalisedDestinationAddress = useSelect(
		( select ) =>
			select( addressStore ).getNormalizedAddress(
				ADDRESS_TYPES.DESTINATION
			),
		[]
	);
	const {
		rates: { updateRates },
		labels: { hasPurchasedLabel },
		shipment: { getShipmentOrigin, getShipmentPurchaseOrigin },
	} = useLabelPurchaseContext();

	const origins = useSelect(
		( select ) => select( addressStore ).getOriginAddresses(),
		[]
	);

	const originAddress = ! hasPurchasedLabel( false )
		? ( getShipmentOrigin() as OriginAddress )
		: ( getShipmentPurchaseOrigin() as OriginAddress );

	/**
	 * 1) We need to run the auto verification process only once but the useEffect runs on every render. So we use a ref
	 * to keep track of it, but if `normalisedDestinationAddress` is not defined yet, we want to allow it to run again
	 * that's why passing an empty dependency array wouldn't work, and we need to use a ref to keep track of the
	 * effective runs
	 *
	 * 2) We should also not run the auto verification process if the address modal is open.
	 *
	 */
	const hasAutoVerificationRunOnce = useRef( false );

	useEffect(
		() => {
			if ( hasAutoVerificationRunOnce.current || isAddressModalOpen ) {
				return;
			}

			// Check if the destination address is verified, if not, run it through the normalization process and then through areAddressesClose to determine if it's close enough to auto verify the address.
			const verifyShippingAddress = async () => {
				if ( isDestinationAddressVerified ) {
					return Promise.resolve();
				}

				await dispatch( addressStore ).verifyOrderShippingAddress( {
					orderId: String( order.id ),
				} );

				// If destination address is not verified, lets normalize it and check if it's close to the verified address and then auto verify it.
				if ( ! isDestinationAddressVerified ) {
					if ( ! normalisedDestinationAddress ) {
						return Promise.resolve();
					}

					// Set the flag to true so that the auto verification process runs only once.
					hasAutoVerificationRunOnce.current = true;

					const transformedNormalisedAddress = {
						...normalisedDestinationAddress,
					};

					const shouldAutoVerify = areAddressesClose(
						transformedNormalisedAddress,
						destinationAddress
					);

					if ( ! shouldAutoVerify ) {
						return Promise.resolve();
					}

					// If made it till here, verify the address.
					await dispatch( addressStore ).updateShipmentAddress(
						{
							orderId: order.id ? String( order.id ) : '',
							address: transformedNormalisedAddress,
							isVerified: true, // Either the address is verified or the normalized address is selected
						},
						ADDRESS_TYPES.DESTINATION
					);
				}

				return Promise.resolve();
			};

			verifyShippingAddress();
		},
		// eslint-disable-next-line react-hooks/exhaustive-deps -- isAddressModalOpen is not a dependency
		[
			order,
			destinationAddress,
			isDestinationAddressVerified,
			normalisedDestinationAddress,
		]
	);

	const onCompleteCallback = () => {
		setIsAddressModalOpen( false );
		updateRates();
	};

	const { CardHeader, isOpen } = useCollapsibleCard( true );
	return (
		<Card>
			<CardHeader isBorderless iconSize={ 'small' }>
				<Flex direction={ 'row' } align="space-between">
					<Text weight={ 500 } size={ 15 }>
						{ __( 'Addresses', 'woocommerce-shipping' ) }
					</Text>
					{ ! isDestinationAddressVerified && (
						<Badge intent="warning-alt">
							{ __( 'Not validated', 'woocommerce-shipping' ) }{ ' ' }
						</Badge>
					) }
					{ isDestinationAddressVerified && ! isOpen && (
						<Text
							as="span"
							weight={ 400 }
							size={ 13 }
							style={ {
								maxWidth: '300px',
								overflow: 'hidden',
								textOverflow: 'ellipsis',
								whiteSpace: 'nowrap',
							} }
						>
							{ firstFilled( [
								originAddress?.company,
								originAddress?.name,
								__(
									'(no name provided)',
									'woocommerce-shipping'
								),
							] ) }
							{ ' → ' }
							{ destinationAddress &&
								`${ destinationAddress.state }, ${ destinationAddress.country } ${ destinationAddress.postcode }` }
						</Text>
					) }
				</Flex>
			</CardHeader>
			{ isOpen && (
				<CardBody style={ { padding: 0, paddingBottom: 0 } }>
					<Flex direction="column" gap={ 0 } justify="space-between">
						<Spacer
							paddingX={ 6 }
							paddingBottom={ 4 }
							marginBottom={ 0 }
						>
							<Flex direction={ 'column' } gap={ 1 }>
								<Text
									size={ 11 }
									weight={ 500 }
									lineHeight={ '24px' }
									variant="muted"
									upperCase
								>
									{ __( 'Sender', 'woocommerce-shipping' ) }
								</Text>
								{ ! hasPurchasedLabel( false ) && (
									<>
										{ origins.length > 1 ? (
											<ShipFromSelectV2
												disabled={ hasPurchasedLabel(
													false
												) }
											/>
										) : (
											<AddressBlock
												address={ origins[ 0 ] }
											/>
										) }
									</>
								) }
								{ hasPurchasedLabel( false ) && (
									<AddressBlock
										address={
											originAddress as OriginAddress
										}
									/>
								) }
							</Flex>
						</Spacer>
						<Spacer marginBottom={ 0 } marginX={ 6 }>
							<CardDivider />
						</Spacer>
						<Spacer
							paddingX={ 6 }
							paddingTop={ 4 }
							paddingBottom={ 3 }
							marginBottom={ 3 }
							onMouseEnter={ () => {
								if ( hasPurchasedLabel( false ) ) {
									return;
								}
								setIsRecipientAddressHovered( true );
							} }
							onMouseLeave={ () => {
								setIsRecipientAddressHovered( false );
							} }
							style={ {
								background: isRecipientAddressHovered
									? '#F9F7F8'
									: 'transparent',
							} }
						>
							<Flex direction={ 'column' } gap={ 1 }>
								<Flex
									direction="row"
									align="flex-start"
									gap={ 4 }
								>
									<Text
										size={ 11 }
										lineHeight={ '24px' }
										weight={ 500 }
										variant="muted"
										upperCase
									>
										{ __(
											'Recipient',
											'woocommerce-shipping'
										) }
									</Text>
									{ isRecipientAddressHovered ? (
										<Button
											onClick={ () =>
												setIsAddressModalOpen( true )
											}
											icon={ edit }
											iconSize={ 24 }
											hidden={
												! isRecipientAddressHovered
											}
											title={ __(
												'Click to change address',
												'woocommerce-shipping'
											) }
											style={ {
												color: '#1E1E1E',
												height: 24,
												width: 24,
												minWidth: 24,
												padding: 0,
											} }
										/>
									) : (
										' '
									) }
								</Flex>
								{ ! hasPurchasedLabel( false ) && (
									<AddressBlock
										address={ destinationAddress }
									>
										<AddressVerifiedIcon
											addressType={
												ADDRESS_TYPES.DESTINATION
											}
											isVerified={
												isDestinationAddressVerified
											}
											errorMessage={ __(
												'Not validated',
												'woocommerce-shipping'
											) }
											message={ __(
												'Validated',
												'woocommerce-shipping'
											) }
											nextDesign
										/>
									</AddressBlock>
								) }
								{ hasPurchasedLabel( false ) && (
									<AddressBlock
										address={ destinationAddress }
									/>
								) }
							</Flex>
						</Spacer>
					</Flex>
				</CardBody>
			) }
			{ isAddressModalOpen && (
				<Modal
					onRequestClose={ () => setIsAddressModalOpen( false ) }
					focusOnMount
					shouldCloseOnClickOutside={ false }
					size="medium"
					__experimentalHideHeader
				>
					<Spacer marginBottom={ 4 }>
						<Flex justify="space-between" align="flex-start">
							<Text as="h2" size={ 20 } weight={ 500 }>
								{ __(
									'Edit destination address',
									'woocommerce-shipping'
								) }
							</Text>
							<Button
								icon={ close }
								onClick={ () => setIsAddressModalOpen( false ) }
								title={ __(
									'Close modal',
									'woocommerce-shipping'
								) }
								style={ {
									padding: 0,
									minWidth: '24px',
									height: '24px',
								} }
							/>
						</Flex>
					</Spacer>
					<AddressStep
						type={ ADDRESS_TYPES.DESTINATION }
						address={ {
							id: '',
							...formatAddressFields(
								destinationAddress as
									| OriginAddress
									| Destination
							),
							firstName: '',
							lastName: '',
						} }
						isAdd={ false }
						onCompleteCallback={ onCompleteCallback }
						onCancelCallback={ () =>
							setIsAddressModalOpen( false )
						}
						orderId={ `${ order.id }` }
						originCountry={ getShipmentOrigin()?.country }
						nextDesign={ true }
					/>
				</Modal>
			) }
		</Card>
	);
};
