<template>
    <div class="flex flex-col gap-6">
        <div class="flex items-center justify-between">
            <h1 class="text-2xl font-bold text-neutral-900">{{ $t('absences.title') }}</h1>
            <MalioButton
                :label="$t('absences.newRequest')"
                icon-name="mdi:plus"
                icon-position="left"
                @click="requestDrawerOpen = true"
            />
        </div>

        <AbsenceBalanceCards :balances="balances" />

        <!-- Filters -->
        <div class="flex flex-wrap gap-3">
            <MalioSelect
                v-model="filters.status"
                :label="$t('absences.table.status')"
                :options="statusOptions"
                :empty-option-label="$t('absences.filters.allStatuses')"
                group-class="w-52"
            />
            <MalioSelect
                v-model="filters.type"
                :label="$t('absences.table.type')"
                :options="typeOptions"
                :empty-option-label="$t('absences.filters.allTypes')"
                group-class="w-52"
            />
            <MalioSelect
                v-model="filters.year"
                :label="$t('absences.table.year')"
                :options="yearOptions"
                :empty-option-label="$t('absences.filters.allYears')"
                group-class="w-40"
            />
        </div>

        <MalioDataTable
            :columns="columns"
            :items="rows"
            :total-items="rows.length"
            :row-clickable="true"
            :empty-message="$t('absences.noRequests')"
            @row-click="openDetail"
        >
            <template #cell-status="{ item }">
                <StatusBadge
                    :label="statusLabel((item as Row).status)"
                    :variant="statusVariant((item as Row).status)"
                    :icon="statusIcon((item as Row).status)"
                />
            </template>
        </MalioDataTable>

        <AbsenceRequestDrawer
            v-model="requestDrawerOpen"
            :policies="policies"
            @created="reload"
        />
        <AbsenceDetailDrawer
            v-model="detailDrawerOpen"
            :request="selected"
            :can-cancel="selected?.status === 'pending'"
            @cancelled="reload"
        />
    </div>
</template>

<script setup lang="ts">
import type { AbsenceBalance, AbsencePolicy, AbsenceRequest, AbsenceStatus, AbsenceType } from '~/services/dto/absence'
import { useAbsenceService, type AbsenceRequestFilters } from '~/services/absences'
import { useAbsenceHelpers } from '~/composables/useAbsenceHelpers'

type Row = AbsenceRequest & { typeLabelText: string; periodText: string; daysText: string; createdAtText: string }

definePageMeta({ middleware: ['employee'] })

const { t } = useI18n()
const service = useAbsenceService()
const { statusLabel, statusVariant, statusIcon, formatRange, formatDays, formatDate } = useAbsenceHelpers()

useHead({ title: t('absences.title') })

const balances = ref<AbsenceBalance[]>([])
const requests = ref<AbsenceRequest[]>([])
const policies = ref<AbsencePolicy[]>([])

const requestDrawerOpen = ref(false)
const detailDrawerOpen = ref(false)
const selected = ref<AbsenceRequest | null>(null)

// Empty option of MalioSelect has value null, so filters default to null.
const filters = reactive<{ status: AbsenceStatus | null; type: AbsenceType | null; year: number | null }>({
    status: null,
    type: null,
    year: null,
})

const columns = [
    { key: 'typeLabelText', label: t('absences.table.type') },
    { key: 'periodText', label: t('absences.table.period') },
    { key: 'daysText', label: t('absences.table.days') },
    { key: 'status', label: t('absences.table.status') },
    { key: 'createdAtText', label: t('absences.table.requestedAt') },
]

const statusOptions = [
    { label: t('absences.status.pending'), value: 'pending' },
    { label: t('absences.status.approved'), value: 'approved' },
    { label: t('absences.status.rejected'), value: 'rejected' },
    { label: t('absences.status.cancelled'), value: 'cancelled' },
]

const typeOptions = computed(() => policies.value.map(p => ({ label: p.label, value: p.type })))

const yearOptions = computed(() => {
    const current = new Date().getFullYear()
    return [current + 1, current, current - 1, current - 2].map(y => ({ label: String(y), value: y }))
})

const rows = computed<Row[]>(() =>
    requests.value.map(r => ({
        ...r,
        typeLabelText: r.label,
        periodText: formatRange(r),
        daysText: formatDays(r.countedDays),
        createdAtText: formatDate(r.createdAt),
    })),
)

function openDetail(item: Record<string, unknown>) {
    selected.value = item as Row
    detailDrawerOpen.value = true
}

async function loadRequests() {
    // Scope to the current user: the collection endpoint returns every user's
    // requests for admins, which would leak the whole team into "Mes absences".
    const userId = useAuthStore().user?.id
    if (!userId) {
        requests.value = []
        return
    }
    const f: AbsenceRequestFilters = { user: userId }
    if (filters.status) f.status = filters.status
    if (filters.type) f.type = filters.type
    if (filters.year) f.year = filters.year
    requests.value = await service.getRequests(f)
}

async function reload() {
    // Scope balances to the current user: the collection endpoint returns every
    // user's balance for admins, which would pollute the personal "Mes absences" view.
    const userId = useAuthStore().user?.id
    const [bal] = await Promise.all([
        userId ? service.getBalances({ user: userId }) : Promise.resolve([]),
        loadRequests(),
    ])
    balances.value = bal
}

watch(() => [filters.status, filters.type, filters.year], loadRequests)

onMounted(async () => {
    policies.value = await service.getPolicies()
    await reload()
})
</script>
