import {
  AriaAttributes,
  AriaRole,
  FocusEventHandler,
  PropsWithChildren,
  Ref,
  createContext,
  useContext,
  useMemo,
} from 'react';

/** Value of {@link TriggerButtonContext} */
export interface TriggerButtonContextValue {
  ariaHasPopup?: AriaAttributes['aria-haspopup'];
  ariaLabel?: AriaAttributes['aria-label'];
  ariaInvalid?: AriaAttributes['aria-invalid'];
  ariaErrorMessage?: AriaAttributes['aria-errormessage'];
  ariaDescribedBy?: AriaAttributes['aria-describedby'];
  ariaControls?: AriaAttributes['aria-controls'];
  ariaExpanded?: AriaAttributes['aria-expanded'];
  id: string | undefined;
  role: AriaRole | undefined;
  triggerRef: Ref<HTMLButtonElement> | undefined;
  disabled: boolean | undefined;
  onClick: (() => void) | undefined;
  onBlur: FocusEventHandler<HTMLButtonElement> | undefined;
}

const TriggerButtonContext = createContext<TriggerButtonContextValue>({
  id: undefined,
  disabled: undefined,
  triggerRef: undefined,
  role: undefined,
  onClick: undefined,
  onBlur: undefined,
  ariaHasPopup: undefined,
  ariaLabel: undefined,
  ariaControls: undefined,
  ariaExpanded: undefined,
  ariaInvalid: undefined,
  ariaErrorMessage: undefined,
  ariaDescribedBy: undefined,
});

/** Provider that pass data to {@link TriggerButton} */
export function TriggerButtonContextProvider({
  children,
  id,
  disabled,
  triggerRef,
  onClick,
  onBlur,
  role,
  ariaHasPopup,
  ariaLabel,
  ariaControls,
  ariaExpanded,
  ariaInvalid,
  ariaErrorMessage,
  ariaDescribedBy,
}: PropsWithChildren<TriggerButtonContextValue>) {
  const value: TriggerButtonContextValue = useMemo(
    () => ({
      id,
      disabled,
      triggerRef,
      role,
      onClick,
      onBlur,
      ariaHasPopup,
      ariaLabel,
      ariaControls,
      ariaExpanded,
      ariaInvalid,
      ariaErrorMessage,
      ariaDescribedBy,
    }),
    [
      id,
      disabled,
      triggerRef,
      role,
      onClick,
      onBlur,
      ariaHasPopup,
      ariaLabel,
      ariaControls,
      ariaExpanded,
      ariaInvalid,
      ariaErrorMessage,
      ariaDescribedBy,
    ],
  );

  return <TriggerButtonContext.Provider value={value}>{children}</TriggerButtonContext.Provider>;
}

/** Returns data that used by {@link TriggerButton} */
export function useTriggerButtonContext(): TriggerButtonContextValue {
  return useContext(TriggerButtonContext);
}
