<template>
  <component
    :is="componentTag"
    v-bind="$attrs"
    :to="isNuxtLink ? to : undefined"
    :href="isAnchor ? href : undefined"
    :type="isButton ? type : undefined"
    :disabled="isButton ? disabled || loading : undefined"
    :aria-disabled="(!isButton && (disabled || loading)) ? 'true' : undefined"
    :class="[
      'ds-button',
      `ds-button--${variant}`,
      `ds-button--${size}`,
      props.textColor ? `ds-button--text-${props.textColor}` : '',
      props.borderColor ? `ds-button--border-${props.borderColor}` : '',
      { 'ds-button--disabled': disabled, 'ds-button--loading': loading }
    ]"
    @click="onClick"
  >
    <span class="ds-button__content">
      <span v-if="$slots.iconLeft" class="ds-button__icon ds-button__icon--left">
        <slot name="iconLeft" />
      </span>

      <span class="ds-button__label">
        <slot />
      </span>

      <span v-if="$slots.iconRight" class="ds-button__icon ds-button__icon--right">
        <slot name="iconRight" />
      </span>
    </span>

    <span v-if="loading" class="ds-button__spinner" aria-hidden="true" />
  </component>
</template>

<script setup>
    defineOptions({ inheritAttrs: false }) // désactive la transmission automatique des attributs HTML, utile pour v-bind="$attrs"
    import { computed, resolveComponent } from 'vue'

    const props = defineProps({
        variant: { type: String, default: 'primary' }, // primary/secondary/ghost/link
        size: { type: String, default: 'md' },         // sm/md/lg

        to: { type: [String, Object], default: '' },   // NuxtLink
        href: { type: String, default: '' },           // <a>
        type: { type: String, default: 'button' },     // button/submit/reset (pour éviter des soumissions involontaires on met button pas défaut, si pas submit non désiré)

        disabled: { type: Boolean, default: false },
        loading: { type: Boolean, default: false },
        textColor: { type: String, default: '' },    // accepts CSS color or tone name (ex: invert)
        borderColor: { type: String, default: '' },  // accepts CSS color or tone name (ex: invert)
    })

    // TYPE D'ÉLÉMENT : NUXTLINK, A ou BUTTON ?
    // quelle est la prop fournie ?
    const isNuxtLink = computed(() => !!props.to) // NuxtLink si prop "to" présente
    const isAnchor = computed(() => !props.to && !!props.href) // <a> si prop "href" présente et pas "to"
    const isButton = computed(() => !props.to && !props.href) // <button> si pas "href" et pas "to"
    // décision de l'élément en fonction de la prop fournie
    const componentTag = computed(() => {
      if (isNuxtLink.value) return resolveComponent('NuxtLink')
      if (isAnchor.value) return 'a'
      return 'button'
    })

    const emit = defineEmits(['click']) // déclare que ce composant peut émettre un événement click.
    // onClick(e) est appelé quand on clique sur le bouton, sauf en cas de disabled ou loading
    function onClick(e) {
      if (props.disabled || props.loading) {
          e.preventDefault()
          e.stopPropagation()
          return
      }
      emit('click', e)
    }
</script>

