import Split from '@uiw/react-split';
import clsx from 'clsx';
import { twMerge } from 'tailwind-merge';

import { PolymorphicComponent } from '@/utils/polymorphic';

export const SplitPanelBar: React.FC<
  React.HTMLAttributes<HTMLDivElement> & {
    innerClassName?: string;
    mode?: 'horizontal' | 'vertical';
    size?: number | string | null;
  }
> = (props) => {
  const { mode, size = 6, innerClassName, children, ...restProps } = props;
  return (
    <div
      {...restProps}
      className={twMerge(
        'group relative',
        'text-(--split-panel-bar,transparent)',
        'hover:text-(--split-panel-bar-hover,var(--color-overlay-on-primary))',
        props.className
      )}
      // Disable default CSS
      style={
        {
          '--w-split-bar-shadow': 'transparent',
          '--w-split-bar-shadow-disable': 'transparent',
          boxShadow: 'none',
          background: 'transparent',
          [mode === 'vertical' ? 'height' : 'width']: size,
          ...restProps.style,
        } as React.CSSProperties
      }
    >
      <div
        className={twMerge(
          clsx(
            'pointer-events-all absolute',
            'transition-colors duration-150',
            'before:absolute before:inset-0 before:bg-current',
            'before:transition-colors before:duration-150',
            {
              'min-w-1': mode === 'horizontal',
              'min-h-1': mode === 'vertical',
            }
          ),
          innerClassName
        )}
      >
        {children}
      </div>
    </div>
  );
};

export const SplitPanel: PolymorphicComponent = (props) => {
  const { as: Component = 'div', ...restProps } = props;
  const className = twMerge(
    'relative overflow-y-auto @container/panel',
    props.className
  );
  return <Component {...restProps} className={className} />;
};

export type Props = React.ComponentProps<typeof Split> & {
  barClassName?: string;
  barChildren?: React.ReactNode;
};

export const SplitGroup: React.FC<Props> = (props) => {
  const {
    mode = 'horizontal',
    barClassName,
    barChildren,
    ...restProps
  } = props;
  return (
    <Split
      {...restProps}
      mode={mode}
      renderBar={(barProps) => (
        <SplitPanelBar
          mode={mode}
          innerClassName={barClassName}
          {...barProps}
          className={twMerge(
            clsx({ hidden: !restProps.visible }),
            barProps.className
          )}
        >
          {barChildren}
        </SplitPanelBar>
      )}
      className={twMerge(
        'flex-column flex items-stretch justify-stretch',
        props.className
      )}
    />
  );
};

/**
 * Panels are arranged as columns
 */
export const VerticalSplitGroup: React.FC<Props> = (props) => (
  <SplitGroup mode='horizontal' {...props} />
);

/**
 * Panels are arranged as rows
 */
export const HorizontalSplitGroup: React.FC<Props> = (props) => (
  <SplitGroup mode='vertical' {...props} />
);
