import { Button, YStack, Text, Paragraph } from '@junwon/aesthetics'
import { type Route, useRouterContext } from '../providers/RouterProvider'
import { useVisa, type Response } from '../providers/VisaProvider'
import { useState, useEffect } from 'react'
import { Keyboard } from 'react-native'
import { CodeInput } from './CodeInput'

const CODE_LENGTH = 6
const RESEND_COOLDOWN = 30

interface VerifyOtpProps {
  type: 'email' | 'email_change'
  redirectTo: string
  onResend: () => Promise<Response>
}

export function VerifyOtp({ type, redirectTo, onResend }: VerifyOtpProps) {
  const { setRoute } = useRouterContext()
  const [error, setError] = useState('')
  const [isSending, setIsSending] = useState(false)
  const [resendCooldown, setResendCooldown] = useState(30)
  const [inputValues, setInputValues] = useState(Array(CODE_LENGTH).fill(''))

  const { verifyOtp, loading, emailToVerify } = useVisa()

  useEffect(() => {
    if (!emailToVerify) {
      setRoute('/')
    }
  }, [emailToVerify, type, setRoute])

  useEffect(() => {
    if (inputValues.join('').length === CODE_LENGTH) {
      handleSubmit()
    }
  }, [inputValues])

  useEffect(() => {
    if (resendCooldown > 0) {
      const timer = setTimeout(() => {
        setResendCooldown(resendCooldown - 1)
      }, 1000)
      return () => clearTimeout(timer)
    }
  }, [resendCooldown])

  const resetCode = () => {
    setInputValues(Array(CODE_LENGTH).fill(''))
    Keyboard.dismiss()
  }

  const handleResend = async () => {
    if (resendCooldown > 0 || loading || !emailToVerify) return
    setError('')
    setIsSending(true)
    try {
      const result = await onResend()
      if (result.success) {
        setResendCooldown(RESEND_COOLDOWN)
      } else {
        throw result.error || new Error('Failed to resend code')
      }
    } catch (err) {
      console.log('Resend error:', err)
      setError('Failed to resend code')
    }
    setIsSending(false)
  }

  const handleChange = (newValues: string[]) => {
    if (error && newValues.some((val) => val !== '')) {
      setError('')
    }
    setInputValues(newValues)
  }

  const handleSubmit = async () => {
    const code = inputValues.join('')
    if (loading || code.length !== CODE_LENGTH) return

    try {
      const result = await verifyOtp(code, type, redirectTo)

      if (result.success) {
        setRoute(redirectTo as Route)
      } else {
        switch (result.error?.message) {
          case 'Token has expired or is invalid':
            setError('Code is wrong or has expired.')
            resetCode()
            break
          default:
            setError('Verification failed. Please try again.')
            resetCode()
        }
      }
    } catch (err) {
      console.error('Verification error:', err)
      setError('Verification failed. Please try again.')
      resetCode()
    }
  }

  if (!emailToVerify) return null

  return (
    <YStack
      f={1}
      ai="center"
      py="$4"
      gap="$4"
    >
      <YStack
        py="$12"
        gap="$3"
      >
        <CodeInput
          codeLength={CODE_LENGTH}
          inputValues={inputValues}
          setInputValues={handleChange}
        />
        <YStack h="$2">
          <Paragraph
            col={loading ? '#FFFFFF' : '$red10'}
            ta="center"
          >
            {loading ? 'Verifying...' : error}
          </Paragraph>
        </YStack>
      </YStack>
      <Text fos="$4">{emailToVerify}</Text>
      <Button
        onPress={handleResend}
        disabled={isSending || loading || resendCooldown > 0}
        theme={isSending || resendCooldown > 0 ? 'gray' : undefined}
        bc={isSending || resendCooldown > 0 ? undefined : '#FF7725'}
        w="$16"
      >
        <Text>
          {isSending
            ? 'Sending...'
            : resendCooldown > 0
              ? `Resend Code (${resendCooldown})`
              : 'Resend Code'}
        </Text>
      </Button>
    </YStack>
  )
}
