import type * as React from 'react';
import {
  Platform,
  ActionSheetIOS,
  UIManager,
  findNodeHandle,
  View,
} from 'react-native';
import { HiddenItem, HiddenItemProps } from '../HeaderItems';
import { OverflowMenuContextType } from './OverflowMenuContext';
import inspectElements, { type PropsExtractor } from 'react-to-imperative';

type OverflowButtonDescriptors = ReadonlyArray<{
  title: string;
  onPress?: HiddenItemProps['onPress'];
  destructive?: boolean;
  disabled?: boolean;
}>;

export const extractOverflowButtonData = (
  hiddenButtons: React.ReactNode
): OverflowButtonDescriptors => {
  return inspectElements(hiddenButtons, extractHiddenItemProps);
};

export const extractHiddenItemProps: PropsExtractor<HiddenItemProps> = ({
  props,
  type,
}) => {
  if (type === HiddenItem) {
    return props;
  }
  return true;
};

export type OnOverflowMenuPressParams = {
  hiddenButtons: OverflowButtonDescriptors;
  overflowButtonRef: null | View;
  cancelButtonLabel?: string;
  children: React.ReactNode;
} & OverflowMenuContextType;

export const overflowMenuPressHandlerActionSheet = ({
  hiddenButtons,
  cancelButtonLabel = 'Cancel',
}: OnOverflowMenuPressParams) => {
  let actionTitles = hiddenButtons.map((btn) => btn.title);
  actionTitles.unshift(cancelButtonLabel);

  const disabledButtonIndices: Array<number> = (() => {
    let result: number[] = [];
    hiddenButtons.forEach((it, index) => {
      if (it.disabled) {
        result.push(index + 1);
      }
    });
    return result;
  })();

  const destructiveButtonIndex: Array<number> = (() => {
    let result: number[] = [];
    hiddenButtons.forEach((it, index) => {
      if (it.destructive) {
        result.push(index + 1);
      }
    });
    return result;
  })();

  ActionSheetIOS.showActionSheetWithOptions(
    {
      options: actionTitles,
      cancelButtonIndex: 0,
      disabledButtonIndices,
      destructiveButtonIndex,
    },
    (buttonIndex: number) => {
      if (buttonIndex > 0) {
        hiddenButtons[buttonIndex - 1]?.onPress?.();
      }
    }
  );
};

export const overflowMenuPressHandlerPopupMenu = ({
  hiddenButtons,
  overflowButtonRef,
}: OnOverflowMenuPressParams) => {
  const enabledButtons = hiddenButtons.filter((it) => it.disabled !== true);
  const presenter = UIManager.showPopupMenu;
  const node = findNodeHandle(overflowButtonRef);
  if (!presenter || !node) {
    console.warn(
      'could not present overflow menu using showPopupMenu(). Note this is only available on Android.'
    );
    return;
  }

  presenter(
    node,
    enabledButtons.map((btn) => btn.title),
    () => console.debug('overflowBtn error'),
    (eventName: string, index?: number) => {
      if (eventName !== 'itemSelected' || typeof index !== 'number') {
        return;
      }
      enabledButtons[index]?.onPress?.();
    }
  );
};

export const overflowMenuPressHandlerDropdownMenu = ({
  children,
  overflowButtonRef,
  presentMenu,
}: OnOverflowMenuPressParams) => {
  if (overflowButtonRef) {
    overflowButtonRef.measureInWindow((x, y, width) => {
      presentMenu({ elements: children, x: x + width, y });
    });
  } else {
    console.error('overflowButtonRef is null, cannot show overflow menu');
  }
};

export const defaultOnOverflowMenuPress: (
  params: OnOverflowMenuPressParams
) => void = Platform.select({
  ios: overflowMenuPressHandlerActionSheet,
  default: overflowMenuPressHandlerDropdownMenu,
});