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

        <!-- Filtres -->
        <section class="mt-4 rounded border border-gray-200 bg-white p-4">
            <div class="grid grid-cols-1 gap-3 md:grid-cols-5">
                <div>
                    <label class="block text-xs font-medium text-gray-600">
                        {{ t('audit.filters.date_from') }}
                    </label>
                    <input
                        v-model="filters.performedAtAfter"
                        type="datetime-local"
                        class="mt-1 w-full rounded border border-gray-300 px-2 py-1 text-sm"
                    >
                </div>
                <div>
                    <label class="block text-xs font-medium text-gray-600">
                        {{ t('audit.filters.date_to') }}
                    </label>
                    <input
                        v-model="filters.performedAtBefore"
                        type="datetime-local"
                        class="mt-1 w-full rounded border border-gray-300 px-2 py-1 text-sm"
                    >
                </div>
                <div>
                    <label class="block text-xs font-medium text-gray-600">
                        {{ t('audit.filters.entity_type') }}
                    </label>
                    <input
                        v-model="filters.entityType"
                        type="text"
                        placeholder="core.User"
                        class="mt-1 w-full rounded border border-gray-300 px-2 py-1 text-sm"
                    >
                </div>
                <div>
                    <label class="block text-xs font-medium text-gray-600">
                        {{ t('audit.filters.user') }}
                    </label>
                    <input
                        v-model="filters.performedBy"
                        type="text"
                        class="mt-1 w-full rounded border border-gray-300 px-2 py-1 text-sm"
                    >
                </div>
                <div>
                    <label class="block text-xs font-medium text-gray-600">
                        {{ t('audit.filters.action') }}
                    </label>
                    <div class="mt-1 flex flex-wrap gap-2">
                        <label v-for="a in allActions" :key="a" class="flex items-center gap-1 text-xs">
                            <input
                                type="checkbox"
                                :checked="selectedActions.includes(a)"
                                @change="toggleAction(a)"
                            >
                            {{ t(`audit.action.${a}`) }}
                        </label>
                    </div>
                </div>
            </div>

            <div class="mt-3 flex justify-end">
                <button
                    type="button"
                    class="px-3 py-1 text-xs rounded border border-gray-300 hover:bg-gray-50"
                    @click="resetFilters"
                >
                    {{ t('audit.filters.reset') }}
                </button>
            </div>
        </section>

        <!-- Tableau -->
        <section class="mt-4 rounded border border-gray-200 bg-white overflow-hidden">
            <table class="min-w-full text-sm">
                <thead class="bg-tertiary-500 text-white">
                    <tr>
                        <th class="px-3 py-2 text-left font-medium">
                            {{ t('admin.auditLog.table.performedAt') }}
                        </th>
                        <th class="px-3 py-2 text-left font-medium">
                            {{ t('admin.auditLog.table.performedBy') }}
                        </th>
                        <th class="px-3 py-2 text-left font-medium">
                            {{ t('admin.auditLog.table.entityType') }}
                        </th>
                        <th class="px-3 py-2 text-left font-medium">
                            {{ t('admin.auditLog.table.entityId') }}
                        </th>
                        <th class="px-3 py-2 text-left font-medium">
                            {{ t('admin.auditLog.table.action') }}
                        </th>
                        <th class="px-3 py-2 text-left font-medium">
                            {{ t('admin.auditLog.table.summary') }}
                        </th>
                    </tr>
                </thead>
                <tbody>
                    <template v-if="entries.length > 0">
                        <template v-for="entry in entries" :key="entry.id">
                            <tr
                                class="border-t border-gray-100 hover:bg-gray-50 cursor-pointer"
                                @click="toggleExpand(entry.id)"
                            >
                                <td class="px-3 py-2">
                                    {{ formatDate(entry.performedAt) }}
                                </td>
                                <td class="px-3 py-2">{{ entry.performedBy }}</td>
                                <td class="px-3 py-2 font-mono text-xs">{{ entry.entityType }}</td>
                                <td class="px-3 py-2 font-mono text-xs">{{ entry.entityId }}</td>
                                <td class="px-3 py-2">
                                    <span
                                        class="inline-flex items-center rounded-full px-2 py-0.5 text-xs font-medium"
                                        :class="actionBadgeClass(entry.action)"
                                    >
                                        {{ t(`audit.action.${entry.action}`) }}
                                    </span>
                                </td>
                                <td class="px-3 py-2 text-xs text-gray-600">
                                    {{ summarize(entry) }}
                                </td>
                            </tr>
                            <!-- Detail expandable : diff courant + timeline complete de l'entite. -->
                            <tr v-if="expandedId === entry.id" class="bg-gray-50">
                                <td colspan="6" class="px-3 py-3">
                                    <AuditLogDetail :entry="entry" />
                                    <div class="mt-4 border-t border-gray-200 pt-3">
                                        <h3 class="text-sm font-medium text-gray-700 mb-2">
                                            {{ entry.entityType }} #{{ entry.entityId }}
                                        </h3>
                                        <AuditTimeline
                                            :entity-type="entry.entityType"
                                            :entity-id="entry.entityId"
                                        />
                                    </div>
                                </td>
                            </tr>
                        </template>
                    </template>
                    <tr v-else-if="!loading">
                        <td colspan="6" class="px-3 py-6 text-center text-sm text-gray-500">
                            {{ isFiltered ? t('audit.no_results') : t('audit.empty') }}
                        </td>
                    </tr>
                    <tr v-else>
                        <td colspan="6" class="px-3 py-6 text-center text-sm text-gray-500">
                            {{ t('common.loading') }}
                        </td>
                    </tr>
                </tbody>
            </table>
        </section>

        <!-- Pagination via hydra (view.next / view.previous) -->
        <nav class="mt-3 flex items-center justify-between text-sm">
            <span class="text-gray-600">
                {{ totalItems }} entrée{{ totalItems > 1 ? 's' : '' }}
            </span>
            <div class="flex gap-2">
                <button
                    type="button"
                    class="px-3 py-1 rounded border border-gray-300 disabled:opacity-60"
                    :disabled="!hasPrevious || loading"
                    @click="goPrevious"
                >
                    {{ t('admin.auditLog.pagination.previous') }}
                </button>
                <button
                    type="button"
                    class="px-3 py-1 rounded border border-gray-300 disabled:opacity-60"
                    :disabled="!hasNext || loading"
                    @click="goNext"
                >
                    {{ t('admin.auditLog.pagination.next') }}
                </button>
            </div>
        </nav>
    </div>
