import { Button } from '@/components/ui/button';
import { Input } from '@/components/ui/input';
import {
  InputOTP,
  InputOTPGroup,
  InputOTPSlot,
} from '@/components/ui/input-otp';
import { Separator } from '@/components/ui/separator';
import { OTP_MAX_LENGTH, useTwoFactorAuth } from '@/hooks/use-two-factor-auth';
import { handleApiError } from '@/lib/error-handler';
import { request } from '@/lib/fetcher';
import { SharedData } from '@/types';
import { usePage } from '@inertiajs/react';
import axios from 'axios';
import { REGEXP_ONLY_DIGITS } from 'input-otp';
import { useState } from 'react';
import { useTranslation } from 'react-i18next';
import { toast } from 'sonner';
import { Badge } from '../ui/badge';

type Step = 'idle' | 'password-confirm' | 'setup' | 'recovery';
type PendingAction = 'enable' | 'disable' | null;

export default function TwoFactorSection() {
  const { auth } = usePage<SharedData>().props;
  const { t } = useTranslation();

  const [isEnabled, setIsEnabled] = useState<boolean>(
    (auth.user.two_factor_enabled as boolean | undefined) ?? false,
  );
  const [step, setStep] = useState<Step>('idle');
  const [pendingAction, setPendingAction] = useState<PendingAction>(null);
  const [password, setPassword] = useState('');
  const [otpCode, setOtpCode] = useState('');
  const [loading, setLoading] = useState(false);

  const {
    qrCodeSvg,
    manualSetupKey,
    recoveryCodesList,
    fetchSetupData,
    fetchRecoveryCodes,
    clearSetupData,
  } = useTwoFactorAuth();

  const performEnable = async () => {
    await request.post('/user/two-factor-authentication');
    await fetchSetupData();
    setStep('setup');
  };

  const performDisable = async () => {
    await request.delete('/user/two-factor-authentication');
    setIsEnabled(false);
    setStep('idle');
    toast.success(t('Two-factor authentication disabled'));
  };

  const tryAction = async (action: 'enable' | 'disable') => {
    setLoading(true);
    try {
      if (action === 'enable') await performEnable();
      else await performDisable();
    } catch (error) {
      if (axios.isAxiosError(error) && error.response?.status === 423) {
        setPendingAction(action);
        setStep('password-confirm');
      } else {
        handleApiError(error);
      }
    } finally {
      setLoading(false);
    }
  };

  const handlePasswordConfirm = async () => {
    setLoading(true);
    try {
      await request.post('/user/confirm-password', { password });
      setPassword('');
      if (pendingAction === 'enable') await performEnable();
      else if (pendingAction === 'disable') await performDisable();
      setPendingAction(null);
    } catch (error) {
      handleApiError(error);
    } finally {
      setLoading(false);
    }
  };

  const handleConfirmOtp = async () => {
    setLoading(true);
    try {
      await request.post('/user/confirmed-two-factor-authentication', {
        code: otpCode,
      });
      await fetchRecoveryCodes();
      setIsEnabled(true);
      setOtpCode('');
      clearSetupData();
      setStep('recovery');
      toast.success(t('Two-factor authentication enabled'));
    } catch (error) {
      handleApiError(error);
    } finally {
      setLoading(false);
    }
  };

  const handleViewCodes = async () => {
    setLoading(true);
    try {
      await fetchRecoveryCodes();
      setStep('recovery');
    } catch {
      toast.error(t('Failed to fetch recovery codes'));
    } finally {
      setLoading(false);
    }
  };

  const handleRegenerate = async () => {
    setLoading(true);
    try {
      await request.post('/user/two-factor-recovery-codes');
      await fetchRecoveryCodes();
      toast.success(t('Recovery codes regenerated'));
    } catch (error) {
      handleApiError(error);
    } finally {
      setLoading(false);
    }
  };

  if (step === 'password-confirm') {
    return (
      <>
        <Separator className="my-6 bg-black/5 dark:bg-white/5" />
        <div className="space-y-4">
          <div>
            <h3 className="mb-1 text-base font-medium">
              {t('Confirm Password')}
            </h3>
            <p className="text-sm text-black/50 dark:text-white/40">
              {t('Please confirm your password to continue.')}
            </p>
          </div>
          <Input
            type="password"
            value={password}
            onChange={(e) => setPassword(e.target.value)}
            onKeyDown={(e) => {
              if (e.key === 'Enter' && password) handlePasswordConfirm();
            }}
            placeholder={t('Your current password')}
            className="max-w-sm"
            autoFocus
          />
          <div className="flex gap-3">
            <Button
              onClick={handlePasswordConfirm}
              disabled={!password}
              loading={loading}
              variant="primary"
            >
              {t('Confirm')}
            </Button>
            <Button
              variant="secondary"
              className="rounded-full"
              disabled={loading}
              onClick={() => {
                setStep('idle');
                setPendingAction(null);
                setPassword('');
              }}
            >
              {t('Cancel')}
            </Button>
          </div>
        </div>
      </>
    );
  }

  if (step === 'setup') {
    return (
      <>
        <Separator className="my-6 bg-black/5 dark:bg-white/5" />
        <div className="space-y-4">
          <div>
            <h3 className="mb-1 text-base font-medium">
              {t('Set Up Two-Factor Authentication')}
            </h3>
            <p className="text-sm text-black/50 dark:text-white/40">
              {t(
                'Scan the QR code with your authenticator app (e.g. Google Authenticator, Authy), then enter the code to confirm.',
              )}
            </p>
          </div>

          {qrCodeSvg && (
            <div
              className="inline-block rounded-xl bg-white p-3 shadow-sm"
              dangerouslySetInnerHTML={{ __html: qrCodeSvg }}
            />
          )}

          {manualSetupKey && (
            <div className="space-y-1">
              <p className="text-xs text-black/50 dark:text-white/40">
                {t('Or enter this key manually:')}
              </p>
              <code className="block w-fit rounded-lg bg-black/5 px-3 py-1.5 font-mono text-sm tracking-widest dark:bg-white/10">
                {manualSetupKey}
              </code>
            </div>
          )}

          <div className="space-y-2">
            <p className="text-sm font-medium">
              {t('Enter the 6-digit code from your authenticator app:')}
            </p>
            <InputOTP
              maxLength={OTP_MAX_LENGTH}
              value={otpCode}
              onChange={setOtpCode}
              pattern={REGEXP_ONLY_DIGITS}
            >
              <InputOTPGroup>
                {Array.from({ length: OTP_MAX_LENGTH }, (_, i) => (
                  <InputOTPSlot
                    key={i}
                    index={i}
                    className="rounded-2xl border border-black/5 bg-black/5 dark:border-white/10 dark:bg-white/10"
                  />
                ))}
              </InputOTPGroup>
            </InputOTP>
          </div>

          <div className="flex gap-3">
            <Button
              onClick={handleConfirmOtp}
              disabled={otpCode.length !== OTP_MAX_LENGTH}
              loading={loading}
              variant="primary"
            >
              {t('Verify & Enable')}
            </Button>
            <Button
              variant="secondary"
              className="rounded-full"
              disabled={loading}
              onClick={() => {
                setStep('idle');
                clearSetupData();
                setOtpCode('');
              }}
            >
              {t('Cancel')}
            </Button>
          </div>
        </div>
      </>
    );
  }

  if (step === 'recovery') {
    return (
      <>
        <Separator className="my-6 bg-black/5 dark:bg-white/5" />
        <div className="space-y-4">
          <div>
            <h3 className="mb-1 text-base font-medium">
              {t('Recovery Codes')}
            </h3>
            <p className="text-sm text-black/50 dark:text-white/40">
              {t(
                'Store these recovery codes somewhere safe. Each code can be used once to sign in if you lose access to your authenticator app.',
              )}
            </p>
          </div>

          <div className="grid grid-cols-2 gap-1.5 rounded-xl bg-black/5 p-4 font-mono text-sm dark:bg-white/5">
            {recoveryCodesList.map((code) => (
              <span key={code} className="text-black/70 dark:text-white/70">
                {code}
              </span>
            ))}
          </div>

          <div className="flex gap-3">
            <Button
              variant="secondary"
              loading={loading}
              onClick={handleRegenerate}
              className="rounded-full"
            >
              {t('Regenerate Codes')}
            </Button>
            <Button
              variant="primary"
              disabled={loading}
              onClick={() => setStep('idle')}
            >
              {t('Done')}
            </Button>
          </div>
        </div>
      </>
    );
  }

  return (
    <>
      <Separator className="my-6 bg-black/5 dark:bg-white/5" />
      <div className="space-y-4">
        <div className="flex items-start justify-between gap-4">
          <div>
            <h3 className="mb-1 text-base font-medium">
              {t('Two-Factor Authentication')}
            </h3>
            <p className="text-sm text-black/50 dark:text-white/40">
              {t(
                'Add an extra layer of security to your account using an authenticator app.',
              )}
            </p>
          </div>
          <Badge variant={isEnabled ? 'successOutline' : 'destructiveOutline'}>
            {isEnabled ? t('Enabled') : t('Disabled')}
          </Badge>
        </div>

        <div className="flex flex-wrap gap-3">
          {isEnabled ? (
            <>
              <Button
                variant="secondary"
                loading={loading}
                onClick={handleViewCodes}
                className="rounded-full"
              >
                {t('View Recovery Codes')}
              </Button>
              <Button
                variant="destructiveSubtle"
                loading={loading}
                onClick={() => tryAction('disable')}
                className="rounded-full"
              >
                {t('Disable 2FA')}
              </Button>
            </>
          ) : (
            <Button
              variant="primary"
              loading={loading}
              onClick={() => tryAction('enable')}
            >
              {t('Enable 2FA')}
            </Button>
          )}
        </div>
      </div>
    </>
  );
}
