import { Bar } from '@visx/shape';

type dominantBaseline =
  | 'central'
  | 'middle'
  | 'auto'
  | 'baseline'
  | 'before-edge'
  | 'text-before-edge'
  | 'after-edge'
  | 'text-after-edge'
  | 'ideographic'
  | 'alphabetic'
  | 'hanging'
  | 'mathematical'
  | 'inherit'
  | undefined;

interface BarLabelProps {
  x: number;
  y: number;
  width: number;
  height: number;
  value?: string | number;
  color?: string;
  fontSize?: number;
  horizontal?: boolean;
  labelPosition?: 'center' | 'inset' | 'offset';
}

export const BarLabel = ({
  x,
  y,
  width,
  height,
  value,
  color,
  fontSize = 12,
  horizontal,
  labelPosition,
}: BarLabelProps) => {
  let textProps;
  if (labelPosition === 'offset') {
    if (horizontal) {
      textProps = {
        textAnchor: 'start',
        dominantBaseline: 'central' as dominantBaseline,
        x: width + 8,
        y: height / 2 + y,
      };
    } else {
      textProps = {
        textAnchor: 'middle',
        x: width / 2 + x,
        y: y - 8,
      };
    }
  } else if (horizontal && labelPosition === 'inset') {
    textProps = {
      textAnchor: 'end',
      dominantBaseline: 'central' as dominantBaseline,
      x: width - 8,
      y: height / 2 + y,
    };
  } else {
    textProps = {
      x: width / 2 + x,
      y: height / 2 + y,
      textAnchor: 'middle',
      dominantBaseline: 'central' as dominantBaseline,
    };
  }

  const hasSizeForLabel = horizontal
    ? width >= String(value).length * 8
    : height >= 16;

  if (labelPosition !== 'offset' && !hasSizeForLabel) return null;

  return (
    <text fill={color} fontSize={fontSize} {...textProps}>
      {value}
    </text>
  );
};

interface BarWithLabelProps {
  x: number;
  y: number;
  width: number;
  height: number;
  horizontal?: boolean;
  fill: string;
  textLabelColor?: string;
  textLabelSize?: number;
  value?: number | string;
  labelPosition?: 'center' | 'inset' | 'offset';
  onClick?: React.MouseEventHandler<SVGRectElement>;
}

export const BarElement = ({
  x,
  y,
  width,
  height,
  horizontal,
  fill,
  textLabelColor,
  textLabelSize,
  value,
  labelPosition,
  onClick,
  ...props
}: BarWithLabelProps) => {
  const safeWidth = Math.max(0, width);
  const safeHeight = Math.max(0, height);
  const rectangle = Boolean(safeWidth && safeHeight);

  return (
    <g {...props}>
      {rectangle && (
        <Bar
          x={x}
          y={y}
          width={safeWidth}
          height={safeHeight}
          fill={fill}
          onClick={onClick}
        />
      )}
      {rectangle && value && (
        <BarLabel
          x={x}
          y={y}
          width={safeWidth}
          height={safeHeight}
          value={value}
          color={textLabelColor}
          fontSize={textLabelSize}
          horizontal={horizontal}
          labelPosition={labelPosition}
        />
      )}
    </g>
  );
};