</template>

<script setup lang="ts">
import { computed, onMounted, reactive, ref, watch } from 'vue'
import type { AuditLogEntry, AuditLogFilters } from '~/shared/types'

const { t } = useI18n()
const { can } = usePermissions()
const router = useRouter()
const route = useRoute()
const { fetchLogs } = useAuditLog()

// Protection cote UI : le middleware `modules.global.ts` filtre deja les
// routes desactivees, mais si quelqu'un atterit ici sans la permission on
// renvoie sur la page admin parente plutot que de flasher un ecran vide.
if (!can('core.audit_log.view')) {
    throw createError({ statusCode: 403, statusMessage: 'Forbidden' })
}

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

const allActions = ['create', 'update', 'delete'] as const
type ActionKind = typeof allActions[number]

const filters = reactive<AuditLogFilters>({
    performedAtAfter:  readQuery('after'),
    performedAtBefore: readQuery('before'),
    entityType:        readQuery('entity_type'),
    performedBy:       readQuery('performed_by'),
    action:            readQuery('action'),
    page:              Number(readQuery('page') ?? 1) || 1,
})

// Les checkboxes d'action fonctionnent en multi-select cote UI mais l'API
// ne supporte qu'une valeur a la fois : on combine les cases cochees en un
// seul filtre "action=X" lorsque une seule case est active. Si plusieurs ou
// zero sont cochees, on n'applique pas le filtre action (comportement =
// "toutes actions").
const selectedActions = ref<ActionKind[]>(filters.action ? [filters.action as ActionKind] : [])

const entries = ref<AuditLogEntry[]>([])
const totalItems = ref(0)
const hasPrevious = ref(false)
const hasNext = ref(false)
const loading = ref(false)
const expandedId = ref<string | null>(null)

const isFiltered = computed(() =>
    Boolean(filters.performedAtAfter || filters.performedAtBefore || filters.entityType
        || filters.performedBy || filters.action),
)

