<template>
    <div class="h-screen overflow-hidden">
        <div class="flex h-full">
            <MalioSidebar
                v-model="ui.sidebarCollapsed"
                :sections="mergedSections"
                :sidebar-class="ui.sidebarCollapsed ? '' : 'w-[232px]'"
            >
                <template #logo>
                    <img src="/LOGO_MALIO.png" alt="Malio"/>
                </template>
                <template #logo-collapsed>
                    <img src="/LOGO_MALIO_COLLAPSED.png" alt="Malio"/>
                </template>
                <template #footer>
                    <div class="flex flex-col gap-2">
                        <SidebarTimer :collapsed="false" />
                        <p v-if="version" class="text-center text-sm font-bold">v {{ version }}</p>
                    </div>
                </template>
                <template #footer-collapsed>
                    <SidebarTimer :collapsed="true" />
                </template>
            </MalioSidebar>

            <div class="h-full flex-1 flex flex-col min-h-0 min-w-0">
                <AppTopNav :user="auth.user" />
                <main class="flex flex-1 flex-col overflow-y-auto overflow-x-hidden bg-white px-4 pb-24 sm:px-6 lg:px-12 xl:px-11">
                    <slot/>
                </main>
            </div>
        </div>

        <TimeEntryDrawer
            v-model="completeDrawerOpen"
            :entry="timerStore.pendingCompleteEntry"
            :users="refData.users"
            :projects="refData.projects"
            :tags="refData.tags"
            @saved="onCompleteSaved"
        />
    </div>
</template>

<script setup lang="ts">
import type { UserData } from '~/services/dto/user-data'
import type { Project } from '~/modules/project-management/services/dto/project'
import type { TaskTag } from '~/modules/project-management/services/dto/task-tag'
import { useAppVersion } from '~/composables/useAppVersion'
import type { HydraCollection } from '~/utils/api'
import { extractHydraMembers } from '~/utils/api'

const auth = useAuthStore()
const ui = useUiStore()
const mailStore = useMailStore()
const {version} = useAppVersion()
const route = useRoute()
const { t } = useI18n()
const { sections } = useSidebar()

const isEmployee = computed(() => Boolean(auth.user?.isEmployee))

const isMailVisible = computed(() => {
    const roles: string[] = auth.user?.roles ?? []
    return roles.includes('ROLE_USER') || roles.includes('ROLE_ADMIN')
})

const { enabled: shareEnabled, ensureLoaded: ensureShareStatus } = useShareStatus()
const isDocumentsVisible = computed(() => shareEnabled.value === true)

const currentProjectId = computed(() => {
    const match = route.path.match(/^\/projects\/(\d+)/)
    return match ? match[1] : null
})

type MalioItem = { label: string; to: string; exact?: boolean }
type MalioSection = { label: string; icon: string; items: MalioItem[] }

// Ordre d'affichage canonique des sections.
const SECTION_ORDER = [
    'sidebar.general.section',
    'sidebar.tools.section',
    'sidebar.admin.section',
] as const

// Icônes de secours pour les sections créées côté client (absentes du backend,
// ex. module mail off mais partage actif → section Outils à recréer).
const SECTION_ICON: Record<string, string> = {
    'sidebar.general.section': 'mdi:view-dashboard-outline',
    'sidebar.tools.section': 'mdi:tools',
    'sidebar.admin.section': 'mdi:cog-outline',
}

// Item client avec ancre optionnelle : `after` = `to` de l'item après lequel l'insérer
// (sinon ajouté en fin de section).
type ClientItem = MalioItem & { after?: string }

// Items rendus côté client (dépendent d'un état runtime ignoré du backend).
function clientItemsFor(key: string): ClientItem[] {
    if (key === 'sidebar.general.section') {
        const items: ClientItem[] = []
        if (currentProjectId.value) {
            const id = currentProjectId.value
            // Insérés juste sous « Projets », dans l'ordre via ancres chaînées.
            items.push({ label: t('sidebar.project.kanban'), to: `/projects/${id}`, exact: true, after: '/projects' })
            items.push({ label: t('sidebar.project.groups'), to: `/projects/${id}/groups`, after: `/projects/${id}` })
            items.push({ label: t('sidebar.project.archives'), to: `/projects/${id}/archives`, after: `/projects/${id}/groups` })
        }
        if (isEmployee.value) {
            items.push({ label: t('sidebar.general.myAbsences'), to: '/absences' })
        }
        return items
    }
    if (key === 'sidebar.tools.section') {
        const items: ClientItem[] = []
        if (isMailVisible.value) {
            const n = mailStore.globalUnreadCount
            const suffix = n > 0 ? ` (${n > 99 ? '99+' : n})` : ''
            items.push({ label: `${t('mail.sidebar.title')}${suffix}`, to: '/mail' })
        }
        if (isDocumentsVisible.value) {
            items.push({ label: t('sharedFiles.sidebar.title'), to: '/documents' })
        }
        return items
    }
    return []
}

