<script setup lang="ts">
import { computed, useAttrs, useSlots } from 'vue';
import { SidebarMenuButton } from '@/components/core/sidebar';
import { ACTIVE_INDICATOR_CLASS } from '@/lib/activeIndicator';
import { cn, omitClass } from '@/lib/utils';
import type {
  UiSidebarMenuButtonEmits,
  UiSidebarMenuButtonProps,
} from './types';

defineOptions({
  name: 'UiSidebarMenuButton',
  inheritAttrs: false,
});

const emit = defineEmits<UiSidebarMenuButtonEmits>();

const props = withDefaults(defineProps<UiSidebarMenuButtonProps>(), {
  tooltip: undefined,
  variant: 'default',
  size: 'default',
  isActive: false,
  endIconClickable: false,
  endIconAriaLabel: 'Menu action',
});

const attrs = useAttrs();
const slots = useSlots();
const hasSubtitle = computed(() => Boolean(slots.subtitle));

const containerClass = computed(() =>
  cn(
    'relative flex w-full min-w-0 items-center gap-2 rounded-md border border-transparent px-2 py-1.5 transition-colors',
    hasSubtitle.value ? 'h-[54px]' : 'h-8',
    'group-data-[collapsible=icon]:size-8 group-data-[collapsible=icon]:justify-center group-data-[collapsible=icon]:gap-0 group-data-[collapsible=icon]:p-0',
    // `:has(:focus-visible)` instead of `:focus-within` so the outer ring only appears for
    // keyboard focus — clicking a descendant button gives it DOM focus but not :focus-visible,
    // and we don't want to show a ring on mouse/touch interactions.
    'has-[:focus-visible]:border-border-surface-focus-ring has-[:focus-visible]:ring-[3px] has-[:focus-visible]:ring-ring/50',
    // Row hover/active fill for transparent sidebar items.
    'hover:bg-background-surface-muted-subtle data-[active=true]:bg-background-surface-muted-subtle',
    ACTIVE_INDICATOR_CLASS,
  ),
);

const rootClass = computed(() =>
  cn(
    '!h-full !rounded-none !p-0 body-14-regular text-content-on-surface-primary',
    '!hover:bg-transparent !active:bg-transparent',
    'data-[active=true]:!bg-transparent data-[active=true]:!text-content-on-surface-primary',
    '[&>[data-slot=start-icon]]:shrink-0',
    '[&>[data-slot=label]]:min-w-0 [&>[data-slot=label]]:truncate',
    'focus-visible:ring-0',
    // Stretched-link: extend the button's hit area to cover the full row container
    // (including its `px-2 py-1.5` padding and the gap before the end-icon) so clicks
    // anywhere on the row navigate. The end-icon stays interactive via its own `z-10`.
    'before:content-[""] before:absolute before:inset-0 before:z-0',
    attrs.class as string | undefined,
  ),
);

const endIconClass = computed(() =>
  cn(
    'ml-auto shrink-0 group-data-[collapsible=icon]:hidden',
    'relative z-10 flex size-4 items-center justify-center rounded-sm text-content-on-surface-primary outline-hidden',
    'focus-visible:ring-0',
  ),
);

const passthroughAttrs = computed(() =>
  omitClass(attrs as Record<string, unknown>),
);

function onEndIconClick(event: MouseEvent) {
  event.stopPropagation();
  // Public kebab-case event preserved for backwards compatibility.
  // eslint-disable-next-line vue/custom-event-name-casing
  emit('end-icon-click', event);
}
</script>

<template>
  <div :data-active="props.isActive" :class="containerClass">
    <SidebarMenuButton
      v-bind="passthroughAttrs"
      :tooltip="props.tooltip"
      :variant="props.variant"
      :size="props.size"
      :is-active="props.isActive"
      :class="
        cn(rootClass, 'min-w-0 flex-1 group-data-[collapsible=icon]:flex-none')
      "
    >
      <div v-if="$slots['start-icon']" data-slot="start-icon">
        <slot name="start-icon" />
      </div>
      <div v-if="$slots.default" data-slot="label" class="min-w-0">
        <div
          :class="
            cn(
              'truncate text-content-on-surface-primary',
              props.isActive
                ? 'body-14-medium'
                : hasSubtitle
                  ? 'body-14-bold'
                  : 'body-14-regular',
            )
          "
        >
          <slot />
        </div>
        <div
          v-if="$slots.subtitle"
          class="truncate body-14-regular text-content-on-surface-muted"
        >
          <slot name="subtitle" />
        </div>
      </div>
    </SidebarMenuButton>

    <button
      v-if="$slots['end-icon'] && props.endIconClickable"
      type="button"
      :ariaLabel="props.endIconAriaLabel"
      :class="endIconClass"
      @click="onEndIconClick"
    >
      <slot name="end-icon" />
    </button>

    <div v-else-if="$slots['end-icon']" :class="endIconClass">
      <slot name="end-icon" />
    </div>
  </div>
</template>
