import { useCallback, useMemo, useRef } from 'react';
import clsx from 'clsx';
import { useAppSelector } from '@akinon/next/redux/hooks';
import { useSetPaymentOptionMutation } from '@akinon/next/data/client/checkout';
import { usePaymentOptions } from '@akinon/next/hooks/use-payment-options';
import { useLocalization } from '@akinon/next/hooks';
import { Icon } from '@theme/components';
import type { RootState } from '@theme/redux/store';
import type { CheckoutPaymentOption } from '@akinon/next/types';

const PAYMENT_TYPE_ICON: Record<string, string> = {
  credit_card: 'cvc',
  funds_transfer: 'file',
  pay_on_delivery: 'address',
  bkm_express: 'akinon',
  masterpass: 'cvc',
  masterpass_rest: 'cvc',
  saved_card: 'cvc',
  gpay: 'google',
  google_pay: 'google',
  apple_pay: 'apple',
  wallet: 'akinon',
  redirection: 'globe',
  credit_payment: 'installment',
  loyalty: 'heart-full',
  hepsipay: 'akinon',
  tabby: 'installment',
  tamara: 'installment',
  iyzico: 'cvc',
  cybersource_uc: 'cvc',
  flow_payment: 'installment'
};

const SLUG_KEYWORD_ICON: Array<[string, string]> = [
  ['apple', 'apple'],
  ['google', 'google'],
  ['gpay', 'google'],
  ['hepsi', 'akinon'],
  ['tabby', 'installment'],
  ['tamara', 'installment'],
  ['flow', 'installment'],
  ['saved', 'cvc'],
  ['credit', 'cvc'],
  ['transfer', 'file'],
  ['delivery', 'address'],
  ['wallet', 'akinon']
];

const getOptionIcon = (option: CheckoutPaymentOption): string => {
  if (PAYMENT_TYPE_ICON[option.payment_type]) {
    return PAYMENT_TYPE_ICON[option.payment_type];
  }
  const slug = option.slug?.toLowerCase() || '';
  for (const [keyword, icon] of SLUG_KEYWORD_ICON) {
    if (slug.includes(keyword)) return icon;
  }
  return 'default';
};

const PaymentOptionsGrid = () => {
  const { t } = useLocalization();
  const { preOrder, attributeBasedShippingOptions } = useAppSelector(
    (state: RootState) => state.checkout
  );
  const [setPaymentOption, { isLoading }] = useSetPaymentOptionMutation();
  const { filteredPaymentOptions } = usePaymentOptions();

  const containerRef = useRef<HTMLDivElement>(null);

  const visibleOptions = useMemo(() => {
    if (
      attributeBasedShippingOptions &&
      Object.keys(attributeBasedShippingOptions).length > 0
    ) {
      return filteredPaymentOptions.filter(
        (option) => option.slug?.toLowerCase() !== 'pay-on-delivery'
      );
    }
    return filteredPaymentOptions;
  }, [filteredPaymentOptions, attributeBasedShippingOptions]);

  const handleKeyDown = useCallback(
    (event: React.KeyboardEvent<HTMLDivElement>) => {
      if (
        !['ArrowRight', 'ArrowLeft', 'ArrowDown', 'ArrowUp', 'Home', 'End'].includes(
          event.key
        )
      ) {
        return;
      }
      event.preventDefault();
      const buttons = Array.from(
        containerRef.current?.querySelectorAll<HTMLButtonElement>(
          'button[role="radio"]'
        ) ?? []
      );
      if (buttons.length === 0) return;
      const currentIndex = buttons.findIndex(
        (btn) => btn === document.activeElement
      );
      let nextIndex = currentIndex;
      switch (event.key) {
        case 'ArrowRight':
        case 'ArrowDown':
          nextIndex = (currentIndex + 1 + buttons.length) % buttons.length;
          break;
        case 'ArrowLeft':
        case 'ArrowUp':
          nextIndex = (currentIndex - 1 + buttons.length) % buttons.length;
          break;
        case 'Home':
          nextIndex = 0;
          break;
        case 'End':
          nextIndex = buttons.length - 1;
          break;
      }
      buttons[nextIndex]?.focus();
    },
    []
  );

  if (visibleOptions.length === 0) {
    return (
      <p className="rounded-xl border border-dashed border-gray-200 bg-gray-50 px-5 py-4 text-sm italic text-gray-600">
        {t('checkout.one_page.payment.no_options')}
      </p>
    );
  }

  return (
    <div
      ref={containerRef}
      className={clsx(
        'grid grid-cols-1 gap-2.5 sm:grid-cols-2 lg:grid-cols-3',
        { 'pointer-events-none opacity-60': isLoading }
      )}
      role="radiogroup"
      aria-label={t('checkout.one_page.payment.title')}
      onKeyDown={handleKeyDown}
    >
      {visibleOptions.map((option, index) => {
        const selected = preOrder?.payment_option?.pk === option.pk;
        return (
          <button
            key={option.pk}
            type="button"
            role="radio"
            aria-checked={selected}
            tabIndex={selected || (!preOrder?.payment_option && index === 0) ? 0 : -1}
            onClick={() => setPaymentOption(option.pk)}
            className={clsx(
              'group relative flex min-h-[5rem] items-center gap-3',
              'rounded-xl border px-4 py-3 text-left',
              'transition-all duration-200 ease-out',
              'focus:outline-none focus-visible:ring-2 focus-visible:ring-black-800 focus-visible:ring-offset-2',
              selected
                ? 'border-black-800 bg-black-800/[0.03] shadow-[inset_0_0_0_1px_rgb(31,31,31)]'
                : 'border-gray-200 bg-white hover:border-gray-400'
            )}
            data-testid={`one-page-payment-card-${option.pk}`}
            data-payment-type={option.payment_type}
          >
            <Icon
              name={getOptionIcon(option)}
              size={20}
              className={clsx(
                'flex-shrink-0 transition-colors',
                selected ? 'fill-black-800' : 'fill-gray-600'
              )}
              aria-hidden="true"
            />
            <span
              className={clsx(
                'flex-1 text-sm font-medium leading-tight',
                selected ? 'text-black-800' : 'text-gray-700'
              )}
            >
              {option.name}
            </span>
            <span
              className={clsx(
                'flex h-4 w-4 flex-shrink-0 items-center justify-center rounded-full border-2 transition-all',
                selected
                  ? 'border-black-800 bg-black-800'
                  : 'border-gray-300 bg-white group-hover:border-gray-400'
              )}
              aria-hidden="true"
            >
              {selected && (
                <span className="block h-1.5 w-1.5 rounded-full bg-white" />
              )}
            </span>
          </button>
        );
      })}
    </div>
  );
};

export default PaymentOptionsGrid;
