'use client';

import { useState, useRef, useTransition, useEffect, useMemo } from 'react';
import { Modal } from '@/components/ui/modal';
import Button from '@/components/ui/button/Button';
import { Typography } from '@/components/atoms/typogrpahy';
import { createTopUp } from '../actions/topup.action';
import { PaymentChannel } from '../types/channel.types';
import { handlePaymentResult } from '../services/paymentHandlers';
import { minTopupByCurrency, predefinedAmountsByCurrency } from '../const/const';
import VirtualAccountModal from './modals/VirtualAccountModal';
import OTCModal from './modals/OTCModal';
import QRModal from './modals/QRModal';

interface TopUpFormProps {
  paymentChannels: PaymentChannel[];
}

const TopUpForm: React.FC<TopUpFormProps> = ({ paymentChannels = [] }) => {
  // Nominal Quick Pick untuk Indonesia
  const predefinedAmounts = predefinedAmountsByCurrency.IDR || [50000];
  const minTopupAmount = minTopupByCurrency.IDR || predefinedAmounts[0];
  const appMode = (process.env.NEXT_PUBLIC_MODE || process.env.NODE_ENV || '').toLowerCase();
  const enforceMinTopup = appMode === 'production';

  const [amount, setAmount] = useState<number>(predefinedAmounts[0]);
  const isBelowMin = enforceMinTopup && amount > 0 && amount < minTopupAmount;
  const [isConfirmModalOpen, setIsConfirmModalOpen] = useState(false);
  const formRef = useRef<HTMLFormElement>(null);
  const amountInputRef = useRef<HTMLInputElement>(null);
  const [isPending, startTransition] = useTransition();

  const [displayAmount, setDisplayAmount] = useState<string>(
    predefinedAmounts[0].toLocaleString('id-ID')
  );

  const [selectedPaymentMethod, setSelectedPaymentMethod] = useState<PaymentChannel | null>(null);
  const [amountError, setAmountError] = useState<string | null>(null);
  const [shouldShakeError, setShouldShakeError] = useState(false);
  const shakeTimeoutRef = useRef<ReturnType<typeof setTimeout> | null>(null);

  // Payment Modal States
  const [isVaModalOpen, setIsVaModalOpen] = useState(false);
  const [isOtcModalOpen, setIsOtcModalOpen] = useState(false);
  const [isQrModalOpen, setIsQrModalOpen] = useState(false);

  // Payment Data States
  const [vaNumber, setVaNumber] = useState<string>('');
  const [vaBankName, setVaBankName] = useState<string>('');
  const [otcCode, setOtcCode] = useState<string>('');
  const [merchantId, setMerchantId] = useState<string>('');
  const [otcExpiresAt, setOtcExpiresAt] = useState<string>('');
  const [qrString, setQrString] = useState<string>('');

  // Memoize the grouped and sorted payment methods
  const organizedPaymentMethods = useMemo(() => {
    const virtualAccount: PaymentChannel[] = [];
    const eWallet: PaymentChannel[] = [];
    const creditCard: PaymentChannel[] = [];
    const otc: PaymentChannel[] = [];
    const qr: PaymentChannel[] = [];

    paymentChannels.forEach(method => {
      switch (method.type) {
        case 'VIRTUAL_ACCOUNT':
          virtualAccount.push(method);
          break;
        case 'EWALLET':
          eWallet.push(method);
          break;
        case 'CREDIT_CARD':
          creditCard.push(method);
          break;
        case 'OTC':
          otc.push(method);
          break;
        case 'QR':
          qr.push(method);
          break;
        default:
          break;
      }
    });

    // Sort each group by name
    virtualAccount.sort((a, b) => a.name.localeCompare(b.name));
    eWallet.sort((a, b) => {
      const aName = a.name.trim();
      const bName = b.name.trim();
      const aIsGoPay = aName.toLowerCase() === 'gopay';
      const bIsGoPay = bName.toLowerCase() === 'gopay';
      if (aIsGoPay && !bIsGoPay) return -1;
      if (!aIsGoPay && bIsGoPay) return 1;
      return aName.localeCompare(bName);
    });
    creditCard.sort((a, b) => a.name.localeCompare(b.name));
    otc.sort((a, b) => a.name.localeCompare(b.name));
    qr.sort((a, b) => a.name.localeCompare(b.name));

    return [
      { title: 'Virtual Account', methods: virtualAccount },
      { title: 'E-Wallet', methods: eWallet },
      { title: 'Credit Card', methods: creditCard },
      { title: 'QR Payment', methods: qr },
      { title: 'Retail Outlet (OTC)', methods: otc },
    ].filter(group => group.methods.length > 0);
  }, [paymentChannels]);


  const creditCardGroup = organizedPaymentMethods.find(
    (group) => group.title === 'Credit Card'
  );
  const qrGroup = organizedPaymentMethods.find(
    (group) => group.title === 'QR Payment'
  );
  const shouldRenderCardQrRow = Boolean(
    creditCardGroup?.methods.length === 1 && qrGroup?.methods.length === 1
  );

  useEffect(() => {
    if (amount !== undefined) {
      setDisplayAmount(amount.toLocaleString('id-ID'));
    } else {
      setDisplayAmount('');
    }
  }, [amount]);

  useEffect(() => {
    return () => {
      if (shakeTimeoutRef.current) {
        clearTimeout(shakeTimeoutRef.current);
      }
    };
  }, []);

  const validateMinTopup = (value: number) => {
    if (!enforceMinTopup) {
      setAmountError(null);
      return;
    }
    if (value > 0 && value < minTopupAmount) {
      setAmountError(`Minimum topup allowed is Rp ${minTopupAmount.toLocaleString('id-ID')}`);
      return;
    }
    setAmountError(null);
  };

  const handleAmountClick = (value: number) => {
    setAmount(value);
    validateMinTopup(value);
  };

  const handleCustomAmountChange = (e: React.ChangeEvent<HTMLInputElement>) => {
    const value = e.target.value;
    const rawValue = value.replace(/\D/g, '');
    const numericValue = Number(rawValue);

    const formattedValue = rawValue ? numericValue.toLocaleString('id-ID') : '';

    setDisplayAmount(formattedValue);
    setAmount(numericValue);
    validateMinTopup(numericValue);
  };

  const handleCustomAmountBlur = () => {
    if (amount !== undefined && !isNaN(amount)) {
      if (amount === 0) {
        setDisplayAmount('');
      } else {
        setDisplayAmount(amount.toLocaleString('id-ID'));
      }
    } else {
      setDisplayAmount('');
    }
  };

  const triggerErrorShake = () => {
    if (!isBelowMin) return;
    setShouldShakeError(true);
    if (shakeTimeoutRef.current) {
      clearTimeout(shakeTimeoutRef.current);
    }
    shakeTimeoutRef.current = setTimeout(() => {
      setShouldShakeError(false);
    }, 250);
  };

  const handlePaymentMethodSelect = (method: PaymentChannel) => {
    setSelectedPaymentMethod(method);
  };

  const handleSubmit = (e: React.FormEvent<HTMLFormElement>) => {
    e.preventDefault();

    if (amount === undefined || isNaN(amount)) {
      return;
    }
    if (enforceMinTopup && amount < minTopupAmount) {
      setAmountError(`Minimum topup allowed is Rp ${minTopupAmount.toLocaleString('id-ID')}`);
      triggerErrorShake();
      requestAnimationFrame(() => {
        amountInputRef.current?.focus();
        amountInputRef.current?.scrollIntoView({ behavior: 'smooth', block: 'center' });
      });
      return;
    }
    if (!selectedPaymentMethod) {
      alert("Please select a payment method.");
      return;
    }
    
    setIsConfirmModalOpen(true);
  };

  const resetForm = () => {
    setAmount(predefinedAmounts[0]);
    setSelectedPaymentMethod(null);
    setDisplayAmount(predefinedAmounts[0].toLocaleString('id-ID'));
    setAmountError(null);
    // Reset modal data
    setVaNumber('');
    setVaBankName('');
    setOtcCode('');
    setMerchantId('');
    setOtcExpiresAt('');
    setQrString('');
  };

  const handlePaymentSuccess = (paymentResult: any) => {
    if (!selectedPaymentMethod) return;

    const handledResult = handlePaymentResult(paymentResult, selectedPaymentMethod);

    if (handledResult.success) {
      switch (selectedPaymentMethod.type) {
        case 'VIRTUAL_ACCOUNT':
          if (handledResult.vaNumber) {
            setVaNumber(handledResult.vaNumber);
            setVaBankName(selectedPaymentMethod.name);
            setIsVaModalOpen(true);
          }
          break;
        case 'OTC':
          if (handledResult.otcCode) {
            setOtcCode(handledResult.otcCode);
            setMerchantId(handledResult.merchantId || '');
            setOtcExpiresAt(handledResult.expiresAt || '');
            setIsOtcModalOpen(true);
          }
          break;
        case 'QR':
          if (handledResult.qrString) {
            setQrString(handledResult.qrString);
            setIsQrModalOpen(true);
          }
          break;
        default:
          alert(handledResult.message || 'Payment initiated successfully!');
          resetForm();
          break;
      }
    } else {
      alert(handledResult.error || "Top-up failed. Please try again.");
    }
  };

  const handleConfirmTopUp = () => {
    if (formRef.current && amount !== undefined && selectedPaymentMethod) {
      const formData = new FormData(formRef.current);
      formData.set('amount', amount.toString());
      formData.set('paymentMethodId', selectedPaymentMethod.id);
      formData.set('paymentMethodName', selectedPaymentMethod.name);
      formData.set('paymentMethodGatewayId', selectedPaymentMethod.gateway_id);
      formData.set('paymentMethodType', selectedPaymentMethod.type);

      startTransition(async () => {
        setIsConfirmModalOpen(false);
        try {
          const result = await createTopUp(formData);
          handlePaymentSuccess(result);
        } catch (error) {
          console.error("Top-up failed:", error);
          alert("Top-up failed. An unexpected error occurred.");
        }
      });
    }
  };

  // Modal close handlers
  const handleVaModalClose = () => {
    setIsVaModalOpen(false);
    resetForm();
  };

  const handleOtcModalClose = () => {
    setIsOtcModalOpen(false);
    resetForm();
  };

  const handleQrModalClose = () => {
    setIsQrModalOpen(false);
    resetForm();
  };

  const getPaymentMethodImageUrl = (method: PaymentChannel): string => {
    return method.logo_url?.trim() || "";
  };

  const renderPaymentMethodButton = (method: PaymentChannel) => {
    const imageUrl = getPaymentMethodImageUrl(method);

    return (
      <button
        key={method.id}
        type="button"
        onClick={() => handlePaymentMethodSelect(method)}
        className={`
          flex w-full flex-col items-center justify-center p-3 rounded-lg border
          text-center transition-all duration-200 ease-in-out
          ${selectedPaymentMethod?.id === method.id
            ? 'border-brand-500 bg-brand-50 dark:bg-brand-900/20'
            : 'border-gray-300 bg-white hover:bg-gray-50 dark:border-gray-700 dark:bg-gray-800 dark:hover:bg-gray-700'
          }
          focus:outline-none focus:ring-2 focus:ring-brand-500 focus:ring-opacity-50
          min-h-[80px]
        `}
      >
        {imageUrl ? (
          <img
            src={imageUrl}
            alt={`${method.name} logo`}
            className="w-15 h-10 object-contain mb-4"
          />
        ) : (
          <div className="w-15 h-10 mb-4" />
        )}
        <Typography variant="b2" className="text-sm font-medium text-black dark:text-white">
          {method.name}
        </Typography>
      </button>
    );
  };

  return (
    <>
      <form ref={formRef} onSubmit={handleSubmit}>
        <input type="hidden" name="amount" value={amount !== undefined ? amount : ''} /> 
        <input type="hidden" name="paymentMethodId" value={selectedPaymentMethod?.id || ''} />
        <input type="hidden" name="paymentMethodName" value={selectedPaymentMethod?.name || ''} />
        <input type="hidden" name="paymentMethodGatewayId" value={selectedPaymentMethod?.gateway_id || ''} />

        <div className="mb-6">
          <Typography variant="s1" className="mb-2 font-bold text-black dark:text-white">Enter amount</Typography>
          <div className="relative">
            <Typography
              variant="h3"
              className={`absolute left-4 top-1/2 -translate-y-1/2 font-normal ${
                isBelowMin ? 'text-red-600 dark:text-red-400' : 'text-gray-800 dark:text-white/90'
              }`}
            >
              Rp
            </Typography>
            <input
              id="customAmount"
              type="text"
              ref={amountInputRef}
              value={displayAmount}
              onChange={handleCustomAmountChange}
              onBlur={handleCustomAmountBlur}
              placeholder="e.g., 65.000"
              className={`
                w-full py-2.5 pl-18 max-md:pr-14 focus:outline-hidden focus:ring-0
                border-b-2
                ${
                  isBelowMin
                    ? 'border-red-500 focus:border-red-500 text-red-600 placeholder:text-red-300 dark:text-red-400 dark:placeholder:text-red-300'
                    : 'border-gray-300 dark:border-gray-700 text-gray-800 placeholder:text-gray-400 focus:border-brand-500 dark:focus:border-brand-500 dark:text-white/90 dark:placeholder:text-white/30'
                }
                dark:bg-white/[0.03]
                transition-all duration-200 ease-in-out
                text-2xl lg:text-5xl overflow-auto text-center
                placeholder:font-normal
              `}
            />
          </div>
          {amountError && (
            <Typography
              variant="b2"
              className={`mt-2 text-sm text-red-600 dark:text-red-400 ${shouldShakeError ? 'animate-shake-once' : ''}`}
            >
              {amountError}
            </Typography>
          )}
        </div>

        <div className="mb-6">
          <Typography variant="s2" className="mb-2 font-semibold text-black/90 dark:text-white">Quick select</Typography>
          <div className="grid grid-cols-2 gap-4 md:grid-cols-3 lg:grid-cols-5">
            {predefinedAmounts.map((predefinedAmount) => (
              <Button
                key={predefinedAmount}
                type="button"
                variant="outline"
                onClick={() => handleAmountClick(predefinedAmount)}
                className={`w-full justify-center rounded-lg px-4 py-2 text-center font-medium border
                  bg-transparent text-black border-slate-300 hover:bg-slate-100 
                  dark:text-white dark:border-strokedark dark:hover:bg-slate-800
                  `}
              >
                {predefinedAmount.toLocaleString('id-ID')}
              </Button>
            ))}
          </div>
        </div>

        <div className="mt-14">
          <Typography variant="s1" className="mb-2 font-bold text-black dark:text-white">Select Payment Method</Typography>
          {organizedPaymentMethods.map(group => {
            if (shouldRenderCardQrRow && group.title === 'Credit Card' && creditCardGroup && qrGroup) {
              return (
                <div key="credit-card-qr-row" className="mb-6 grid grid-cols-2 gap-3 md:grid-cols-3 lg:grid-cols-4 xl:grid-cols-5">
                  <div>
                    <Typography variant="s2" className="mb-3 font-semibold text-black/90 dark:text-white">
                      Credit Card
                    </Typography>
                    {renderPaymentMethodButton(creditCardGroup.methods[0])}
                  </div>
                  <div>
                    <Typography variant="s2" className="mb-3 font-semibold text-black/90 dark:text-white">
                      QR Payment
                    </Typography>
                    {renderPaymentMethodButton(qrGroup.methods[0])}
                  </div>
                </div>
              );
            }

            if (shouldRenderCardQrRow && group.title === 'QR Payment') {
              return null;
            }

            const gridClassName = group.methods.length === 1
              ? 'grid grid-cols-1 gap-3'
              : 'grid grid-cols-2 gap-3 md:grid-cols-3 lg:grid-cols-4 xl:grid-cols-5';

            return (
              <div key={group.title} className="mb-6">
                <Typography variant="s2" className="mb-3 font-semibold text-black/90 dark:text-white">{group.title}</Typography>
                <div className={gridClassName}>
                  {group.methods.map(renderPaymentMethodButton)}
                </div>
              </div>
            );
          })}
        </div>

        <Button
          type="submit"
          variant="primary"
          size="md"
          disabled={amount === undefined || !selectedPaymentMethod || isPending}
          onMouseEnter={triggerErrorShake}
          onFocus={triggerErrorShake}
          className="w-full justify-center text-lg font-bold bg-brand text-white hover:bg-brand/90"
        >
          {isPending ? 'Processing...' : 'Top Up'}
        </Button>
      </form>

      {/* Confirmation Modal */}
      <Modal isOpen={isConfirmModalOpen} onClose={() => setIsConfirmModalOpen(false)} className="max-w-md mx-auto p-6 rounded-xl shadow-lg dark:bg-gray-900">
        <div className="text-center text-black dark:text-white">
          <h2 className="mb-2 text-2xl font-bold text-brand-500">Topup Confirmation</h2>
          <p className="text-sm text-gray-500 dark:text-gray-400 mb-6">
            {new Date().toLocaleDateString('en-GB', { day: '2-digit', month: 'long', year: 'numeric' })} at {new Date().toLocaleTimeString('en-GB', { hour: '2-digit', minute: '2-digit', hour12: false })}
          </p>

          <div className="pt-4 space-y-4 mb-8 text-left">
            <div className="flex justify-between items-center">
              <Typography variant="b2" className="text-gray-600 dark:text-gray-300">Amount:</Typography>
              <Typography variant="s1" className="font-semibold text-lg text-black dark:text-white">
                Rp {amount?.toLocaleString('id-ID')}
              </Typography>
            </div>
            <div className="flex justify-between items-center">
              <Typography variant="b2" className="text-gray-600 dark:text-gray-300">Payment Channel:</Typography>
              <Typography variant="s1" className="font-semibold text-black dark:text-white">
                {selectedPaymentMethod?.name}
              </Typography>
            </div>
          </div>

          <p className="pt-8 text-sm text-yellow-500 dark:text-gray-300 mb-2">
            Please confirm the details above to proceed with your topup*
          </p>

          <div className="flex flex-col gap-3">
            <Button
              type="button"
              onClick={handleConfirmTopUp}
              disabled={isPending}
            >
              {isPending ? 'Confirming...' : 'Confirm Top Up'}
            </Button>
            <Button
              type="button"
              onClick={() => setIsConfirmModalOpen(false)}
              variant="outline"
              className="w-full justify-center rounded-md px-6 py-3 border border-slate-300 text-black dark:border-strokedark dark:text-white hover:bg-slate-100 dark:hover:bg-gray-800 text-lg font-semibold"
            >
              Cancel
            </Button>
          </div>
        </div>
      </Modal>

      {/* Payment Modals */}
      <VirtualAccountModal
        isOpen={isVaModalOpen}
        onClose={handleVaModalClose}
        vaNumber={vaNumber}
        bankName={vaBankName}
        amount={amount}
      />

      <OTCModal
        isOpen={isOtcModalOpen}
        onClose={handleOtcModalClose}
        otcCode={otcCode}
        merchantId={merchantId}
        expiresAt={otcExpiresAt}
        channelName={selectedPaymentMethod?.name || ''}
        amount={amount}
      />

      <QRModal
        isOpen={isQrModalOpen}
        onClose={handleQrModalClose}
        qrString={qrString}
        channelName={selectedPaymentMethod?.name || ''}
        amount={amount}
      />
    </>
  );
};

export default TopUpForm;
