<script setup lang="ts">
import { computed } from 'vue';
import { cn } from '@/lib/utils';
import { UiIcon } from '@/components/UiIcon';
import type { UiChipProps } from './types';

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

const props = withDefaults(defineProps<UiChipProps>(), {
  variant: 'static',
  selectable: false,
  disabled: false,
  removeLabel: 'Remove chip',
});

const emits = defineEmits<{
  (e: 'remove'): void;
}>();

const modelValue = defineModel<boolean>({ default: false });

const isRemovable = computed(() => props.variant === 'removable');
const isSelectable = computed(
  () =>
    props.variant === 'selectable' ||
    (props.variant === 'removable' && props.selectable),
);
const isSelected = computed(() => isSelectable.value && modelValue.value);

function toggleSelected() {
  if (!isSelectable.value || props.disabled) {
    return;
  }

  modelValue.value = !modelValue.value;
}

function removeChip(event: MouseEvent) {
  event.stopPropagation();
  if (props.disabled) {
    return;
  }
  emits('remove');
}

function handleRemovablePrimaryAction() {
  if (isSelectable.value) {
    toggleSelected();
  }
}

const chipBaseClass = computed(() =>
  cn(
    'inline-flex items-center rounded-full border border-border-button-outlined bg-background-surface-secondary text-content-on-accent-soft label-12-medium transition-[color,background-color,border-color]',
    'data-[selected=true]:bg-background-accent-soft data-[selected=true]:border-accent-default',
    'data-[selected=true]:hover:bg-background-accent-soft data-[selected=true]:hover:border-accent-default',
    props.disabled && 'opacity-50',
  ),
);

const standaloneChipClass = computed(() =>
  cn(
    chipBaseClass.value,
    'h-7 gap-1.5 px-3',
    isSelectable.value &&
      'cursor-pointer hover:bg-background-surface-secondary hover:border-border-button-outlined focus-visible:outline-none focus-visible:border-border-surface-focus-ring disabled:pointer-events-none',
  ),
);

const removableChipClass = computed(() =>
  cn(
    chipBaseClass.value,
    'h-7 gap-0.5 pl-3 pr-1',
    'focus-within:border-border-surface-focus-ring',
  ),
);
</script>

<template>
  <span
    v-if="!isRemovable && !isSelectable"
    data-slot="chip"
    :aria-disabled="props.disabled ? 'true' : undefined"
    :class="standaloneChipClass"
  >
    <component
      :is="props.startIcon"
      v-if="props.startIcon"
      class="size-3.5 shrink-0"
    />
    <slot />
  </span>

  <button
    v-else-if="!isRemovable"
    data-slot="chip"
    :data-selected="isSelected"
    :disabled="props.disabled"
    :aria-pressed="isSelected ? 'true' : 'false'"
    type="button"
    :class="standaloneChipClass"
    @click="toggleSelected"
  >
    <component
      :is="props.startIcon"
      v-if="props.startIcon"
      class="size-3.5 shrink-0"
    />
    <slot />
  </button>

  <div
    v-else
    data-slot="chip"
    :data-selected="isSelected"
    :class="removableChipClass"
  >
    <button
      type="button"
      class="inline-flex min-w-0 items-center gap-1.5 rounded-full outline-none"
      :class="isSelectable ? 'cursor-pointer' : 'cursor-default'"
      :disabled="props.disabled"
      :aria-pressed="isSelectable ? (isSelected ? 'true' : 'false') : undefined"
      @click="handleRemovablePrimaryAction"
    >
      <component
        :is="props.startIcon"
        v-if="props.startIcon"
        class="size-3.5 shrink-0"
      />
      <slot />
    </button>

    <button
      data-slot="chip-remove"
      type="button"
      class="inline-flex size-5 items-center justify-center rounded-full outline-none hover-layer hover-layer-default focus-visible:border-ring focus-visible:ring-[3px] focus-visible:ring-ring/50 disabled:pointer-events-none"
      :aria-label="props.removeLabel"
      :disabled="props.disabled"
      @click="removeChip"
    >
      <UiIcon name="x" :size="12" class="text-content-on-surface-primary" />
    </button>
  </div>
</template>