function readQuery(key: string): string | undefined {
    const v = route.query[key]
    return typeof v === 'string' && v !== '' ? v : undefined
}

function toggleAction(action: ActionKind): void {
    const idx = selectedActions.value.indexOf(action)
    if (idx >= 0) selectedActions.value.splice(idx, 1)
    else selectedActions.value.push(action)
    filters.action = selectedActions.value.length === 1 ? selectedActions.value[0] : undefined
    filters.page = 1
    syncQuery()
}

function resetFilters(): void {
    filters.performedAtAfter = undefined
    filters.performedAtBefore = undefined
    filters.entityType = undefined
    filters.performedBy = undefined
    filters.action = undefined
    filters.page = 1
    selectedActions.value = []
    syncQuery()
}

async function loadEntries(): Promise<void> {
    loading.value = true
    try {
        const data = await fetchLogs({
            ...filters,
            // Convertit datetime-local (YYYY-MM-DDTHH:MM) en ISO pour l'API.
            performedAtAfter:  filters.performedAtAfter ? toIso(filters.performedAtAfter) : undefined,
            performedAtBefore: filters.performedAtBefore ? toIso(filters.performedAtBefore) : undefined,
        })
        entries.value = data.member ?? []
        totalItems.value = data.totalItems ?? 0
        const view = data.view
        hasPrevious.value = Boolean(view?.previous)
        hasNext.value = Boolean(view?.next)
    } finally {
        loading.value = false
    }
}

function toIso(localDateTime: string): string {
    // datetime-local n'a pas de timezone : on assume heure locale et on
    // laisse le navigateur generer l'ISO via Date().
    return new Date(localDateTime).toISOString()
}

function formatDate(iso: string): string {
    return new Date(iso).toLocaleString('fr-FR', {
        dateStyle: 'short',
        timeStyle: 'short',
    })
}

function actionBadgeClass(action: string): string {
    switch (action) {
        case 'create': return 'bg-green-100 text-green-800'
        case 'update': return 'bg-yellow-100 text-yellow-800'
        case 'delete': return 'bg-red-100 text-red-800'
        default: return 'bg-gray-100 text-gray-800'
    }
}

function summarize(entry: AuditLogEntry): string {
    const keys = Object.keys(entry.changes)
    if (keys.length === 0) return '—'
    if (keys.length <= 3) return keys.join(', ')
    return `${keys.slice(0, 3).join(', ')}… (+${keys.length - 3})`
}

function toggleExpand(id: string): void {
    expandedId.value = expandedId.value === id ? null : id
}

function goPrevious(): void {
    if (!hasPrevious.value || !filters.page) return
    filters.page = Math.max(1, filters.page - 1)
    syncQuery()
    loadEntries()
}

function goNext(): void {
    if (!hasNext.value) return
    filters.page = (filters.page ?? 1) + 1
    syncQuery()
    loadEntries()
}

// Persiste les filtres dans les query params URL pour que le reload ou le
// partage de lien retrouve le meme etat.
function syncQuery(): void {
    const query: Record<string, string> = {}
    if (filters.performedAtAfter)  query.after = filters.performedAtAfter
    if (filters.performedAtBefore) query.before = filters.performedAtBefore
    if (filters.entityType)        query.entity_type = filters.entityType
    if (filters.performedBy)       query.performed_by = filters.performedBy
    if (filters.action)            query.action = filters.action
    if (filters.page && filters.page !== 1) query.page = String(filters.page)
    router.replace({ query })
}

// Synchronisation reactive : tout changement de filtre declenche un fetch
// + reset de la pagination a la page 1. La navigation page (prev/next) ne
// passe PAS par un watcher : elle appelle `loadEntries()` directement dans
// `goPrevious`/`goNext`. Cette separation evite un double-fetch concurrent
// quand une filtre reset la page a 1 (sinon le watch de `filters.page`
// serait declenche une seconde fois en parallele).
watch(
    () => [filters.performedAtAfter, filters.performedAtBefore, filters.entityType, filters.performedBy, filters.action],
    () => {
        filters.page = 1
        syncQuery()
        loadEntries()
    },
)

onMounted(() => {
    loadEntries()
})
</script>
