import { useFormContext } from 'react-hook-form'
import { motion, AnimatePresence } from 'framer-motion'
import clsx from 'clsx'
import React, { useState, type Key } from 'react'
import { Icon } from '../../../atoms/Icon'
import { inputErrorMotion } from './helpers'
import { findInputError } from '../../../../utils/findInputError'
import { isFormInvalid } from '../../../../utils/isFormInvalid'
import { getGlobalStyle } from '../../../../helpers'

interface InputProps {
  name: string
  type?: string
  value?: string
  width?: string
  id: string
  label?: string
  placeholder?: string
  classNames?: string
  autoComplete?: string
  defaultValue?: string
  showEye?: boolean
  icon?: string
  style?: React.CSSProperties
  generatePassword?: () => void
  onChange?: (e: React.ChangeEvent<HTMLInputElement>) => void
}
export const InputText: React.FC<InputProps> = ({
  name,
  type,
  value,
  icon = '',
  id,
  width,
  placeholder,
  defaultValue,
  autoComplete,
  showEye,
  label,
  classNames,
  style,
  onChange,
  generatePassword
}: InputProps & { label?: string }) => {
  // STATES
  const [show, setShow] = useState<boolean>(false)
  // HOOKS
  const { register, formState: { errors } } = useFormContext()
  const inputError = findInputError(errors, name)
  const isInvalid = isFormInvalid(inputError)

  const handleShowEye = (): void => {
    return setShow(!show)
  }

  const styles = {
    zIndex: 10,
    height: '2.5rem', // 12 * 0.25rem = 3rem
    width: '100%',
    borderRadius: '0.5rem', // rounded-lg = 0.5rem
    borderWidth: '2px',
    borderColor: '#cbd5e1', // slate-300
    paddingLeft: '0.75rem', // px-3 = 0.75rem
    paddingRight: '0.75rem',
    transition: 'border-color 0.3s', // For hover effect
    border: `2px solid ${getGlobalStyle('--color-neutral-gray')}`,
    outline: 'none',
  }
  return (
    <div className="relative z-10" style={{ width }}>
      <label
        htmlFor={id}
        className="absolute left-0 top-[-15px] -mt-5 font-bold text-slate-500"
        style={{
          color: '#111928'
        }}
      >
        {label?.includes('*')
          ? (
            <>
              {label?.replace('*', '')}
              <span style={{ color: getGlobalStyle('--color-feedback-error-dark') }}>*</span>
            </>
            )
          : (
              label
            )}
      </label>
      {icon !== '' && (
        <button
          type="button"
          style={{
            position: 'absolute',
            top: '20px',
            left: '20px'
          }}
        >
          <Icon icon={icon} />
        </button>
      )}
      <input
        id={id}
        defaultValue={defaultValue}
        placeholder={placeholder}
        value={value}
        {...register(name)}
        autoComplete={autoComplete}
        className={clsx(classNames)}
        onFocus={(e) => {
          e.target.style.borderColor = getGlobalStyle('--color-primary-purply')
        }}
        type={show ? 'text' : type}
        style={{ ...styles, ...style, borderColor: getGlobalStyle('--color-neutral-gray') }}
      />
      <AnimatePresence mode="wait" initial={false}>
        {isInvalid && (
          <InputError
            message={inputError.error?.message as string}
            key={inputError.error?.message as Key}
          />
        )}
      </AnimatePresence>
      {showEye && (
        <button
          type="button"
          className="absolute right-0 top-0 -mt-5 mr-3"
          onClick={handleShowEye}
          style={{
            position: 'absolute',
            right: '110px',
            top: '40px'
          }}
        >
          {<Icon icon="IconEye" />}
        </button>
      )}
      {typeof generatePassword === 'function' && (
        <button
          onClick={generatePassword}
          type="button"
          style={{
            backgroundColor: '#E1EFFE',
            color: '#1E429F',
            fontSize: '0.75rem',
            borderRadius: '0.375rem',
            padding: '0.1875rem 0.625rem  0.1875rem 0.625rem',
            position: 'absolute',
            right: '15px',
            top: '15px'
          }}
        >
          Generate
        </button>
      )}
    </div>
  )
}

function InputError ({ message }: { message: string }): React.ReactNode {
  return (
    <motion.div
      style={{ top: '100%', left: '50%', transform: 'translateX(-50%)', width: 'fit-content', padding: '0.25rem 0.5rem', color: getGlobalStyle('--color-text-error'), fontSize: getGlobalStyle('--font-size-sm') }}
      {...inputErrorMotion}
    >
      {message}
    </motion.div>
  )
}
