import React, { useState, useRef, useCallback, useEffect } from 'react';
import { verifyOtp, sendOtp } from '../core/checkout-api';
import type { OtpStepProps } from '../core/types';

const OTP_LENGTH = 6;
const RESEND_COOLDOWN = 30; // seconds

/** Mask phone for display: +91 98765 **210 */
function maskMobile(mobile: string): string {
  const digits = mobile.replace(/\D/g, '');
  if (digits.length < 4) return mobile;
  return `+91 ${digits.slice(2, 7)} **${digits.slice(-3)}`;
}

const OtpStep: React.FC<OtpStepProps> = ({
  mobile,
  onVerified,
  onBack,
  functionBaseUrl,
  merchantId,
  sessionContext,
}) => {
  const [digits, setDigits] = useState<string[]>(Array(OTP_LENGTH).fill(''));
  const [loading, setLoading] = useState(false);
  const [error, setError] = useState<string | null>(null);
  const [resendCountdown, setResendCountdown] = useState(RESEND_COOLDOWN);
  const [resendLoading, setResendLoading] = useState(false);
  const inputRefs = useRef<(HTMLInputElement | null)[]>([]);
  const timerRef = useRef<ReturnType<typeof setInterval> | null>(null);

  // Start countdown on mount
  useEffect(() => {
    timerRef.current = setInterval(() => {
      setResendCountdown((c) => {
        if (c <= 1) {
          clearInterval(timerRef.current!);
          return 0;
        }
        return c - 1;
      });
    }, 1000);
    return () => { if (timerRef.current) clearInterval(timerRef.current); };
  }, []);

  const focusBox = (index: number) => {
    inputRefs.current[index]?.focus();
  };

  const handleDigitChange = useCallback((index: number, value: string) => {
    const char = value.replace(/\D/g, '').slice(-1);
    setError(null);

    setDigits((prev) => {
      const next = [...prev];
      next[index] = char;
      return next;
    });

    if (char && index < OTP_LENGTH - 1) {
      focusBox(index + 1);
    }
  }, []);

  const handleKeyDown = useCallback((index: number, e: React.KeyboardEvent<HTMLInputElement>) => {
    if (e.key === 'Backspace') {
      if (digits[index]) {
        // Clear current box
        setDigits((prev) => { const n = [...prev]; n[index] = ''; return n; });
      } else if (index > 0) {
        // Move back and clear previous
        setDigits((prev) => { const n = [...prev]; n[index - 1] = ''; return n; });
        focusBox(index - 1);
      }
    } else if (e.key === 'ArrowLeft' && index > 0) {
      focusBox(index - 1);
    } else if (e.key === 'ArrowRight' && index < OTP_LENGTH - 1) {
      focusBox(index + 1);
    }
  }, [digits]);

  // Handle paste into any box
  const handlePaste = useCallback((e: React.ClipboardEvent<HTMLInputElement>) => {
    e.preventDefault();
    const pasted = e.clipboardData.getData('text').replace(/\D/g, '').slice(0, OTP_LENGTH);
    if (!pasted) return;
    const next = Array(OTP_LENGTH).fill('');
    pasted.split('').forEach((ch, i) => { next[i] = ch; });
    setDigits(next);
    setError(null);
    focusBox(Math.min(pasted.length, OTP_LENGTH - 1));
  }, []);

  const otp = digits.join('');
  const isComplete = otp.length === OTP_LENGTH && !digits.includes('');

  const handleVerify = useCallback(async () => {
    if (!isComplete) return;
    setLoading(true);
    setError(null);
    try {
      const result = await verifyOtp({ functionBaseUrl, merchantId }, mobile, otp, sessionContext);
      onVerified(result.session_token, result.buyer_id, result.session_id);
    } catch (err: unknown) {
      setError(err instanceof Error ? err.message : 'Verification failed. Please try again.');
      // Clear boxes on wrong OTP so user can retry without backspacing
      setDigits(Array(OTP_LENGTH).fill(''));
      focusBox(0);
    } finally {
      setLoading(false);
    }
  }, [isComplete, otp, mobile, functionBaseUrl, merchantId, onVerified, sessionContext]);

  // Auto-verify once all 6 digits are filled (great UX for SMS auto-read)
  useEffect(() => {
    if (isComplete && !loading) {
      handleVerify();
    }
    // eslint-disable-next-line react-hooks/exhaustive-deps
  }, [isComplete]);

  const handleResend = useCallback(async () => {
    if (resendCountdown > 0 || resendLoading) return;
    setResendLoading(true);
    setError(null);
    setDigits(Array(OTP_LENGTH).fill(''));
    try {
      await sendOtp({ functionBaseUrl, merchantId }, mobile);
      // Restart countdown
      setResendCountdown(RESEND_COOLDOWN);
      timerRef.current = setInterval(() => {
        setResendCountdown((c) => {
          if (c <= 1) { clearInterval(timerRef.current!); return 0; }
          return c - 1;
        });
      }, 1000);
      focusBox(0);
    } catch (err: unknown) {
      setError(err instanceof Error ? err.message : 'Failed to resend OTP.');
    } finally {
      setResendLoading(false);
    }
  }, [resendCountdown, resendLoading, functionBaseUrl, merchantId, mobile]);

  return (
    <div className="qr-auth-step">
      {/* Back */}
      <button type="button" className="qr-back-btn qr-back-btn--auth" onClick={onBack} disabled={loading}>
        <svg aria-hidden="true" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2.5" strokeLinecap="round" strokeLinejoin="round">
          <path d="M19 12H5M12 5l-7 7 7 7" />
        </svg>
      </button>

      {/* Icon */}
      <div className="qr-auth-step__icon" aria-hidden="true">
        <svg viewBox="0 0 48 48" fill="none" xmlns="http://www.w3.org/2000/svg">
          <circle cx="24" cy="24" r="24" fill="var(--qr-primary-light)" />
          <rect x="13" y="16" width="22" height="16" rx="2" stroke="var(--qr-primary)" strokeWidth="1.8" fill="none" />
          <path d="M13 22h22" stroke="var(--qr-primary)" strokeWidth="1.8" />
          <circle cx="18" cy="29" r="1.5" fill="var(--qr-primary)" />
          <circle cx="24" cy="29" r="1.5" fill="var(--qr-primary)" />
          <circle cx="30" cy="29" r="1.5" fill="var(--qr-primary)" />
        </svg>
      </div>

      <h3 className="qr-auth-step__title">Enter OTP</h3>
      <p className="qr-auth-step__sub">
        Sent to <strong>{maskMobile(mobile)}</strong>
      </p>

      {/* OTP boxes */}
      <div className="qr-otp-boxes" role="group" aria-label="Enter one-time password">
        {digits.map((d, i) => (
          <input
            key={i}
            ref={(el) => { inputRefs.current[i] = el; }}
            type="text"
            inputMode="numeric"
            maxLength={1}
            className={`qr-otp-box${d ? ' qr-otp-box--filled' : ''}${error ? ' qr-otp-box--error' : ''}`}
            value={d}
            onChange={(e) => handleDigitChange(i, e.target.value)}
            onKeyDown={(e) => handleKeyDown(i, e)}
            onPaste={handlePaste}
            onFocus={(e) => e.target.select()}
            aria-label={`OTP digit ${i + 1}`}
            disabled={loading}
            autoComplete={i === 0 ? 'one-time-code' : 'off'}
          />
        ))}
      </div>

      {error && (
        <p className="qr-auth-step__error" role="alert">{error}</p>
      )}

      {/* Verify button — shows when not auto-verifying */}
      <button
        type="button"
        className="qr-btn qr-btn--primary qr-btn--full"
        onClick={handleVerify}
        disabled={!isComplete || loading}
      >
        {loading ? (
          <span className="qr-spinner qr-spinner--sm" aria-hidden="true" />
        ) : 'Verify OTP'}
      </button>

      {/* Resend */}
      <p className="qr-auth-step__resend">
        {resendCountdown > 0 ? (
          <span>Resend OTP in {resendCountdown}s</span>
        ) : (
          <button
            type="button"
            className="qr-link-btn"
            onClick={handleResend}
            disabled={resendLoading}
          >
            {resendLoading ? 'Sending…' : 'Resend OTP'}
          </button>
        )}
      </p>
    </div>
  );
};

export default OtpStep;
