<script>
import theme from "#build/b24ui/sidebar";
</script>

<script setup>
import { computed, onMounted, ref, toRef, watch } from "vue";
import { Primitive } from "reka-ui";
import { defu } from "defu";
import { createReusableTemplate, useMediaQuery } from "@vueuse/core";
import { useAppConfig } from "#imports";
import { useComponentProps } from "../composables/useComponentProps";
import { useLocale } from "../composables/useLocale";
import { tv } from "../utils/tv";
import icons from "../dictionary/icons";
import B24Button from "./Button.vue";
import B24Slideover from "./Slideover.vue";
import B24Modal from "./Modal.vue";
import B24Drawer from "./Drawer.vue";
defineOptions({ inheritAttrs: false });
const _props = defineProps({
  as: { type: null, required: false, default: "aside" },
  variant: { type: null, required: false, default: "sidebar" },
  collapsible: { type: null, required: false, default: "offcanvas" },
  side: { type: null, required: false, default: "left" },
  title: { type: String, required: false },
  description: { type: String, required: false },
  close: { type: [Boolean, Object], required: false, default: false },
  closeIcon: { type: [Function, Object], required: false },
  rail: { type: Boolean, required: false, default: false },
  transition: { type: Boolean, required: false, default: true },
  mode: { type: null, required: false, default: "slideover" },
  menu: { type: null, required: false },
  class: { type: null, required: false },
  b24ui: { type: Object, required: false }
});
const slots = defineSlots();
const props = useComponentProps("sidebar", _props);
const [DefineInnerTemplate, ReuseInnerTemplate] = createReusableTemplate();
const [DefineContentTemplate, ReuseContentTemplate] = createReusableTemplate();
const mediaQuery = useMediaQuery("(max-width: 1023px)");
const isMounted = ref(false);
onMounted(() => {
  isMounted.value = true;
});
const isMobile = computed(() => isMounted.value && mediaQuery.value);
const modelOpen = defineModel("open", { type: Boolean, ...{ default: true } });
const openMobile = ref(false);
const desktopOpen = ref(modelOpen.value);
const open = computed({
  get: () => isMobile.value ? openMobile.value : modelOpen.value,
  set: (value) => {
    if (isMobile.value) {
      openMobile.value = value;
    } else {
      modelOpen.value = value;
    }
  }
});
watch(isMobile, (mobile) => {
  if (mobile) {
    desktopOpen.value = modelOpen.value;
    modelOpen.value = false;
  } else {
    modelOpen.value = desktopOpen.value;
  }
}, { immediate: true });
watch(modelOpen, (value) => {
  if (isMobile.value) {
    openMobile.value = value;
  }
});
watch(openMobile, (value) => {
  if (isMobile.value) {
    modelOpen.value = value;
  }
});
const { t } = useLocale();
const appConfig = useAppConfig();
const state = computed(() => open.value ? "expanded" : "collapsed");
const canClose = computed(() => props.close && props.collapsible !== "none" || isMobile.value);
function closeSidebar() {
  open.value = false;
}
const hasHeader = computed(() => !!slots.header || props.title || !!slots.title || props.description || !!slots.description || !!slots.actions || canClose.value || !!slots.close);
const b24ui = computed(() => tv({ extend: theme, ...appConfig.b24ui?.sidebar || {} })({
  side: props.side,
  variant: props.variant,
  collapsible: props.collapsible,
  transition: props.transition
}));
const Menu = computed(() => ({
  slideover: B24Slideover,
  modal: B24Modal,
  drawer: B24Drawer
})[props.mode]);
const menuProps = toRef(() => {
  const modeSettings = props.mode === "modal" ? { fullscreen: true, transition: false } : props.mode === "slideover" ? { side: props.side, inset: props.variant === "inset", close: false } : {};
  if (props.mode === "modal") {
    modeSettings["b24ui"] = { content: "p-0 pt-0" };
  }
  const result = defu(
    props.menu,
    {
      title: props.title,
      description: props.description,
      close: props.close,
      closeIcon: props.closeIcon
    },
    modeSettings
  );
  result["b24ui"] = {
    overlay: b24ui.value.overlay({ class: props.b24ui?.overlay }),
    content: b24ui.value.content({
      class: [modeSettings?.b24ui?.content, props.b24ui?.content]
    })
  };
  return result;
});
</script>

