<template>
  <button
    :type="type"
    :disabled="disabled || loading"
    :class="buttonClasses"
    @click="handleClick"
  >
    <span v-if="loading" class="spinner" aria-hidden="true"></span>
    <span
      v-if="icon && iconPosition === 'left' && !loading"
      class="icon icon-left"
    >
      {{ icon }}
    </span>
    <span v-if="$slots.default" :class="{ 'sr-only': loading }">
      <slot></slot>
    </span>
    <span
      v-if="icon && iconPosition === 'right' && !loading"
      class="icon icon-right"
    >
      {{ icon }}
    </span>
  </button>
</template>

<script setup>
import { computed, useSlots } from 'vue';

const props = defineProps({
  /**
   * Button variant style
   * @type {'primary' | 'secondary' | 'danger' | 'ghost' | 'icon-only'}
   */
  variant: {
    type: String,
    default: 'primary',
    validator: value =>
      ['primary', 'secondary', 'danger', 'ghost', 'icon-only'].includes(value)
  },

  /**
   * Button size
   * @type {'small' | 'medium' | 'large'}
   */
  size: {
    type: String,
    default: 'medium',
    validator: value => ['small', 'medium', 'large'].includes(value)
  },

  /**
   * Whether button is in loading state
   */
  loading: {
    type: Boolean,
    default: false
  },

  /**
   * Whether button is disabled
   */
  disabled: {
    type: Boolean,
    default: false
  },

  /**
   * Icon character or emoji to display
   */
  icon: {
    type: String,
    default: null
  },

  /**
   * Icon position relative to text
   * @type {'left' | 'right'}
   */
  iconPosition: {
    type: String,
    default: 'left',
    validator: value => ['left', 'right'].includes(value)
  },

  /**
   * Whether button should take full width of container
   */
  fullWidth: {
    type: Boolean,
    default: false
  },

  /**
   * Button type attribute
   * @type {'button' | 'submit' | 'reset'}
   */
  type: {
    type: String,
    default: 'button',
    validator: value => ['button', 'submit', 'reset'].includes(value)
  }
});

const emit = defineEmits(['click']);
const slots = useSlots();

const buttonClasses = computed(() => [
  'base-button',
  `base-button--${props.variant}`,
  `base-button--${props.size}`,
  {
    'base-button--loading': props.loading,
    'base-button--disabled': props.disabled,
    'base-button--full-width': props.fullWidth,
    'base-button--icon-only':
      props.variant === 'icon-only' || (!slots.default && props.icon)
  }
]);

const handleClick = event => {
  if (!props.disabled && !props.loading) {
    emit('click', event);
  }
};
</script>

<style scoped>
.base-button {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 0.5rem;
  font-family: inherit;
  font-weight: 500;
  line-height: 1.5;
  border: none;
  border-radius: 0.375rem;
  cursor: pointer;
  transition: all 0.2s ease;
  position: relative;
  white-space: nowrap;
}

.base-button:focus-visible {
  outline: 2px solid #3b82f6;
  outline-offset: 2px;
}

/* Sizes */
.base-button--small {
  padding: 0.375rem 0.75rem;
  font-size: 0.875rem;
}

.base-button--medium {
  padding: 0.5rem 1rem;
  font-size: 1rem;
}

.base-button--large {
  padding: 0.75rem 1.5rem;
  font-size: 1.125rem;
}

/* Variants */
.base-button--primary {
  background-color: #3b82f6;
  color: white;
}

.base-button--primary:hover:not(:disabled) {
  background-color: #2563eb;
}

.base-button--primary:active:not(:disabled) {
  background-color: #1d4ed8;
}

.base-button--secondary {
  background-color: #e5e7eb;
  color: #1f2937;
}

.base-button--secondary:hover:not(:disabled) {
  background-color: #d1d5db;
}

.base-button--secondary:active:not(:disabled) {
  background-color: #9ca3af;
}

.base-button--danger {
  background-color: #ef4444;
  color: white;
}

.base-button--danger:hover:not(:disabled) {
  background-color: #dc2626;
}

.base-button--danger:active:not(:disabled) {
  background-color: #b91c1c;
}

.base-button--ghost {
  background-color: transparent;
  color: #3b82f6;
  border: 1px solid transparent;
}

.base-button--ghost:hover:not(:disabled) {
  background-color: #eff6ff;
  border-color: #3b82f6;
}

.base-button--ghost:active:not(:disabled) {
  background-color: #dbeafe;
}

.base-button--icon-only {
  padding: 0.5rem;
  background-color: transparent;
  color: #6b7280;
}

.base-button--icon-only:hover:not(:disabled) {
  background-color: #f3f4f6;
  color: #1f2937;
}

.base-button--icon-only:active:not(:disabled) {
  background-color: #e5e7eb;
}

/* States */
.base-button:disabled,
.base-button--disabled,
.base-button--loading {
  opacity: 0.5;
  cursor: not-allowed;
}

.base-button--full-width {
  width: 100%;
}

/* Loading spinner */
.spinner {
  display: inline-block;
  width: 1em;
  height: 1em;
  border: 2px solid currentColor;
  border-right-color: transparent;
  border-radius: 50%;
  animation: spin 0.6s linear infinite;
}

@keyframes spin {
  to {
    transform: rotate(360deg);
  }
}

/* Icon spacing */
.icon {
  display: inline-flex;
  align-items: center;
}

.icon-left {
  margin-right: -0.25rem;
}

.icon-right {
  margin-left: -0.25rem;
}

/* Screen reader only */
.sr-only {
  position: absolute;
  width: 1px;
  height: 1px;
  padding: 0;
  margin: -1px;
  overflow: hidden;
  clip: rect(0, 0, 0, 0);
  white-space: nowrap;
  border-width: 0;
}
</style>
