'use client';

/* IMPORT */
import { format } from 'date-fns';
import { Button, type ButtonProps } from '@/components/ui/button';
import { Calendar } from '@/components/ui/calendar';
import { CalendarIcon, X } from 'lucide-react';
import { cn } from '@/lib/utils';
import { parseAsString, useQueryStates } from 'nuqs';
import {
  Popover,
  PopoverContent,
  PopoverTrigger,
} from '@/components/ui/popover';
import { type ComponentPropsWithoutRef, type MouseEvent, useMemo } from 'react';
import { type DateRange } from 'react-day-picker';

// ----------------------------------------------------------------------------------------------------

/* TYPES */
interface RisksDateRangePickerProps extends ComponentPropsWithoutRef<typeof PopoverContent> {
  defaultDateRange?: DateRange;
  placeholder?: string;
  triggerVariant?: Exclude<ButtonProps['variant'], 'destructive' | 'link'>;
  triggerSize?: Exclude<ButtonProps['size'], 'icon'>;
  triggerClassName?: string;
  shallow?: boolean;
  showClearButton?: boolean;
}

// ----------------------------------------------------------------------------------------------------

/* RISKS DATE RANGE PICKER COMPONENT */
function RisksDateRangePicker(props: RisksDateRangePickerProps) {
  const {
    defaultDateRange,
    placeholder = '날짜를 선택하십시오.',
    triggerVariant = 'outline',
    triggerSize = 'default',
    triggerClassName,
    showClearButton = false,
    shallow = true,
    className,
    ...otherProps
  } = props;
  const [dateParams, setDateParams] = useQueryStates(
    {
      from: parseAsString.withDefault(
        defaultDateRange?.from?.toISOString() ?? ''
      ),
      to: parseAsString.withDefault(defaultDateRange?.to?.toISOString() ?? ''),
    },
    {
      clearOnDefault: true,
      shallow,
    }
  )

  const date = useMemo(() => {
    function parseDate(dateString: string | null) {
      if (!dateString) {
        return undefined;
      }
      const parsedDate = new Date(dateString);
      return isNaN(parsedDate.getTime()) ? undefined : parsedDate;
    }

    return {
      from: parseDate(dateParams.from) ?? defaultDateRange?.from,
      to: parseDate(dateParams.to) ?? defaultDateRange?.to,
    };
  }, [dateParams, defaultDateRange]);

  const clearDates = (e: MouseEvent) => {
    e.stopPropagation();
    void setDateParams({
      from: "",
      to: "",
    });
  };

  const hasSelectedDate = Boolean(date?.from || date?.to);

  return (
    <div className="grid gap-2">
      <Popover>
        <PopoverTrigger asChild>
          <Button
            variant={triggerVariant}
            size={triggerSize}
            className={cn(
              'relative w-full justify-start gap-2 truncate text-left font-normal',
              !date && 'text-muted-foreground',
              triggerClassName
            )}
          >
            <CalendarIcon className="size-4" />
            {date?.from ? (
              date.to ? (
                <>
                  {format(date.from, 'LLL dd, y')} -{' '}
                  {format(date.to, 'LLL dd, y')}
                </>
              ) : (
                format(date.from, 'LLL dd, y')
              )
            ) : (
              <span>{placeholder}</span>
            )}

            {showClearButton && hasSelectedDate && (
              <Button
                type="button"
                variant="ghost"
                size="icon"
                className="absolute right-0 top-0 h-full rounded-l-none px-3 hover:bg-background"
                onClick={clearDates}
              >
                <X className="size-4" />
                <span className="sr-only">초기화</span>
              </Button>
            )}
          </Button>
        </PopoverTrigger>
        <PopoverContent className={cn("w-auto p-0", className)} {...otherProps}>
          <Calendar
            initialFocus
            mode="range"
            defaultMonth={date?.from}
            selected={date?.from && date?.to ? date : undefined}
            onSelect={(newDateRange) => {
              const from = newDateRange?.from;
              const to = newDateRange?.to;

              if (from && to && from > to) {
                void setDateParams({
                  from: to.toISOString(),
                  to: from.toISOString(),
                });
              } else {
                void setDateParams({
                  from: from?.toISOString() ?? '',
                  to: to?.toISOString() ?? '',
                });
              }
            }}
            numberOfMonths={2}
          />
        </PopoverContent>
      </Popover>
    </div>
  )
}

// ----------------------------------------------------------------------------------------------------

export default RisksDateRangePicker;