// Insère les items client après leur ancre (`after`), sinon en fin de liste.
function mergeClientItems(base: MalioItem[], extra: ClientItem[]): MalioItem[] {
    const result = [...base]
    for (const { after, ...item } of extra) {
        const idx = after ? result.findIndex((i) => i.to === after) : -1
        if (idx !== -1) {
            result.splice(idx + 1, 0, item)
        } else {
            result.push(item)
        }
    }
    return result
}

const mergedSections = computed<MalioSection[]>(() => {
    // 1. Sections backend (déjà filtrées par permissions), mail retiré (ré-injecté côté client).
    const backend = new Map<string, MalioSection>()
    for (const section of sections.value) {
        backend.set(section.label, {
            label: t(section.label),
            icon: section.icon,
            items: section.items
                .filter((item) => item.to !== '/mail')
                .map((item) => ({ label: t(item.label), to: item.to })),
        })
    }

    // 2. Fusion dans l'ordre canonique.
    const result: MalioSection[] = []
    for (const key of SECTION_ORDER) {
        const base = backend.get(key)
        const extra = clientItemsFor(key)
        if (base) {
            base.items = mergeClientItems(base.items, extra)
            if (base.items.length > 0) {
                result.push(base)
            }
        } else if (extra.length > 0) {
            result.push({ label: t(key), icon: SECTION_ICON[key] ?? '', items: mergeClientItems([], extra) })
        }
    }

    // 3. Garde-fou : toute section backend hors ordre canonique n'est pas perdue.
    for (const [key, section] of backend) {
        if (!(SECTION_ORDER as readonly string[]).includes(key) && section.items.length > 0) {
            result.push(section)
        }
    }

    return result
})

const timerStore = useTimerStore()

const baseTitle = ref('Lesstime')

useHead({
    titleTemplate: (title) => {
        baseTitle.value = title || 'Lesstime'
        return title || 'Lesstime'
    },
})

watch(
    [() => timerStore.elapsedFormatted, () => timerStore.isRunning, () => timerStore.activeEntry?.title],
    ([elapsed, running, label]) => {
        if (import.meta.server) return
        const base = baseTitle.value
        if (running) {
            document.title = label ? `${base} | ${elapsed} · ${label}` : `${base} | ${elapsed}`
        } else {
            document.title = base
        }
    },
)

onMounted(() => {
    timerStore.fetchActive()
    if (isMailVisible.value) {
        mailStore.startPolling()
    }
    ensureShareStatus()
})

watch(() => auth.user, (user) => {
    if (!user) {
        mailStore.stopPolling()
    } else {
        if (isMailVisible.value) {
            mailStore.startPolling()
        }
        ensureShareStatus()
    }
})

const completeDrawerOpen = ref(false)
const refData = reactive({
    users: [] as UserData[],
    projects: [] as Project[],
    tags: [] as TaskTag[],
    loaded: false,
})

async function loadRefData() {
    if (refData.loaded) return
    const api = useApi()
    const [usersData, projectsData, typesData] = await Promise.all([
        api.get<HydraCollection<UserData>>('/users'),
        api.get<HydraCollection<Project>>('/projects'),
        api.get<HydraCollection<TaskTag>>('/task_tags'),
    ])
    refData.users = extractHydraMembers(usersData)
    refData.projects = extractHydraMembers(projectsData)
    refData.tags = extractHydraMembers(typesData)
    refData.loaded = true
}

watch(() => timerStore.pendingCompleteEntry, async (entry) => {
    if (entry) {
        await loadRefData()
        completeDrawerOpen.value = true
    }
})

watch(completeDrawerOpen, (open) => {
    if (!open) {
        nextTick(() => {
            timerStore.clearPendingEntry()
        })
    }
})

function onCompleteSaved() {
    completeDrawerOpen.value = false
    nextTick(() => {
        timerStore.clearPendingEntry()
    })
}
</script>
