import React, {
  ComponentProps,
  type ComponentPropsWithoutRef,
  type ElementType,
  forwardRef,
  type ReactElement,
  Ref,
} from 'react';
import { Box as MuiBox } from '@mui/material';

type HTMLTagMap = {
  div: HTMLDivElement;
  span: HTMLSpanElement;
  a: HTMLAnchorElement;
  button: HTMLButtonElement;
};

type MuiProps = ComponentProps<typeof MuiBox>;

type PolymorphicRef<C extends ElementType> = C extends keyof HTMLTagMap ? Ref<HTMLTagMap[C]> : Ref<unknown>;

export type Props<C extends ElementType> = {
  component?: C;
  renderHiddenContent?: boolean;
  id?: string | number | boolean;
  selectedId?: string | number | boolean;
} & MuiProps &
  Omit<ComponentPropsWithoutRef<C>, keyof MuiProps | 'component'>;

function PolymorphicComponentImpl<C extends ElementType = 'div'>(
  props: Props<C>,
  ref: PolymorphicRef<C>,
): ReactElement {
  const { renderHiddenContent = true, id, selectedId, ...rest } = props;

  return !!renderHiddenContent || id === selectedId ? (
    <MuiBox
      {...rest}
      aria-labelledby={`tab-${id}`}
      // TypeScript can't infer polymorphic ref on MUI base, safe to cast
      // eslint-disable-next-line @typescript-eslint/no-explicit-any
      ref={ref as Ref<any>}
      style={{
        display: id !== selectedId ? 'none' : null,
      }}
    />
  ) : (
    // eslint-disable-next-line react/jsx-no-useless-fragment
    <></>
  );
}

const PolymorphicComponent = forwardRef(
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
  PolymorphicComponentImpl as unknown as (props: Props<any>, ref: PolymorphicRef<any>) => ReactElement,
);

const TabContent = PolymorphicComponent as <C extends ElementType = 'div'>(
  props: Props<C> & { ref?: PolymorphicRef<C> },
) => ReactElement | null;

// @ts-expect-error TS can't detect displayName from forwardRef
TabContent.displayName = 'TabContent';

export default TabContent;
