<template>
    <div>
        <!-- En-tete -->
        <div class="flex items-center justify-between">
            <h1 class="text-xl font-bold text-primary-500 sm:text-2xl">
                {{ t('admin.users.title') }}
            </h1>
        </div>

        <!-- Table des utilisateurs avec filtres + pagination -->
        <MalioDataTable
            v-model:page="page"
            v-model:per-page="perPage"
            class="mt-6"
            :columns="columns"
            :items="userItems"
            :total-items="totalItems"
            :row-clickable="canManage"
            :empty-message="t('admin.users.noUsers')"
            @row-click="onRowClick"
        >
            <template #header-username>
                <input
                    v-model="filters.username"
                    type="text"
                    :placeholder="t('admin.users.table.username')"
                    class="w-full border-0 border-b border-black bg-transparent px-0 py-1 text-xl outline-none"
                >
            </template>
            <template #header-admin>
                <select
                    v-model="filters.isAdmin"
                    class="w-full appearance-none border-0 border-b border-black bg-transparent px-0 py-1 text-xl outline-none"
                >
                    <option value="">
                        {{ t('admin.users.table.admin') }}
                    </option>
                    <option value="true">
                        {{ t('common.yes') }}
                    </option>
                    <option value="false">
                        {{ t('common.no') }}
                    </option>
                </select>
            </template>
            <template #header-roles>
                <select
                    v-model="filters['rbacRoles.code']"
                    class="w-full appearance-none border-0 border-b border-black bg-transparent px-0 py-1 text-xl outline-none"
                >
                    <option value="">
                        {{ t('admin.users.table.roles') }}
                    </option>
                    <option
                        v-for="role in allRoles"
                        :key="role.id"
                        :value="role.code"
                    >
                        {{ role.label }}
                    </option>
                </select>
            </template>
            <template v-if="sitesModuleActive" #header-sites>
                <select
                    v-model="filters['sites.name']"
                    class="w-full appearance-none border-0 border-b border-black bg-transparent px-0 py-1 text-xl outline-none"
                >
                    <option value="">
                        {{ t('admin.users.table.sites') }}
                    </option>
                    <option
                        v-for="site in allSites"
                        :key="site.id"
                        :value="site.name"
                    >
                        {{ site.name }}
                    </option>
                </select>
            </template>

            <template #cell-admin="{ item }">
                <span
                    v-if="item.admin"
                    class="inline-flex items-center rounded-full bg-purple-100 px-2.5 py-0.5 text-xs font-medium text-purple-800"
                >
                    {{ t('admin.users.table.admin') }}
                </span>
            </template>
        </MalioDataTable>

        <!-- Drawer RBAC -->
        <UserRbacDrawer
            v-model="drawerOpen"
            :user="selectedUser"
            @saved="onUserSaved"
        />
    </div>
</template>

<script setup lang="ts">
import type { Role, UserListItem } from '~/shared/types/rbac'
import type { Site } from '~/shared/types/sites'

const { t } = useI18n()
const api = useApi()
const { can } = usePermissions()
const { isModuleActive } = useModules()

useHead({ title: t('admin.users.title') })

const canManage = computed(() => can('core.users.manage'))
// Conditionne la colonne Sites + le filtre Sites : si le module Sites
// est desactive, inutile de charger /api/sites ni d'afficher ces elements.
// L'invariant "module inactif = app fonctionnelle" est preserve.
const sitesModuleActive = computed(() => isModuleActive('sites'))

// Etat DataTable centralise. On declare le filtre sites.name meme si le
// module Sites est inactif : le composable omet les filtres a valeur
// vide donc ca ne produit aucun impact cote API, et ca evite de casser
// la forme du state si le module est reactive sans reloader la page.
const {
    items,
    totalItems,
    page,
    perPage,
    filters,
    reload,
} = useDataTableServerState<UserListItem>('/users', {
    username: '',
    isAdmin: '',
    'rbacRoles.code': '',
    'sites.name': '',
})

const allRoles = ref<Role[]>([])
const allSites = ref<Site[]>([])
const sitesById = ref(new Map<number, Site>())

async function loadFilterOptions(): Promise<void> {
    const rolesPromise = api.get<{ member: Role[] }>(
        '/roles',
        { itemsPerPage: 999 },
        { toast: false },
    )

    // /api/sites est protege par `sites.view`. On skip si module off pour
    // eviter un 403 inutile dans la console devtools — la UI ne consomme
    // pas le resultat dans ce cas.
    const sitesPromise = sitesModuleActive.value
        ? api.get<{ member: Site[] }>('/sites', { itemsPerPage: 999 }, { toast: false })
        : Promise.resolve({ member: [] as Site[] })

    const [rolesData, sitesData] = await Promise.all([rolesPromise, sitesPromise])
    allRoles.value = rolesData.member ?? []
    allSites.value = sitesData.member ?? []
    sitesById.value = new Map(allSites.value.map(s => [s.id, s]))
}

// Colonnes dynamiques : on omet la colonne Sites si le module est off.
const columns = computed(() => {
    const base = [
        { key: 'username', label: t('admin.users.table.username') },
        { key: 'admin', label: t('admin.users.table.admin') },
        { key: 'roles', label: t('admin.users.table.roles') },
        { key: 'directPermissions', label: t('admin.users.table.directPermissions') },
    ]
    if (sitesModuleActive.value) {
        base.push({ key: 'sites', label: t('admin.users.table.sites') })
    }
    return base
})

// Extraire l'id numerique depuis une IRI API Platform type `/api/sites/3`.
function iriToId(iri: string): number {
    return Number(iri.split('/').pop())
}

const userItems = computed(() =>
    items.value.map(user => ({
        id: user.id,
        username: user.username,
        admin: user.isAdmin,
        roles: user.roles.length,
        directPermissions: user.directPermissions.length,
        // Affichage : liste des noms de sites separes par virgule. Les IRIs
        // du payload /api/users (groupe user:list) sont resolues via la Map
        // construite par loadFilterOptions. Vide si module Sites off.
        sites: (user.sites ?? [])
            .map(iri => sitesById.value.get(iriToId(iri))?.name)
            .filter((name): name is string => Boolean(name))
            .join(', '),
    })),
)

const drawerOpen = ref(false)
const selectedUser = ref<UserListItem | null>(null)

function getUserById(id: number): UserListItem | undefined {
    return items.value.find(u => u.id === id)
}

function openDrawer(user: UserListItem) {
    selectedUser.value = user
    drawerOpen.value = true
}

function onRowClick(item: Record<string, unknown>) {
    const user = getUserById(item.id as number)
    if (user) openDrawer(user)
}

function onUserSaved() {
    reload()
}

onMounted(() => {
    loadFilterOptions()
    reload()
})
</script>
