<template>
    <div class="sidebar-panel-section" :class="{ collapsed: !isOpen, 'is-grow': grow && isOpen }">
        <div v-if="label" class="sidebar-panel-header-row" @click="toggle">
            <span class="sidebar-panel-line" />
            <span class="sidebar-panel-label">{{ label }}</span>
            <span class="sidebar-panel-line" />
            <template v-if="collapsible">
                <ChevronDownIcon v-if="isOpen" class="sidebar-panel-chevron w-3 h-3" />
                <ChevronRightIcon v-else class="sidebar-panel-chevron w-3 h-3" />
            </template>
        </div>
        <OverlayScrollbarsComponent
            v-if="isOpen"
            class="sidebar-panel-content"
            :style="maxHeight ? { maxHeight } : {}"
            :options="scrollbarOptions"
            element="div"
        >
            <slot />
        </OverlayScrollbarsComponent>
    </div>
</template>

<script setup lang="ts">
import { ref, onMounted } from 'vue';
import { ChevronDownIcon, ChevronRightIcon } from '@heroicons/vue/20/solid';
import { OverlayScrollbarsComponent } from 'overlayscrollbars-vue';
import { scrollbarOptions } from '../composables/useScrollbar';

const props = defineProps<{
    label?: string;
    storageKey: string;
    defaultOpen?: boolean;
    maxHeight?: string;
    grow?: boolean;
    radioGroup?: string;
    collapsible?: boolean;
}>();

const STORAGE_PREFIX = 'sidebar_panel_';
const stored = sessionStorage.getItem(STORAGE_PREFIX + props.storageKey);
const isOpen = ref(stored !== null ? stored === 'true' : (props.defaultOpen ?? true));

// Radio group: only one panel open at a time within a group
const radioRegistry = new Map<string, Set<() => void>>();

function getGroup(name: string): Set<() => void> {
    if (!radioRegistry.has(name)) radioRegistry.set(name, new Set());
    return radioRegistry.get(name)!;
}

let collapseMe: (() => void) | null = null;

if (props.radioGroup) {
    collapseMe = () => {
        isOpen.value = false;
        sessionStorage.setItem(STORAGE_PREFIX + props.storageKey, 'false');
    };
    getGroup(props.radioGroup).add(collapseMe);
}

import { onUnmounted } from 'vue';
if (props.radioGroup && collapseMe) {
    onUnmounted(() => {
        getGroup(props.radioGroup!).delete(collapseMe!);
    });
}

function toggle() {
    const opening = !isOpen.value;
    if (opening && props.radioGroup) {
        // Collapse all others in the group
        for (const fn of getGroup(props.radioGroup)) {
            if (fn !== collapseMe) fn();
        }
    }
    isOpen.value = opening;
    sessionStorage.setItem(STORAGE_PREFIX + props.storageKey, String(isOpen.value));
}
</script>

<style>
.sidebar-panel-section {
}

.sidebar-panel-header-row {
    display: flex;
    align-items: center;
    gap: 6px;
    padding: 8px 10px 4px;
    cursor: pointer;
    user-select: none;
}
.sidebar-panel-header-row:hover .sidebar-panel-chevron { opacity: 1; }

.sidebar-panel-line {
    flex: 1;
    height: 1px;
    background: var(--border);
    opacity: 0.4;
}

.sidebar-panel-label {
    font-size: var(--text-base);
    text-transform: none;
    letter-spacing: 0.08em;
    color: var(--text-dim);
    opacity: 0.6;
    flex-shrink: 0;
    white-space: nowrap;
}

.sidebar-panel-chevron {
    color: var(--text-dim);
    opacity: 0.3;
    flex-shrink: 0;
}

.sidebar-panel-content {
    overflow: hidden;
}

.sidebar-panel-section.is-grow {
    flex: 1;
    min-height: 0;
    display: flex;
    flex-direction: column;
}
.sidebar-panel-section.is-grow .sidebar-panel-content {
    flex: 1;
    min-height: 0;
}
</style>
