import React, { RefObject, useCallback, useEffect, useMemo, useRef } from 'react';
import { SilkeSchemaFields } from '../silke-schema-fields';
import { SilkeTextField } from '../../silke-text-field';
import { SilkePopover } from '../../silke-popover';
import { FieldRegisterModel, FormObjectProvider } from '../../silke-form/form-context';
import { SilkeText } from '../../silke-text';
import { SilkeBox } from '../../silke-box';
import { SilkeButton } from '../../silke-button';
import { generateTitle } from './utils';
import { VevProps } from '@vev/utils';
import { getSchemaDefaultValue } from '../schema-utils';
import { SilkeSchemaContext, useSchemaContext } from '../silke-schema-context';
import styles from './styles.scss';

type Props = {
  anchor: RefObject<any>;
  selected: number;
  value: any[];
  disabled?: boolean;
  schema: VevProps | VevProps[] | string;
  onChange: (value: any[]) => void;
  onDelete: () => void;
  onClose: () => void;
};

export function ArrayFieldModal({
  anchor,
  value,
  selected,
  schema,
  disabled,
  onChange,
  onDelete,
  onClose,
}: Props) {
  const schemaContext = useSchemaContext();
  const valueRef = useRef<any>(value);
  const fieldRefs = useRef<any>({});

  const registerField = useCallback((name: any, v: FieldRegisterModel) => {
    fieldRefs.current[name] = v;
  }, []);

  const defaultItemValue = useMemo(
    () => getSchemaDefaultValue(schema as VevProps | VevProps[]),
    [schema],
  );

  const contentRef = useRef<HTMLDivElement>(null);

  useEffect(() => {
    // Focus the first input-like element when the popover opens
    const timer = setTimeout(() => {
      const el = contentRef.current?.querySelector<HTMLElement>(
        'input, textarea, [contenteditable="true"], [role="textbox"]',
      );
      el?.focus();
    }, 50);
    return () => clearTimeout(timer);
  }, [selected]);

  const anchorRect = anchor.current.getBoundingClientRect();
  const anchorPos: [number, number] = [anchorRect.left - 16, anchorRect.top];

  return (
    <SilkePopover
      anchor={anchorPos}
      targetOrigin="top-right"
      hide={selected === undefined}
      zIndex={90}
      contextId="silke-array-schema"
    >
      <SilkeSchemaContext context={schemaContext}>
        <SilkeBox column bg="neutral-5" className={styles.arrayFieldModal} ref={contentRef}>
          <SilkeBox pad="s" vAlign="center">
            <SilkeBox hPad="s" vPad="s" flex>
              <SilkeText weight="strong">
                {generateTitle(value[selected], schema) || 'Untitled'}
              </SilkeText>
            </SilkeBox>
            <SilkeButton disabled={disabled} icon="delete" kind="ghost" onClick={onDelete} />
            <SilkeButton icon="close" kind="ghost" onClick={onClose} />
          </SilkeBox>
          <SilkeBox hPad="m" gap="m" column vAlign="center">
            {typeof schema === 'string' ? (
              <SilkeTextField
                value={(selected !== undefined && value[selected]) || ''}
                type={(schema as any).of}
                onChange={(val: string) => {
                  const update = [...(value || [])];
                  update[selected] = val;
                  onChange(update);
                }}
              />
            ) : (
              <FormObjectProvider
                errors={{}}
                valueRef={valueRef}
                value={value[selected] || defaultItemValue}
                validate={() => {}}
                onChange={(name, update) => {
                  const newValue = [...(value || [])];
                  newValue[selected] = {
                    ...defaultItemValue,
                    ...value[selected],
                    [name]: update,
                  };
                  onChange(newValue);
                }}
                register={registerField}
              >
                <SilkeSchemaFields
                  disabled={disabled}
                  schema={Array.isArray(schema) ? schema : [schema]}
                  value={value[selected] || defaultItemValue}
                  noPad
                  itemIndex={selected}
                />
              </FormObjectProvider>
            )}
          </SilkeBox>
        </SilkeBox>
      </SilkeSchemaContext>
    </SilkePopover>
  );
}
