import React, { useCallback, useRef, useState } from 'react';
import {
  CellTextInput,
  CellAutoCompleteInput,
  type CellAutoCompleteHandle,
} from '@wix/patterns-fields';
import type { CellEditProps } from '../../types';
import type { ValidationRule } from '../../../../state/EditableTable/types';
import { useCloseOnAncestorScroll } from '../../../../hooks/useCloseOnAncestorScroll';
import { st, classes } from './Edit.st.css.js';

function getMaxLength(validation?: ValidationRule[]) {
  return validation?.find(
    (r): r is { type: 'maxLength'; value: number; message: string } =>
      r.type === 'maxLength',
  )?.value;
}

function getSpecificValues(validation?: ValidationRule[]) {
  return validation?.find(
    (
      r,
    ): r is {
      type: 'specificValues';
      values: { id: string; value: string }[];
      message: string;
    } => r.type === 'specificValues',
  )?.values;
}

// Plain text mode
const TextEditPlain: React.FC<CellEditProps<string>> = ({
  value,
  onChange,
  onCommit,
  onCancel,
  inputRef,
  validation,
}) => {
  const maxLength = getMaxLength(validation);
  const [isFocused, setIsFocused] = useState(false);

  const handleKeyDown = useCallback(
    (e: React.KeyboardEvent) => {
      if (e.key === 'Enter' && !e.shiftKey) {
        e.preventDefault();
        onCommit();
      } else if (e.key === 'Escape') {
        e.preventDefault();
        onCancel();
      }
    },
    [onCommit, onCancel],
  );

  const handleFocus = useCallback(() => setIsFocused(true), []);
  const handleBlur = useCallback(() => {
    setIsFocused(false);
    onCommit();
  }, [onCommit]);

  return (
    <div className={classes.editWrapper}>
      <CellTextInput
        inputRef={inputRef}
        value={value ?? ''}
        onChange={onChange}
        onFocus={handleFocus}
        onBlur={handleBlur}
        onKeyDown={handleKeyDown}
        maxLength={maxLength}
        className={st(classes.inputArea, { isFocused })}
      />
    </div>
  );
};

// Specific values mode — autocomplete with a closed list of options
const TextEditSpecificValues: React.FC<
  CellEditProps<string> & { options: { id: string; value: string }[] }
> = ({
  value,
  onChange,
  onCommit,
  onCancel,
  inputRef,
  editTrigger,
  options,
}) => {
  const acHandle = useRef<CellAutoCompleteHandle | null>(null);
  const wrapperRef = useRef<HTMLDivElement | null>(null);

  const closeDropdown = useCallback(() => acHandle.current?.hideOptions(), []);
  useCloseOnAncestorScroll(wrapperRef, closeDropdown, !!editTrigger);

  // Set in capture phase on ArrowUp/Down so onOptionMarked only updates
  // editingValue for explicit arrow navigation — not for auto-highlight on open.
  const isArrowNavRef = useRef(false);

  const handleSelect = useCallback(
    (id: string) => {
      onChange(id);
      onCommit();
    },
    [onChange, onCommit],
  );

  const handleClear = useCallback(() => onChange(''), [onChange]);

  const handleOptionMarked = useCallback(
    (id: string | null) => {
      if (id && isArrowNavRef.current) {
        onChange(id);
        isArrowNavRef.current = false;
      }
    },
    [onChange],
  );

  // Capture phase: set arrow-nav flag before AutoComplete fires onOptionMarked,
  // and cancel on Escape before the dropdown processes it.
  const handleKeyDownCapture = useCallback(
    (e: React.KeyboardEvent) => {
      if (e.key === 'Escape') {
        e.preventDefault();
        e.stopPropagation();
        onCancel();
      } else if (e.key === 'ArrowDown' || e.key === 'ArrowUp') {
        isArrowNavRef.current = true;
      }
    },
    [onCancel],
  );

  return (
    <div
      ref={wrapperRef}
      className={classes.editWrapper}
      onKeyDownCapture={handleKeyDownCapture}
    >
      <CellAutoCompleteInput
        ref={acHandle}
        value={value || undefined}
        options={options}
        initialSearchText={
          editTrigger &&
          typeof editTrigger === 'object' &&
          editTrigger.kind === 'type'
            ? editTrigger.key
            : undefined
        }
        autoOpen={!!editTrigger}
        onSelect={handleSelect}
        onClear={handleClear}
        onOptionMarked={handleOptionMarked}
        inputRef={inputRef}
        className={classes.inputArea}
      />
    </div>
  );
};

export const TextEdit: React.FC<CellEditProps<string>> = (props) => {
  const specificValues = getSpecificValues(props.validation);
  if (specificValues) {
    return <TextEditSpecificValues {...props} options={specificValues} />;
  }
  return <TextEditPlain {...props} />;
};
