import { useMemo } from 'react'
import type { ReactNode } from 'react'

interface TextareaProps extends React.TextareaHTMLAttributes<HTMLTextAreaElement> {
  label?: string
  error?: string
  helperText?: string
  leftIcon?: ReactNode
  rightIcon?: ReactNode
}

function generateId(prefix: string, providedId?: string): string {
  if (providedId) {
    return providedId
  }
  return `${prefix}-${Date.now().toString(36)}-${Math.random().toString(36).substr(2, 5)}`
}

function getErrorClasses(error: string | undefined): string {
  if (!error) {
    return ''
  }
  return 'border-red-500/50 focus:border-red-500 focus:ring-red-500/50'
}

function getTextareaClasses(params: {
  error: string | undefined
  leftIcon: ReactNode | undefined
  rightIcon: ReactNode | undefined
  className: string
}): string {
  const baseClasses = 'block w-full px-3 py-2 border rounded-lg bg-cyber-dark text-cyber-accent placeholder-cyber-accent/50 focus:outline-none focus:ring-2 focus:ring-neon-cyan focus:border-neon-cyan transition-colors resize-y'
  const errorClasses = getErrorClasses(params.error)
  const paddingLeft = params.leftIcon ? 'pl-10' : ''
  const paddingRight = params.rightIcon ? 'pr-10' : ''
  return `${baseClasses} ${errorClasses} ${paddingLeft} ${paddingRight} ${params.className}`.trim()
}

function getAriaDescribedBy(textareaId: string, error: string | undefined, helperText: string | undefined): string | undefined {
  if (error) {
    return `${textareaId}-error`
  }
  if (helperText) {
    return `${textareaId}-helper`
  }
  return undefined
}

function TextareaLabel({ textareaId, label }: { textareaId: string; label: string }): React.ReactElement {
  return (
    <label htmlFor={textareaId} className="block text-sm font-medium text-cyber-accent mb-1">
      {label}
    </label>
  )
}

function TextareaIcons({ leftIcon, rightIcon }: { leftIcon?: ReactNode; rightIcon?: ReactNode }): React.ReactElement | null {
  if (!leftIcon && !rightIcon) {
    return null
  }
  return (
    <>
      {leftIcon && (
        <div className="absolute top-3 left-0 pl-3 flex items-start pointer-events-none text-cyber-accent/50">
          {leftIcon}
        </div>
      )}
      {rightIcon && (
        <div className="absolute top-3 right-0 pr-3 flex items-start text-cyber-accent/50">
          {rightIcon}
        </div>
      )}
    </>
  )
}

function TextareaError({ textareaId, error }: { textareaId: string; error: string }): React.ReactElement {
  return (
    <p id={`${textareaId}-error`} className="mt-1 text-sm text-red-400" role="alert">
      {error}
    </p>
  )
}

function TextareaHelper({ textareaId, helperText }: { textareaId: string; helperText: string }): React.ReactElement {
  return (
    <p id={`${textareaId}-helper`} className="mt-1 text-sm text-cyber-accent/70">
      {helperText}
    </p>
  )
}

export function Textarea({
  label,
  error,
  helperText,
  leftIcon,
  rightIcon,
  className = '',
  id,
  ...props
}: TextareaProps): React.ReactElement {
  const textareaId = useMemo(() => generateId('textarea', id), [id])
  const textareaClasses = useMemo(
    () => getTextareaClasses({ error, leftIcon, rightIcon, className }),
    [error, leftIcon, rightIcon, className]
  )
  const ariaDescribedBy = useMemo(() => getAriaDescribedBy(textareaId, error, helperText), [textareaId, error, helperText])

  return (
    <div className="w-full">
      {label && <TextareaLabel textareaId={textareaId} label={label} />}
      <div className="relative">
        <TextareaIcons leftIcon={leftIcon} rightIcon={rightIcon} />
        <textarea
          id={textareaId}
          className={textareaClasses}
          aria-invalid={error ? 'true' : 'false'}
          aria-describedby={ariaDescribedBy}
          {...props}
        />
      </div>
      {error && <TextareaError textareaId={textareaId} error={error} />}
      {helperText && !error && <TextareaHelper textareaId={textareaId} helperText={helperText} />}
    </div>
  )
}
