'use client';

import {
  ChangeEventHandler,
  FocusEventHandler,
  useEffect,
  useState,
} from 'react';
import { cn, formatDate } from '@/lib/helper';
import Modal, { useModal } from '../Modal';
import { DateRange, DayPicker, Matcher } from 'react-day-picker';
import 'react-day-picker/dist/style.css';
import Button from '../Button';
import { Icon } from '@iconify/react';

export interface DateInputProps {
  label?: string;
  bottomLabel?: string;
  name: string;
  value?: string | { from?: string; to?: string };
  placeholder?: string;
  min?: string;
  max?: string;
  className?: {
    wrapper?: string;
    label?: string;
    inputWrapper?: string;
    input?: string;
  };
  isError?: boolean;
  isValid?: boolean;
  disabled?: boolean;
  readOnly?: boolean;
  required?: boolean;
  isLoading?: boolean;
  isRange?: boolean;
  isNestedModal?: boolean; // New prop to indicate if used inside another modal
  errorMessage?: string;
  onChange?: ChangeEventHandler<HTMLInputElement>;
  onBlur?: FocusEventHandler<HTMLInputElement>;
}

const DateInput = ({
  label,
  bottomLabel,
  name,
  value,
  placeholder = 'dd/mm/yyyy',
  min,
  max,
  className,
  isError: externalError,
  isValid: externalValid,
  errorMessage: externalErrorMessage,
  disabled = false,
  required = false,
  onChange,
  onBlur,
  readOnly = false,
  isLoading = false,
  isRange = false,
  isNestedModal = false,
}: DateInputProps) => {
  const [internalError, setInternalError] = useState<string | null>(null);
  const [selected, setSelected] = useState<Date | undefined>();
  const [selectedRange, setSelectedRange] = useState<{
    from?: Date;
    to?: Date;
  }>({});
  const [displayValue, setDisplayValue] = useState<string>('');

  const minDate = min
    ? new Date(min.split('/').reverse().join('-'))
    : undefined;
  const maxDate = max
    ? new Date(max.split('/').reverse().join('-'))
    : undefined;

  const calendarModal = useModal(isNestedModal);

  // --- Sync value props ---
  useEffect(() => {
    if (!value) {
      setDisplayValue('');
      return;
    }
    if (isRange && typeof value === 'object') {
      const from = value.from ? new Date(value.from) : undefined;
      const to = value.to ? new Date(value.to) : undefined;
      setSelectedRange({ from, to });
      setDisplayValue(
        `${from ? formatDate(from, 'DD/MM/YYYY') : ''} ${
          to ? '- ' + formatDate(to, 'DD/MM/YYYY') : ''
        }`
      );
    } else if (typeof value === 'string') {
      const iso = value.includes('/')
        ? value.split('/').reverse().join('-')
        : value;
      const date = new Date(iso);
      setSelected(date);
      setDisplayValue(formatDate(iso, 'DD/MM/YYYY'));
    }
  }, [value, isRange]);

  const handleClick = (e: React.MouseEvent<HTMLInputElement>) => {
    e.preventDefault();
    if (!disabled && !readOnly) calendarModal.openModal();
  };

  const handleBlur: FocusEventHandler<HTMLInputElement> = (e) => {
    onBlur?.(e);
  };

  const handleSelectSingle = (selectedDate?: Date) => {
    if (!selectedDate) return;
    if (minDate && selectedDate < minDate) {
      setInternalError(`Tanggal tidak boleh sebelum ${min}`);
      return;
    }
    if (maxDate && selectedDate > maxDate) {
      setInternalError(`Tanggal tidak boleh setelah ${max}`);
      return;
    }
    setInternalError(null);
    setSelected(selectedDate);
    const formattedDisplay = formatDate(selectedDate, 'DD/MM/YYYY');
    const formattedISO = formatDate(selectedDate, 'YYYY-MM-DD');
    setDisplayValue(formattedDisplay);

    const syntheticEvent = {
      target: { name, value: formattedISO },
    } as unknown as React.ChangeEvent<HTMLInputElement>;
    onChange?.(syntheticEvent);
    calendarModal.closeModal();
  };

  const handleSelectRange = (range?: { from?: Date; to?: Date }) => {
    if (!range) return;
    setSelectedRange(range);

    const fromStr = range.from ? formatDate(range.from, 'DD/MM/YYYY') : '';
    const toStr = range.to ? formatDate(range.to, 'DD/MM/YYYY') : '';
    setDisplayValue(`${fromStr}${toStr ? ' - ' + toStr : ''}`);

    // Jika kedua tanggal sudah terpilih
    if (range.from && range.to) {
      if (minDate && range.from < minDate) {
        setInternalError(`Tanggal mulai tidak boleh sebelum ${min}`);
        return;
      }
      if (maxDate && range.to > maxDate) {
        setInternalError(`Tanggal akhir tidak boleh setelah ${max}`);
        return;
      }

      setInternalError(null);
      const syntheticEvent = {
        target: {
          name,
          value: {
            from: formatDate(range.from, 'YYYY-MM-DD'),
            to: formatDate(range.to, 'YYYY-MM-DD'),
          },
        },
      } as unknown as React.ChangeEvent<HTMLInputElement>;
      onChange?.(syntheticEvent);
    }
  };

  const handleResetDate = () => {
    setSelected(undefined);
    setSelectedRange({});
    setDisplayValue('');
    const syntheticEvent = {
      target: { name, value: isRange ? { from: '', to: '' } : '' },
    } as unknown as React.ChangeEvent<HTMLInputElement>;
    onChange?.(syntheticEvent);
    calendarModal.closeModal();
  };

  const handleSaveDate = () => {
    if (internalError) return;
    calendarModal.closeModal();
  };

  const finalIsError = externalError || !!internalError;
  const finalErrorMessage = internalError || externalErrorMessage;

  return (
    <div
      className={cn(
        'w-full flex flex-col gap-2 text-start',
        className?.wrapper
      )}
    >
      {label && (
        <label
          htmlFor={name}
          className={cn(
            'w-full text-sm font-normal leading-5',
            { 'text-error': finalIsError },
            className?.label
          )}
        >
          {label}
          {required && (
            <span className='text-error' title='required'>
              {' '}
              *
            </span>
          )}
        </label>
      )}

      <div
        className={cn(
          'input h-12 px-4 py-2 text-base font-normal leading-6 w-full rounded transition-all duration-200 flex items-center border',
          {
            'border-error': finalIsError,
            'border-success': externalValid && !finalIsError,
          },
          className?.inputWrapper
        )}
      >
        <input
          type='text'
          id={name}
          name={name}
          placeholder={isRange ? 'dd/mm/yyyy - dd/mm/yyyy' : placeholder}
          value={displayValue}
          onBlur={handleBlur}
          onClick={handleClick}
          disabled={disabled}
          readOnly // ✅ tidak bisa diketik manual
          className={cn(
            'grow bg-transparent cursor-pointer focus:outline-none',
            className?.input
          )}
        />

        {isLoading && (
          <div className='flex flex-row gap-2'>
            <span className='loading loading-spinner' />
          </div>
        )}
        <Icon
          icon='uil:calendar'
          width={24}
          height={24}
          className='cursor-pointer text-dark'
          onClick={(e) =>
            handleClick(e as unknown as React.MouseEvent<HTMLInputElement>)
          }
        />
      </div>

      {!finalIsError && bottomLabel && (
        <p className='w-full text-sm opacity-60'>{bottomLabel}</p>
      )}
      {finalIsError && finalErrorMessage && (
        <p className='w-full text-sm text-error'>{finalErrorMessage}</p>
      )}

      <Modal
        ref={calendarModal.ref}
        className={{
          modal: 'rounded',
          modalBox: `!max-w-max min-h-${isRange ? '124' : '110'} flex flex-col`,
        }}
        closeOnBackdrop
      >
        {isRange ? (
          <DayPicker
            required={required}
            mode='range'
            captionLayout='dropdown-years'
            navLayout='around'
            reverseYears
            defaultMonth={selectedRange.from ?? new Date()}
            startMonth={minDate ?? new Date(1999, 1)}
            endMonth={maxDate ?? new Date(new Date().getFullYear() + 5, 11)}
            selected={selectedRange as DateRange}
            onSelect={handleSelectRange}
            footer={<div className='text-center mt-3'>{displayValue}</div>}
            disabled={
              [
                minDate ? { before: minDate } : undefined,
                maxDate ? { after: maxDate } : undefined,
              ].filter(Boolean) as Matcher[]
            }
          />
        ) : (
          <DayPicker
            required={required}
            mode='single'
            captionLayout='dropdown-years'
            navLayout='around'
            reverseYears
            defaultMonth={selected ?? new Date()}
            startMonth={minDate ?? new Date(1999, 1)}
            endMonth={maxDate ?? new Date(new Date().getFullYear() + 5, 11)}
            selected={selected}
            onSelect={handleSelectSingle}
            disabled={
              [
                minDate ? { before: minDate } : undefined,
                maxDate ? { after: maxDate } : undefined,
              ].filter(Boolean) as Matcher[]
            }
          />
        )}
        <div className='mt-auto flex flex-col gap-2'>
          {isRange && (
            <small className='text-secondary'>
              Tekan dua kali untuk memilih tanggal awal
            </small>
          )}

          <div className='flex h-full justify-end items-end gap-2'>
            <Button type='button' color='warning' onClick={handleResetDate}>
              Reset
            </Button>
            {isRange && (
              <Button type='button' onClick={handleSaveDate}>
                Simpan
              </Button>
            )}
          </div>
        </div>
      </Modal>
    </div>
  );
};

export default DateInput;
