'use client';

import {
  ChangeEvent,
  ChangeEventHandler,
  FocusEventHandler,
  ReactNode,
  useEffect,
  useRef,
  useState,
} from 'react';

import { cn } from '@/lib/helper';
import Inputmask from 'inputmask';

const createInputMask = (
  maskType: MaskType,
  decimals: number,
  thousandSeparator: string,
  decimalSeparator: string,
  allowNegative: boolean,
  oncomplete?: () => void,
  onincomplete?: () => void,
  oncleared?: () => void
): Inputmask.Instance => {
  const options: Inputmask.Options = {
    alias: 'numeric',
    groupSeparator: thousandSeparator,
    radixPoint: decimalSeparator,
    digits: decimals,
    allowMinus: allowNegative,
    rightAlign: false,
    insertMode: true,
    autoUnmask: false,
    clearMaskOnLostFocus: false,
    digitsOptional: decimals > 0,
    placeholder: '0',
    numericInput: false,
    positionCaretOnClick: 'radixFocus',
    greedy: true,
    oncomplete,
    onincomplete,
    oncleared
  };

  return new Inputmask(options);
};

export type MaskType = 'currency' | 'weight' | 'decimal' | 'number' | 'text';

export interface NumberInputProps {
  label?: string;
  bottomLabel?: string;
  name: string;
  value?: number | string;
  placeholder?: string;

  className?: {
    wrapper?: string;
    label?: string;
    inputWrapper?: string;
    input?: string;
  };

  isError?: boolean;
  isValid?: boolean;
  errorMessage?: string;
  disabled?: boolean;
  readOnly?: boolean;
  required?: boolean;
  isLoading?: boolean;

  startAdornment?: ReactNode;
  endAdornment?: ReactNode;

  onChange?: ChangeEventHandler<HTMLInputElement>;
  onBlur?: FocusEventHandler<HTMLInputElement>;
  onFocus?: FocusEventHandler<HTMLInputElement>;

  maskType?: MaskType;
  decimals?: number;
  thousandSeparator?: string;
  decimalSeparator?: string;
  currencyPrefix?: string;
  weightUnit?: string;

  min?: number;
  max?: number;
  allowNegative?: boolean;

  oncomplete?: () => void;
  onincomplete?: () => void;
  oncleared?: () => void;
}