<style lang="scss">
  .ds-button {
    position: relative;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    gap: var(--sp-2);
    border-radius: var(--r-md);
    border: 2px solid transparent;
    font-family: var(--font-roboto);
    font-weight: var(--fw-medium);
    line-height: 1;
    text-decoration: none;
    cursor: pointer;
    user-select: none;
    white-space: nowrap;

    transition:
      transform 120ms ease,
      background-color 120ms ease,
      border-color 120ms ease,
      box-shadow 120ms ease,
      color 120ms ease;

    &:hover {
      transform: translateY(-2px);
    }
    &:focus-visible {
      outline: none;
      box-shadow: 0 0 0 3px var(--c-focus);
    }

    &--disabled,
    &--loading {
      opacity: 0.55;
      cursor: not-allowed;
    }

    /* Sizes */
    &--aplati {
      font-size: var(--text-md);
      padding-inline: var(--sp-14);
      min-height: 2rem;
    }
    &--xs {
      font-size: var(--text-sm);
      padding: 5px 8px;
      min-height: 30px;
      max-height: 30px;
    }
    &--sm {
      font-size: var(--text-sm);
      padding: var(--sp-4) var(--sp-8);
      min-height: 2.25rem;
    }

    &--md {
      font-size: var(--text-md);
      padding: var(--sp-6) var(--sp-12);
      min-height: 2.75rem;
    }

    &--lg {
      font-size: var(--text-lg);
      padding: var(--sp-8) var(--sp-16);
      min-height: 3.25rem;
    }

    /* Variants */
    &--primary {
      color: var(--ds-button-text, var(--c-brand-contrast));
      border-color: var(--ds-button-border, transparent);
    }

    &--secondary {
      background: var(--c-surface);
      color: var(--ds-button-text, var(--c-text));
      border-color: var(--ds-button-border, var(--c-border-strong));
      box-shadow: var(--sh-soft);
    }
    &--secondary:hover {
      background: var(--c-hover);
    }

    &--third {
      background: var(--c-gris);
      color: var(--ds-button-text, var(--c-brand-contrast));
      border-color: var(--ds-button-border, transparent);
    }
    &--white {
      background: var(--c-surface);
    }

    &--ghost {
      background: transparent;
      color: var(--ds-button-text, var(--c-text));
      border-color: var(--ds-button-border, transparent);
    }
    &--ghost:hover {
      background: var(--c-hover);
    }

    &--link {
      background: transparent;
      color: var(--ds-button-text, var(--c-brand));
      padding: 0;
      min-height: auto;
      border-color: var(--ds-button-border, transparent);
    }
    &--link:hover {
      text-decoration: underline;
    }

    &--text-default { --ds-button-text: var(--c-text); }
    &--text-muted { --ds-button-text: var(--c-text-muted); }
    &--text-invert { --ds-button-text: var(--c-text-invert); }
    &--text-brand_rouge { --ds-button-text: var(--c-brand_rouge); }
    &--text-brand_rouge-weak { --ds-button-text: var(--c-brand_rouge-weak); }
    &--text-success { --ds-button-text: var(--c-success); }
    &--text-warning { --ds-button-text: var(--c-warning); }
    &--text-danger { --ds-button-text: var(--c-danger); }
    &--text-bleu_fonce { --ds-button-text: var(--c-bleu_fonce); }
    &--text-bleu_clair { --ds-button-text: var(--c-bleu_clair); }
    &--text-info { --ds-button-text: var(--c-info); }

    &--border-default { --ds-button-border: var(--c-text); }
    &--border-none { --ds-button-border: none; }
    &--border-muted { --ds-button-border: var(--c-text-muted); }
    &--border-invert { --ds-button-border: var(--c-text-invert); }
    &--border-brand_rouge { --ds-button-border: var(--c-brand_rouge); }
    &--border-brand_rouge-weak { --ds-button-border: var(--c-brand_rouge-weak); }
    &--border-success { --ds-button-border: var(--c-success); }
    &--border-warning { --ds-button-border: var(--c-warning); }
    &--border-danger { --ds-button-border: var(--c-danger); }
    &--border-bleu_fonce { --ds-button-border: var(--c-bleu_fonce); }
    &--border-bleu_clair { --ds-button-border: var(--c-bleu_clair); }
    &--border-info { --ds-button-border: var(--c-info); }
    &--border { --ds-button-border: var(--c-border); }
    &--border-strong { --ds-button-border: var(--c-border-strong); }
  }
  .ds-button__content {
    display: inline-flex;
    align-items: center;
    gap: var(--sp-2);
  }

  .ds-button__icon {
    display: inline-flex;
    align-items: center;
    justify-content: center;
  }

  .ds-button__spinner {
    position: absolute;
    width: 1rem;
    height: 1rem;
    border-radius: 999px;
    border: 2px solid rgba(255,255,255,0.45);
    border-top-color: rgba(255,255,255,0.95);
    animation: ds-spin 700ms linear infinite;
  }

  @keyframes ds-spin {
    to { transform: rotate(360deg); }
  }
</style>
