/**
 * PaymentFactory: groups enabled providers by name and renders the appropriate
 * payment component (Braintree or PrePay).
 */
import { useMemo } from '@wordpress/element';
import { __ } from '@wordpress/i18n';
import { Card, CardBody, CardHeader, Flex } from '@wordpress/components';
import type {
	PaymentProvider,
	PaymentProviders,
	GenericPaymentResponse,
} from '../../../types';
import BraintreePayment from './braintree';
import PrePayPayment from './prepay';
import { PaymentOrderResponse } from '../../../types/payment';
import { useParcel2goAuth } from '../../hooks';

interface PaymentFactoryProps {
	paymentOrder: PaymentOrderResponse;
	paymentProviders: PaymentProviders;
	onSuccess: (response: GenericPaymentResponse, paymentOrder: PaymentOrderResponse) => void;
}

function getProviderTitle(provider: string): string {
	switch (provider) {
		case 'braintree':
			return __('Card & Digital Wallets', 'parcel2go-shipping');
		case 'p2g-prepay':
			return __('Account Balance', 'parcel2go-shipping');
		default:
			return __('Payment Method', 'parcel2go-shipping');
	}
}

export default function PaymentFactory({
	paymentOrder,
	paymentProviders,
	onSuccess,
}: PaymentFactoryProps) {
	const { isLinked, isLoading } = useParcel2goAuth();
	const grouped = useMemo(() => {
		if (!paymentProviders?.providers) {
			return {} as Record<string, PaymentProvider[]>;
		}

		return Object.values(paymentProviders.providers)
			.filter((p) => p.enabled)
			.sort((a, b) => {
				const aName = a?.provider?.toLowerCase() ?? a?.type?.toLowerCase() ?? '';
				const bName = b?.provider?.toLowerCase() ?? b?.type?.toLowerCase() ?? '';
				return bName.localeCompare(aName);
			})
			.reduce<Record<string, PaymentProvider[]>>((acc, provider) => {
				const name =
					provider?.provider?.toLowerCase() ??
					provider?.type?.toLowerCase() ??
					'';
				if (!acc[name]) acc[name] = [];
				acc[name].push(provider);
				return acc;
			}, {});
	}, [paymentProviders]);

	return (
		<Flex direction="column" gap={3}>
			{Object.entries(grouped).map(([provider, providers]) => {
				if (isLoading || (!isLinked && provider === 'p2g-prepay')) return null;

				let component: JSX.Element | null = null;

				switch (provider) {
					case 'braintree':
						component = (
							<BraintreePayment
								key={provider}
								paymentOrder={paymentOrder}
								providers={providers}
								onSuccess={onSuccess}
							/>
						);
						break;
					case 'p2g-prepay':
						component = (
							<PrePayPayment
								key={provider}
								paymentOrder={paymentOrder}
								total={paymentProviders.totalInUnits / 100}
								onSuccess={onSuccess}
							/>
						);
						break;
					default:
						return null;
				}

				return (
					<Card key={provider} size="small">
						<CardHeader>
							<strong>{getProviderTitle(provider)}</strong>
						</CardHeader>
						<CardBody>{component}</CardBody>
					</Card>
				);
			})}
		</Flex>
	);
}