<template>
  <DefineContentTemplate>
    <div v-if="hasHeader" data-slot="header" :class="b24ui.header({ class: props.b24ui?.header })">
      <slot name="header" :state="state" :open="open" :close="closeSidebar">
        <div v-if="props.title || !!slots.title || props.description || !!slots.description" data-slot="wrapper" :class="b24ui.wrapper({ class: props.b24ui?.wrapper })">
          <p v-if="props.title || !!slots.title" data-slot="title" :class="b24ui.title({ class: props.b24ui?.title })">
            <slot name="title" :state="state">
              {{ props.title }}
            </slot>
          </p>

          <p v-if="props.description || !!slots.description" data-slot="description" :class="b24ui.description({ class: props.b24ui?.description })">
            <slot name="description" :state="state">
              {{ props.description }}
            </slot>
          </p>
        </div>

        <div v-if="!!slots.actions || canClose" data-slot="actions" :class="b24ui.actions({ class: props.b24ui?.actions })">
          <slot name="actions" :state="state" />

          <slot name="close" :state="state" :b24ui="b24ui">
            <B24Button
              v-if="canClose"
              :icon="props.closeIcon || icons.close"
              size="md"
              color="air-tertiary-no-accent"
              :aria-label="t('sidebar.close')"
              v-bind="typeof props.close === 'object' ? props.close : {}"
              data-slot="close"
              :class="b24ui.close({ class: props.b24ui?.close })"
              @click="closeSidebar"
            />
          </slot>
        </div>
      </slot>
    </div>

    <div data-slot="body" :class="b24ui.body({ class: props.b24ui?.body })">
      <slot :state="state" :open="open" :close="closeSidebar" />
    </div>

    <div v-if="!!slots.footer" data-slot="footer" :class="b24ui.footer({ class: props.b24ui?.footer })">
      <slot name="footer" :state="state" :open="open" :close="closeSidebar" />
    </div>
  </DefineContentTemplate>

  <DefineInnerTemplate>
    <div data-slot="inner" :class="b24ui.inner({ class: props.b24ui?.inner })">
      <ReuseContentTemplate />
    </div>
  </DefineInnerTemplate>

  <!-- Non-collapsible: simple inline sidebar -->
  <Primitive
    v-if="props.collapsible === 'none'"
    :as="props.as"
    v-bind="$attrs"
    data-slot="root"
    :data-variant="props.variant"
    :class="b24ui.root({ class: [props.b24ui?.root, props.class] })"
  >
    <ReuseInnerTemplate />
  </Primitive>

  <!-- Collapsible: fixed sidebar with gap spacer + mobile menu -->
  <template v-else>
    <Primitive
      :as="props.as"
      v-bind="$attrs"
      data-slot="root"
      :data-state="state"
      :data-collapsible="state === 'collapsed' ? props.collapsible : void 0"
      :data-variant="props.variant"
      :data-side="props.side"
      :class="b24ui.root({ class: [props.b24ui?.root, props.class] })"
    >
      <!-- Gap spacer: reserves layout space for the fixed sidebar -->
      <div
        data-slot="gap"
        :data-state="state"
        :class="b24ui.gap({ class: props.b24ui?.gap })"
      />

      <!-- Fixed container: the actual visible sidebar -->
      <div
        data-slot="container"
        :data-state="state"
        :class="b24ui.container({ class: props.b24ui?.container })"
      >
        <ReuseInnerTemplate />

        <slot v-if="props.rail" name="rail" :state="state" :b24ui="b24ui">
          <button
            data-slot="rail"
            :data-state="state"
            :aria-label="t('sidebar.toggle')"
            :tabindex="-1"
            :class="b24ui.rail({ class: props.b24ui?.rail })"
            @click="open = !open"
          />
        </slot>
      </div>
    </Primitive>

    <!-- Mobile menu -->
    <Menu
      v-if="isMobile"
      v-model:open="openMobile"
      v-bind="menuProps"
    >
      <template #content="contentData">
        <slot name="content" v-bind="contentData" :close="closeSidebar">
          <ReuseContentTemplate />
        </slot>
      </template>
    </Menu>
  </template>
</template>