const NumberInput = ({
                       label,
                       bottomLabel,
                       name,
                       value,
                       placeholder,
                       className,
                       isError,
                       isValid,
                       errorMessage,
                       startAdornment,
                       endAdornment,
                       disabled = false,
                       required = false,
                       onChange,
                       onBlur,
                       onFocus,
                       readOnly = false,
                       isLoading = false,
                       maskType = 'number',
                       decimals = 0,
                       thousandSeparator = ',',
                       decimalSeparator = '.',
                       currencyPrefix = 'Rp ',
                       weightUnit = 'kg',
                       allowNegative = false,
                       oncomplete,
                       onincomplete,
                       oncleared,
                     }: NumberInputProps) => {
  const inputRef = useRef<HTMLInputElement>(null);
  const inputmaskRef = useRef<Inputmask.Instance | null>(null);
  const [maskComplete, setMaskComplete] = useState<boolean>(false);
  const [maskIncomplete, setMaskIncomplete] = useState<boolean>(false);
  const [maskCleared, setMaskCleared] = useState<boolean>(false);

  const getInputPrefix = (): string => {
    switch (maskType) {
      case 'currency':
        return currencyPrefix;
      default:
        return '';
    }
  };

  const getInputSuffix = (): string => {
    switch (maskType) {
      case 'weight':
        return weightUnit;
      default:
        return '';
    }
  };

  useEffect(() => {
    if (inputRef.current && !readOnly && !disabled) {
      if (inputmaskRef.current) {
        try {
          inputmaskRef.current.remove();
        } catch (error) {
          console.warn('Error removing Inputmask:', error);
        }
      }

      const handleComplete = () => {
        setMaskComplete(true);
        setMaskIncomplete(false);
        setMaskCleared(false);
        if (oncomplete) oncomplete();
      };

      const handleIncomplete = () => {
        setMaskIncomplete(true);
        setMaskComplete(false);
        setMaskCleared(false);
        if (onincomplete) onincomplete();
      };

      const handleCleared = () => {
        setMaskCleared(true);
        setMaskComplete(false);
        setMaskIncomplete(false);
        if (oncleared) oncleared();
      };

          const im = createInputMask(
        maskType,
        decimals,
        ',',
        '.',
        allowNegative,
        handleComplete,
        handleIncomplete,
        handleCleared
      );

      try {
        im.mask(inputRef.current);
        inputmaskRef.current = im;
      } catch (error) {
        console.warn('Error applying Inputmask:', error);
        inputmaskRef.current = null;
      }
    }

    return () => {
      if (inputmaskRef.current) {
        try {
          inputmaskRef.current.remove();
        } catch (error) {
          console.warn('Error removing Inputmask on cleanup:', error);
        }
      }
    };
  }, [maskType, decimals, thousandSeparator, decimalSeparator, allowNegative, readOnly, disabled, oncomplete, onincomplete, oncleared]);

  useEffect(() => {
    if (inputRef.current && value !== undefined) {
      if (value === null || value === '') {
        inputRef.current.value = '';
      } else {
        inputRef.current.value = String(value);
      }
    }
  }, [value]);

  const handleKeyUp = (e: React.KeyboardEvent<HTMLInputElement>) => {
    const currentValue = (e.currentTarget as HTMLInputElement).value;
    console.log('✅ After format:', currentValue);

    if (onChange) {
      const syntheticEvent = {
        target: {
          name,
          value: currentValue,
        },
      } as ChangeEvent<HTMLInputElement>;
      onChange(syntheticEvent);
    }
  };

  const inputPrefix = getInputPrefix();
  const inputSuffix = getInputSuffix();

  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': isError,
            },
            className?.label
          )}
        >
          {label}
          {required && (
            <>
              {' '}
              <span className='tooltip tooltip-error' data-tip='required'>
                <span className='text-error'> *</span>
              </span>
            </>
          )}
        </label>
      )}

      <div className='relative flex'>
        {inputPrefix && (
          <div
            className={cn(
              'inline-flex items-center px-4 py-2 border border-r-0 rounded-l-md transition-all duration-200',
              {
                'bg-gray-100 border-gray-300': !disabled,
                'bg-gray-50 border-gray-200': disabled,
              }
            )}
          >
            <span
              className={cn(
                'text-sm font-medium select-none whitespace-nowrap',
                {
                  'text-gray-600': !disabled,
                  'text-gray-400': disabled,
                }
              )}
            >
              {inputPrefix}
            </span>
          </div>
        )}

        <div
          className={cn(
            'input h-12 text-base font-normal leading-6 flex-1 rounded-lg! outline-none! transition-all duration-200 flex items-center bg-white',
            {
              'border-error': isError,
              'border-success!': isValid,
              'rounded-l-none!': inputPrefix,
              'rounded-r-none!': inputSuffix,
              'input-disabled': disabled,
              'cursor-not-allowed': disabled,
              'bg-gray-50': disabled,
            },
            className?.inputWrapper
          )}
        >
          {startAdornment && startAdornment}

          <input
            type='text'
            id={name}
            name={name}
            ref={inputRef}
            placeholder={placeholder || '0'}
            onKeyUp={handleKeyUp}
            onFocus={onFocus}
            onBlur={onBlur}
            disabled={disabled}
            className={cn(
              'grow bg-transparent outline-none',
              {
                'cursor-not-allowed': disabled,
                'text-gray-500': disabled,
              },
              className?.input
            )}
            readOnly={readOnly}
            inputMode='text'
            autoComplete='off'
            spellCheck={false}
          />

          {(isLoading || endAdornment) && (
            <div className='flex flex-row gap-2'>
              {isLoading && <span className='loading loading-spinner' />}
              {endAdornment && endAdornment}
            </div>
          )}
        </div>

        {inputSuffix && (
          <div
            className={cn(
              'inline-flex items-center px-4 py-2 border border-l-0 rounded-r-md transition-all duration-200',
              {
                'bg-gray-100 border-gray-300': !disabled,
                'bg-gray-50 border-gray-200': disabled,
              }
            )}
          >
            <span
              className={cn(
                'text-sm font-medium select-none whitespace-nowrap',
                {
                  'text-gray-600': !disabled,
                  'text-gray-400': disabled,
                }
              )}
            >
              {inputSuffix}
            </span>
          </div>
        )}
      </div>

      {(maskType === 'text' || (oncomplete || onincomplete || oncleared)) && (
        <div className='flex gap-2 text-xs'>
          <span
            className={cn(
              'px-2 py-1 rounded transition-all duration-200',
              maskComplete
                ? 'bg-green-100 text-green-700 border border-green-200'
                : 'bg-gray-50 text-gray-400 border border-gray-200'
            )}
          >
            Complete
          </span>
          <span
            className={cn(
              'px-2 py-1 rounded transition-all duration-200',
              maskIncomplete
                ? 'bg-yellow-100 text-yellow-700 border border-yellow-200'
                : 'bg-gray-50 text-gray-400 border border-gray-200'
            )}
          >
            Incomplete
          </span>
          <span
            className={cn(
              'px-2 py-1 rounded transition-all duration-200',
              maskCleared
                ? 'bg-blue-100 text-blue-700 border border-blue-200'
                : 'bg-gray-50 text-gray-400 border border-gray-200'
            )}
          >
            Cleared
          </span>
        </div>
      )}

      {!isError && bottomLabel && (
        <p className='w-full text-sm opacity-60'>{bottomLabel}</p>
      )}
      {isError && errorMessage && (
        <p className='w-full text-sm text-error'>{errorMessage}</p>
      )}
    </div>
  );
};

export default NumberInput;

