'use client';

import { forwardRef, useEffect, useImperativeHandle, useState } from 'react';
import Image from 'next/image';
import { CardDataUpdateType } from '@/types/common';
import { useTranslations } from 'next-intl';
import valid from 'card-validator';
import clsx from 'clsx';

type CardType = 'visa' | 'mastercard' | 'discover' | 'amex' | 'jcb' | null;

type CardStateErrorType = {
    cvc: string | null;
    expiry: string | null;
    cardNumber: string | null;
}
type PropsType = {
    cardData: CardDataUpdateType;
    setCardData: any;
    setIsValidCard: any;
    ref?: any;
}
type RefType = {
    markTouched: () => void;
};

const getCardIcon = (type: string | null): string => {
    switch (type) {
        case 'visa':
            return '/assets/icons/visa-card.svg';
        case 'master':
            return '/assets/icons/mastercard.svg';
        case 'jcb':
            return '/assets/icons/jcb-card.svg';
        case 'discover':
            return '/assets/icons/discover-card.svg';
        default:
            return '/assets/icons/credit-card-default.svg';
    }
}

const InputUpdateCard = forwardRef<RefType, PropsType>(function InputUpdateCard(props, ref) {
    const { cardData, setCardData, setIsValidCard } = props;
    const t = useTranslations("");

    const [cardType, setCardType] = useState<CardType>(null);
    const [touched, setTouched] = useState(false);
    const [errors, setErrors] = useState<CardStateErrorType>({
        cardNumber: t('validate.card.invalidCardNumber'),
        expiry: t('validate.card.invalidExpiryDate'),
        cvc: t('validate.card.invalidCvc'),
    });
    
    const handleBlur = () => {
        if (!touched) {
            setTouched(true);
        }
    };

    const handleInputChange = (e: React.ChangeEvent<HTMLInputElement>) => {
        const name = e.target.name;
        var value: any = e.target.value || '';
        switch (name) {
            case 'cardNumber':
                const maxLength = cardType === 'jcb' ? 19 : 16;
                value = value.replace(/\D/g, '').slice(0, maxLength).replace(/(.{4})/g, '$1 ').trim();

                const numberValidation = valid.number(value);
                const type = numberValidation.card?.type as CardType
                setCardType(type || null);
                setErrors((prev) => ({
                    ...prev,
                    cardNumber: numberValidation.isValid ? null : t('validate.card.invalidCardNumber'),
                }));
                if (value.replace(/\D/g, '').length === maxLength) {
                    const next = document.getElementById('expiryCard');
                    next?.focus();
                }
                break;
            case 'expiry':
                let cleaned  = value.replace(/\D/g, '').slice(0, 4);
                if (cleaned.length > 2) {
                    value = `${cleaned.slice(0, 2)} / ${cleaned.slice(2)}`;
                } else if (cleaned.length > 1) {
                    value = `${cleaned.slice(0, 2)}`;
                }
                
                let expiryValidationMonth = valid.expirationDate(value);
                setErrors((prev) => ({
                    ...prev,
                    expiry: expiryValidationMonth.isValid ? null : t('validate.card.invalidExpiryDate'),
                }));
                if (value.length === 7) {
                    const next = document.getElementById('cardCVC');
                    next?.focus();
                }
                break;
            case 'cvc':
                const cvcValidation = valid.cvv(value, 3);
                setErrors((prev) => ({
                    ...prev,
                    cvc: cvcValidation.isValid ? null : t('validate.card.invalidCvc'),
                }));
                
                break;
            default:
                break;
        }
        setCardData((prev: any) => ({ ...prev, [name]: value }));
    };
    const getError = (): string | null => {
        if (errors.cardNumber) {
            return errors.cardNumber;
        } else if (errors.expiry) {
            return errors.expiry;
        } else if (errors.cvc) {
            return errors.cvc;
        }
        return null;
    }

    useImperativeHandle(ref, () => ({
        markTouched: () => setTouched(true),
    }));

    useEffect(() => {
        const numberValidation = valid.number(cardData.cardNumber);
        const expiryValidationMonth = valid.expirationDate(cardData.expiry);
        const cvcValidation = valid.cvv(cardData.cvc, 3);
        setErrors({
            cardNumber: numberValidation.isValid ? null : t('validate.card.invalidCardNumber'),
            expiry: expiryValidationMonth.isValid ? null : t('validate.card.invalidExpiryDate'),
            cvc: cvcValidation.isValid ? null : t('validate.card.invalidCvc')
        })
    }, []);

    useEffect(() => {
        if (errors.cardNumber || errors.expiry || errors.cvc) {
            setIsValidCard(false);
        } else {
            setIsValidCard(true);
        }
    }, [errors]);

    return (
        <div className="w-full max-w-2xl mx-auto">
            <div className={clsx(
                `flex items-center w-full border px-3 bg-white shadow-sm space-x-2 text-[1rem]`,
                {
                    'border-[#ff3860]': touched && getError() != null,
                    'border-[#d1d5db]': !touched || getError() == null
                }
            )}>
                {/* Card Icon */}
                <div className={`w-[50px] h-[35px] flex items-center ml-2 mr-2 justify-center cursor-pointer`}>
                    <Image
                        src={getCardIcon(cardType)}
                        alt="Card Icon"
                        width={100}
                        height={35}
                        className="object-contain h-full w-full"
                    />
                </div>
                <div className='flex items-center w-full  py-2 '>
                    {/* Card Number */}
                    <input
                        className="flex-1 focus:outline-none"
                        type="text"
                        name="cardNumber"
                        placeholder={t('label.cardNumber')}
                        maxLength={cardType === 'jcb' ? 23 : 19}
                        onBlur={handleBlur}
                        value={cardData.cardNumber}
                        onChange={handleInputChange}
                    />

                    {/* Expiry */}
                    <div className="flex  w-[65px] mr-5">
                        <input
                            className="w-[60px] focus:outline-none text-left"
                            name="expiry"
                            id='expiryCard'
                            type="text"
                            placeholder="MM/YY"
                            maxLength={7}
                            value={cardData.expiry}
                            onChange={handleInputChange}
                        />
                    </div>

                    {/* CVC */}
                    <input
                        className="w-[40px] focus:outline-none"
                        name='cvc'
                        type="text"
                        placeholder="CVC"
                        id='cardCVC'
                        maxLength={3}
                        value={cardData.cvc}
                        onChange={handleInputChange}
                    />
                </div>
            </div>
            {/* Error Messages */}
            {
                touched &&
                <div className="mt-2 text-sm text-red-500 space-y-1">
                    {
                        (errors.cardNumber || errors.expiry || errors.cvc) &&
                        <div>{getError()}</div>
                    }
                </div>
            }
        </div>
    );
});

export default InputUpdateCard;




















































