<template>
    <div>
        <component
            v-if="!isLogout"
            :is="itemComponent"
            :href="itemComponent === 'a' || itemComponent === Link ? item.href : undefined"
            :target="item.external ? '_blank' : undefined"
            :type="itemComponent === 'button' ? 'button' : undefined"
            :method="itemComponent === Link ? item.method : undefined"
            class="flex w-full items-center gap-2 rounded-lg px-3 py-2 text-left text-sm font-medium transition"
            :class="linkClasses"
            @click="toggleChildren"
        >
            <span v-if="item.icon" class="text-base">{{ item.icon }}</span>
            <span v-if="!collapsed" class="flex-1">{{ item.label }}</span>
            <span
                v-if="hasChildren && !collapsed"
                class="text-xs text-slate-400"
            >
                {{ open ? '▾' : '▸' }}
            </span>
        </component>
        <form v-else method="post" :action="item.href">
            <input type="hidden" name="_token" :value="csrf" />
            <button
                type="submit"
                class="flex w-full items-center gap-2 rounded-lg px-3 py-2 text-left text-sm font-medium transition"
                :class="linkClasses"
            >
                <span v-if="item.icon" class="text-base">{{ item.icon }}</span>
                <span v-if="!collapsed" class="flex-1">{{ item.label }}</span>
            </button>
        </form>

        <transition
            enter-active-class="transition-all duration-200 ease-out"
            enter-from-class="max-h-0 opacity-0"
            enter-to-class="max-h-96 opacity-100"
            leave-active-class="transition-all duration-150 ease-in"
            leave-from-class="max-h-96 opacity-100"
            leave-to-class="max-h-0 opacity-0"
        >
            <div v-show="hasChildren && open" class="mt-1 space-y-1 overflow-hidden">
                <SidenavItem
                    v-for="child in item.children"
                    :key="child.label"
                    :item="child"
                    :depth="depth + 1"
                    :collapsed="collapsed"
                />
            </div>
        </transition>
    </div>
</template>

<script setup>
import { computed, ref, watch } from 'vue';
import { Link, usePage } from '@inertiajs/vue3';

defineOptions({ name: 'SidenavItem' });

const props = defineProps({
    item: {
        type: Object,
        required: true,
    },
    depth: {
        type: Number,
        default: 0,
    },
    collapsed: {
        type: Boolean,
        default: false,
    },
});

const page = usePage();
const hasChildren = computed(() => props.item.children?.length);
const itemComponent = computed(() => {
    if (hasChildren.value && !props.item.href) return 'button';
    if (
        props.item.href &&
        !props.item.external &&
        !props.item.href.startsWith('#')
    ) {
        return Link;
    }
    return 'a';
});
const isLogout = computed(() => props.item.action === 'logout');
const csrf = computed(() => page.props.csrf_token);

const isRouteActive = (item) => {
    if (!item.href || item.href.startsWith('#')) {
        return false;
    }
    return page.url.startsWith(item.href);
};

const isActive = computed(() => {
    if (isRouteActive(props.item)) {
        return true;
    }
    if (hasChildren.value) {
        if (props.item.openOnChildActive === false) {
            return false;
        }
        return props.item.children.some((child) => isRouteActive(child));
    }
    return false;
});

const open = ref(isActive.value);

watch(
    () => page.url,
    () => {
        if (hasChildren.value) {
            open.value = isActive.value;
        }
    }
);

const toggleChildren = (event) => {
    if (!hasChildren.value) return;
    event.preventDefault();
    open.value = !open.value;
};

const linkClasses = computed(() => {
    const base = [
        'text-slate-600 hover:bg-slate-100 hover:text-slate-900',
        props.depth > 0 ? 'ml-4 text-xs' : '',
    ];
    if (isActive.value) {
        base.push('bg-slate-100 text-slate-900');
    }
    return base.join(' ');
});
</script>
