import { useEffect, useId, useRef, useState } from 'react';
import { useTranslation } from 'react-i18next';
import { CalendarIcon } from 'lucide-react';
import { useFormatPrefs, formatDate } from '@/lib/date';
import { parseDate, type DateKeywords } from '@/lib/parseDate';
import { Input } from '@/components/ui/input';
import { Button } from '@/components/ui/button';
import { Popover, PopoverContent, PopoverTrigger } from '@/components/ui/popover';
import { Calendar } from '@/components/ui/calendar';
import { cn } from '@/lib/utils';

export type DateFieldProps = {
  value: Date | undefined;
  onChange: (d: Date | undefined) => void;
  onCommit?: (d: Date) => void;
  placeholder?: string;
  minDate?: Date;
  autoFocus?: boolean;
  invalidMessage?: string;
  className?: string;
  'aria-label'?: string;
  id?: string;
};

export function DateField({
  value,
  onChange,
  onCommit,
  placeholder,
  minDate,
  autoFocus,
  invalidMessage,
  className,
  id,
  ...rest
}: DateFieldProps) {
  const reactId = useId();
  const fieldId = id ?? reactId;
  const errorId = `${fieldId}-error`;

  const { t, i18n } = useTranslation();
  const prefs = useFormatPrefs();
  const [text, setText] = useState<string>(value ? formatDate(value.getTime(), prefs) : '');
  const [focused, setFocused] = useState(false);
  const [invalid, setInvalid] = useState(false);
  const [open, setOpen] = useState(false);
  const inputRef = useRef<HTMLInputElement>(null);

  useEffect(() => {
    if (!focused) {
      setText(value ? formatDate(value.getTime(), prefs) : '');
      setInvalid(false);
    }
  }, [value, focused, prefs]);

  function getKeywords(): DateKeywords {
    const today = i18n.t('date.keyword.today', { returnObjects: true }) as unknown;
    const tomorrow = i18n.t('date.keyword.tomorrow', { returnObjects: true }) as unknown;
    const yesterday = i18n.t('date.keyword.yesterday', { returnObjects: true }) as unknown;
    const weekdays = i18n.t('date.keyword.weekdays', { returnObjects: true }) as unknown;
    return {
      today: Array.isArray(today) ? (today as string[]) : ['today'],
      tomorrow: Array.isArray(tomorrow) ? (tomorrow as string[]) : ['tomorrow'],
      yesterday: Array.isArray(yesterday) ? (yesterday as string[]) : ['yesterday'],
      weekdays: Array.isArray(weekdays)
        ? (weekdays as string[][])
        : [['sun'],['mon'],['tue'],['wed'],['thu'],['fri'],['sat']],
    };
  }

  function tryParse(raw: string): Date | null {
    const parsed = parseDate(raw, prefs, getKeywords());
    if (!parsed) return null;
    if (minDate && parsed < new Date(minDate.getFullYear(), minDate.getMonth(), minDate.getDate())) {
      return null;
    }
    return parsed;
  }

  function commit(raw: string, fireCommit: boolean) {
    if (!raw.trim()) {
      onChange(undefined);
      setInvalid(false);
      return;
    }
    const parsed = tryParse(raw);
    if (parsed) {
      setInvalid(false);
      onChange(parsed);
      if (fireCommit) onCommit?.(parsed);
    } else {
      setInvalid(true);
    }
  }

  return (
    <div className={cn('relative', className)}>
      <Input
        ref={inputRef}
        id={fieldId}
        autoFocus={autoFocus}
        placeholder={placeholder ?? t('timeline.pickDate')}
        value={text}
        onChange={(e) => {
          setText(e.target.value);
          setInvalid(false);
        }}
        onFocus={() => setFocused(true)}
        onBlur={() => {
          setFocused(false);
          commit(text, false);
        }}
        onKeyDown={(e) => {
          if (e.key === 'Enter') {
            e.preventDefault();
            commit(text, true);
          } else if (e.altKey && e.key === 'ArrowDown') {
            e.preventDefault();
            setOpen(true);
          }
        }}
        aria-invalid={invalid || !!invalidMessage}
        aria-describedby={invalidMessage ? errorId : undefined}
        aria-label={rest['aria-label']}
        className={cn('pr-8', (invalid || !!invalidMessage) && 'ring-1 ring-destructive')}
      />
      <Popover open={open} onOpenChange={setOpen}>
        <PopoverTrigger asChild>
          <Button
            type="button"
            variant="ghost"
            size="icon"
            className="absolute right-0 top-0 h-full w-8 text-muted-foreground hover:text-foreground"
            aria-label={t('timeline.pickDate')}
            tabIndex={-1}
            onMouseDown={(e) => e.preventDefault()}
          >
            <CalendarIcon className="h-4 w-4" />
          </Button>
        </PopoverTrigger>
        <PopoverContent className="w-auto p-0" align="end">
          <Calendar
            mode="single"
            selected={value}
            onSelect={(d) => {
              if (d) {
                onChange(d);
                setText(formatDate(d.getTime(), prefs));
                setInvalid(false);
                onCommit?.(d);
              }
              setOpen(false);
              inputRef.current?.focus();
            }}
            disabled={minDate ? { before: minDate } : undefined}
          />
        </PopoverContent>
      </Popover>
      {invalidMessage && (
        <p id={errorId} className="mt-1 text-xs text-destructive">{invalidMessage}</p>
      )}
    </div>
  );
}
