<template>
  <div class="flex min-h-screen">
    <aside class="w-72 bg-m-bg p-6 text-white">
      <button
        type="button"
        class="text-xl text-black font-semibold"
        @click="clearSelection"
      >
        Liste des composants
      </button>

      <nav class="mt-6 flex flex-col gap-2">
        <button
          v-for="item in items"
          :key="item.name"
          type="button"
          class="rounded px-3 py-2 text-left text-black font-bold hover:bg-m-primary hover:text-white"
          :class="selectedName === item.name ? 'bg-m-secondary text-white' : ''"
          @click="selectOrToggle(item.name)"
        >
          {{ item.label }}
        </button>
      </nav>
    </aside>

    <main class="flex-1 p-6">
      <component
        :is="selectedDemoComponent"
        v-if="selectedDemoComponent"
      />
      <p
        v-else-if="selectedName"
        class="text-gray-700"
      >
        Page de demo introuvable:
        <code>.playground/pages/composant/{{ selectedDemoFileName }}.vue</code>
      </p>
      <div v-else>
        <h1 class="text-2xl font-semibold text-gray-900">
          Playground composants
        </h1>
        <p class="mt-2 text-gray-600">
          Selectionne un composant dans la liste pour afficher sa page de demo.
        </p>
      </div>
    </main>
  </div>
</template>

<script setup lang="ts">
import { computed, ref, watch, shallowRef } from 'vue'

type LoadedModule = {
  default: unknown
}

type Item = {
  name: string
  label: string
}

const componentModules = import.meta.glob('../../app/components/malio/*.vue')
const demoModules = import.meta.glob('./composant/*.vue')

const demoByName: Record<string, () => Promise<LoadedModule>> =
  Object.fromEntries(
    Object.entries(demoModules).map(([file, loader]) => {
      const name = file.split('/').pop()?.replace('.vue', '') ?? ''
      return [name.toLowerCase(), loader as () => Promise<LoadedModule>]
    }),
  )

const items = computed<Item[]>(() =>
  Object.keys(componentModules).map((file) => {
    const name = file.split('/').pop()?.replace('.vue', '') ?? ''
    return {
      name,
      label: name,
    }
  }),
)

const selectedName = ref('')
const hasInitializedSelection = ref(false)

watch(
  items,
  (val) => {
    if (!hasInitializedSelection.value && val.length > 0) {
      selectedName.value = val[0].name
      hasInitializedSelection.value = true
    }
  },
  { immediate: true },
)

function selectOrToggle(name: string) {
  selectedName.value = selectedName.value === name ? '' : name
}

function clearSelection() {
  selectedName.value = ''
}

const selectedDemoComponent = shallowRef<unknown>(null)

watch(selectedName, async (name) => {
  if (!name) {
    selectedDemoComponent.value = null
    return
  }

  const loader = demoByName[name.toLowerCase()]
  if (!loader) {
    selectedDemoComponent.value = null
    return
  }

  const mod = await loader()
  selectedDemoComponent.value = mod.default
})

const selectedDemoFileName = computed(() => {
  const name = selectedName.value
  if (!name) return ''
  return name.charAt(0).toLowerCase() + name.slice(1)
})
</script>
