import { forwardRef, useId, useRef, useEffect, type InputHTMLAttributes } from 'react'
import { cn } from '@/lib/utils'

export interface CheckboxProps
  extends Omit<InputHTMLAttributes<HTMLInputElement>, 'type' | 'size'> {
  label?: string
  description?: string
  error?: string
  indeterminate?: boolean
}

export const Checkbox = forwardRef<HTMLInputElement, CheckboxProps>(
  (
    {
      label,
      description,
      error,
      indeterminate = false,
      disabled,
      className,
      id: idProp,
      ...props
    },
    forwardedRef,
  ) => {
    const autoId = useId()
    const id = idProp ?? autoId
    const descriptionId = `${id}-description`
    const errorId = `${id}-error`
    const internalRef = useRef<HTMLInputElement>(null)
    const hasError = !!error

    useEffect(() => {
      const el = internalRef.current
      if (el) el.indeterminate = indeterminate
    }, [indeterminate])

    const describedBy =
      [description ? descriptionId : undefined, hasError ? errorId : undefined]
        .filter(Boolean)
        .join(' ') || undefined

    return (
      <div className={cn('flex gap-2', className)}>
        <div className="flex h-6 items-center">
          <input
            ref={(node) => {
              (internalRef as React.MutableRefObject<HTMLInputElement | null>).current = node
              if (typeof forwardedRef === 'function') forwardedRef(node)
              else if (forwardedRef) forwardedRef.current = node
            }}
            type="checkbox"
            id={id}
            disabled={disabled}
            aria-invalid={hasError || undefined}
            aria-describedby={describedBy}
            className={cn(
              'peer size-5 cursor-pointer appearance-none rounded-[3px] border-2 border-control-border bg-control-bg transition-colors',
              'hover:border-control-border-hover',
              'checked:border-control-checked checked:bg-control-checked',
              'checked:hover:border-control-checked-hover checked:hover:bg-control-checked-hover',
              'indeterminate:border-control-checked indeterminate:bg-control-checked',
              'indeterminate:hover:border-control-checked-hover indeterminate:hover:bg-control-checked-hover',
              'focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-control-focus-ring focus-visible:ring-offset-1',
              'active:scale-95',
              'disabled:pointer-events-none disabled:opacity-50',
              hasError &&
                'border-control-error hover:border-control-error checked:border-control-error checked:bg-control-error checked:hover:border-control-error checked:hover:bg-control-error focus-visible:ring-red-03',
            )}
            {...props}
          />
          <svg
            className="pointer-events-none absolute size-5 text-white opacity-0 peer-checked:opacity-100 peer-indeterminate:hidden"
            viewBox="0 0 20 20"
            fill="none"
            stroke="currentColor"
            strokeWidth={3}
            strokeLinecap="round"
            strokeLinejoin="round"
            aria-hidden="true"
          >
            <polyline points="4.5 10.5 8 14 15.5 6.5" />
          </svg>
          <svg
            className="pointer-events-none absolute size-5 text-white opacity-0 peer-indeterminate:opacity-100"
            viewBox="0 0 20 20"
            fill="none"
            stroke="currentColor"
            strokeWidth={3}
            strokeLinecap="round"
            aria-hidden="true"
          >
            <line x1="5" y1="10" x2="15" y2="10" />
          </svg>
        </div>

        {(label || description || hasError) && (
          <div className="flex flex-col gap-0.5 pt-px">
            {label && (
              <label
                htmlFor={id}
                className={cn(
                  'cursor-pointer text-body font-normal text-grey-01',
                  disabled && 'pointer-events-none opacity-50',
                )}
              >
                {label}
              </label>
            )}
            {description && (
              <p
                id={descriptionId}
                className={cn('text-small text-text', disabled && 'opacity-50')}
              >
                {description}
              </p>
            )}
            {hasError && (
              <div id={errorId} className="flex items-center gap-1 text-small text-control-error">
                <svg
                  className="size-4 shrink-0"
                  viewBox="0 0 24 24"
                  fill="none"
                  stroke="currentColor"
                  strokeWidth={2}
                  strokeLinecap="round"
                  strokeLinejoin="round"
                  aria-hidden="true"
                >
                  <circle cx="12" cy="12" r="10" />
                  <line x1="12" y1="8" x2="12" y2="12" />
                  <line x1="12" y1="16" x2="12.01" y2="16" />
                </svg>
                <p>{error}</p>
              </div>
            )}
          </div>
        )}
      </div>
    )
  },
)

Checkbox.displayName = 'Checkbox'
