import { useEffect, useState } from 'react'

import { cn } from '@/lib/utils'

import type { ComponentPropsWithoutRef, FC, FocusEvent } from 'react'


const pad = (n: number): string => n.toString ().padStart (2, '0')


const toDateTimeLocalValue = (value: Date) => {
  const y = value.getFullYear ()
  const m = pad (value.getMonth () + 1)
  const day = pad (value.getDate ())
  const h = pad (value.getHours ())
  const min = pad (value.getMinutes ())
  return `${ y }-${ m }-${ day }T${ h }:${ min }`
}


const toMinutePrecisionIsoUtc = (value: string) => {
  const date = new Date (value)
  if (Number.isNaN (date.getTime ()))
    return value

  const y = date.getUTCFullYear ()
  const m = pad (date.getUTCMonth () + 1)
  const day = pad (date.getUTCDate ())
  const h = pad (date.getUTCHours ())
  const min = pad (date.getUTCMinutes ())
  return `${ y }-${ m }-${ day }T${ h }:${ min }Z`
}


type Props = Omit<ComponentPropsWithoutRef<'input'>, 'onChange'> & {
    value?:     string
    onChange?:  (isoUTC: string | null) => void
    className?: string
    onBlur?:    (ev: FocusEvent<HTMLInputElement>) => void
    invalid?:   boolean }


const DateTimeField: FC<Props> = ({ value, onChange, className, onBlur, invalid, ...rest }) => {
  const [local, setLocal] = useState ('')

  useEffect (() => {
    setLocal (value ? toDateTimeLocalValue (new Date (value)) : '')
  }, [value])

  return (
      <input
	  {...rest}
	  className={cn ('border rounded p-2',
			 (invalid
			  ? ['border-red-500 bg-red-50 text-red-900',
			     'focus:border-red-500 focus:outline-none',
			     'focus:ring-2 focus:ring-red-200',
			     'dark:border-red-500 dark:bg-red-950/30 dark:text-red-100']
			  : ['border-gray-300',
			     'focus:border-blue-500 focus:outline-none',
			     'focus:ring-2 focus:ring-blue-200']),
			 className)}
	  type="datetime-local"
	  step={60}
	  value={local}
	  aria-invalid={invalid}
	  onChange={ev => {
	    const v = ev.target.value
	    setLocal (v)
	    onChange?.(v ? toMinutePrecisionIsoUtc (v) : null)
	  }}
	  onBlur={onBlur}/>)
}

export default DateTimeField
export { toMinutePrecisionIsoUtc }
