<script setup lang="ts">
import { Button as ShadcnButton } from '@/components/core/button';
import { UiSpinner } from '@/components/UiSpinner';
import { computed } from 'vue';
import type { UiButtonProps, UiButtonSize, UiButtonVariant } from './types';

defineOptions({
  name: 'UiButton',
});

const props = withDefaults(defineProps<UiButtonProps>(), {
  variant: 'default',
  size: 'default',
  asChild: false,
  type: 'button',
  disabled: false,
  loading: false,
  ariaLabel: undefined,
  startIcon: undefined,
  endIcon: undefined,
});

const variantMap: Record<
  UiButtonVariant,
  'default' | 'destructive' | 'outline' | 'secondary' | 'ghost' | 'link'
> = {
  default: 'default',
  destructive: 'destructive',
  outline: 'outline',
  secondary: 'secondary',
  ghost: 'ghost',
  link: 'link',
};

const sizeMap: Record<UiButtonSize, UiButtonSize> = {
  default: 'default',
  sm: 'sm',
  lg: 'lg',
  icon: 'icon',
  'icon-xs': 'icon-xs',
  'icon-sm': 'icon-sm',
  'icon-sm-no-padding': 'icon-sm-no-padding',
  'icon-lg': 'icon-lg',
};

/**
 * Icon mode is inferred from the `size` prop: any size whose value starts
 * with `icon` renders the slot content only (no label, no start/end icons).
 */
const isIconMode = computed(() => props.size.startsWith('icon'));

const isDisabled = computed(() => props.disabled || props.loading);

function handleClick(e: MouseEvent) {
  if (isDisabled.value) {
    e.preventDefault();
    e.stopPropagation();
  }
}
</script>

<template>
  <ShadcnButton
    :variant="variantMap[props.variant]"
    :size="sizeMap[props.size]"
    :aria-label="props.ariaLabel"
    :as-child="props.asChild"
    :type="props.type"
    :disabled="isDisabled"
    :aria-busy="props.loading ? 'true' : undefined"
    @click="handleClick"
  >
    <template v-if="isIconMode">
      <UiSpinner v-if="props.loading && !props.asChild" aria-label="Loading" />
      <slot v-else />
    </template>
    <template v-else>
      <UiSpinner v-if="props.loading && !props.asChild" aria-label="Loading" />
      <component
        :is="props.startIcon"
        v-else-if="props.startIcon && !props.asChild"
      />
      <slot />
      <component :is="props.endIcon" v-if="props.endIcon && !props.asChild" />
    </template>
  </ShadcnButton>
</template>
