<script setup lang="ts">
import { useId } from 'vue'
import { useGroupProps, VvAccordionEvents, VvAccordionProps } from '.'

// props, attrs and emit
const props = defineProps(VvAccordionProps)

const emit = defineEmits(VvAccordionEvents)

const attrs = useAttrs() as Record<string, unknown>
const modelValue = useVModel(props, 'modelValue', emit)

// data
const accordionName = computed(
    () => props.name || (attrs?.id as string) || useId(),
)
const { title, content, not } = toRefs(props)
const { isInGroup, modifiers, disabled, bus } = useGroupProps(props)

// state
const isExpanded = ref(false)
watch(
    modelValue,
    (newValue) => {
        if (typeof newValue === 'boolean') {
            isExpanded.value = not.value ? !newValue : newValue
        }
    },
    { immediate: true },
)
watch(isExpanded, (newValue) => {
    modelValue.value = not.value ? !newValue : newValue
})
function onBusToggle({ name, value }: { name: string, value: boolean }) {
    if (name !== accordionName.value) {
        return
    }
    isExpanded.value = value
}
bus?.on('toggle', onBusToggle)
onBeforeUnmount(() => {
    bus?.off('toggle', onBusToggle)
})
function onClick() {
    if (disabled.value) {
        return
    }
    if (isInGroup.value) {
        bus?.emit('toggle', {
            name: accordionName.value,
            value: !isExpanded.value,
        })
        return
    }
    isExpanded.value = !isExpanded.value
}

// register / unregister
watch(
    accordionName,
    (newValue, oldValue) => {
        if (bus) {
            if (oldValue && oldValue !== newValue) {
                bus.emit('unregister', { name: oldValue })
            }
            bus.emit('register', { name: newValue })
        }
    },
    {
        immediate: true,
    },
)
onBeforeUnmount(() => {
    if (bus) {
        bus.emit('unregister', { name: accordionName.value })
    }
})

// methods
function expand() {
    if (isExpanded.value) {
        return
    }
    onClick()
}

function collapse() {
    if (!isExpanded.value) {
        return
    }
    onClick()
}

function groupExpand(name?: string | string[]) {
    if (!bus) {
        console.warn(
            `[VvAccordion]: You are trying to expand accordion group of "${accordionName.value}" but it is not in a group`,
        )
        return
    }
    bus.emit('expand', { name })
}

function groupCollapse(name?: string | string[]) {
    if (!bus) {
        console.warn(
            `[VvAccordion]: You are trying to collapse accordion group of "${accordionName.value}" but it is not in a group`,
        )
        return
    }
    bus?.emit('collapse', { name })
}

// expose
defineExpose({
    /** Whether the accordion is expanded */
    isExpanded,
    /** Expand the accordion */
    expand,
    /** Collapse the accordion */
    collapse,
    /** Expand accordions in the same group */
    groupExpand,
    /** Collapse accordions in the same group */
    groupCollapse,
})

// styles
const bemCssClasses = useModifiers(
    'vv-accordion',
    modifiers,
    computed(() => ({
        disabled: disabled.value,
    })),
)
</script>

<script lang="ts">
export default {
    name: 'VvAccordion',
}
</script>

<template>
    <details :id="accordionName" :class="bemCssClasses" :open="isExpanded">
        <summary
            :aria-controls="accordionName"
            :aria-expanded="isExpanded"
            class="vv-accordion__summary"
            @click.prevent="onClick()"
        >
            <!-- @slot Slot for title -->
            <slot
                name="summary"
                v-bind="{
                    isExpanded,
                    expand,
                    collapse,
                    groupExpand,
                    groupCollapse,
                }"
            >
                {{ title }}
            </slot>
        </summary>
        <div :aria-hidden="!isExpanded" class="vv-accordion__content">
            <!-- @slot Slot for content  -->
            <slot
                v-bind="{
                    isExpanded,
                    expand,
                    collapse,
                    groupExpand,
                    groupCollapse,
                }"
            >
                {{ content }}
            </slot>
        </div>
    </details>
</template>
