<template>
    <div>
        <PageHeader>
            {{ $t("absences.teamTitle") }}
        </PageHeader>

        <div class="flex flex-col gap-6">
        <!-- KPIs -->
        <div class="grid grid-cols-1 gap-4 sm:grid-cols-3">
            <div class="rounded-lg border border-neutral-200 bg-white p-4">
                <p class="text-sm text-neutral-500">
                    {{ $t("absences.admin.kpis.pending") }}
                </p>
                <p class="mt-1 text-3xl font-bold text-amber-600">
                    {{ kpis.pending }}
                </p>
            </div>
            <div class="rounded-lg border border-neutral-200 bg-white p-4">
                <p class="text-sm text-neutral-500">
                    {{ $t("absences.admin.kpis.todayAbsent") }}
                </p>
                <p class="mt-1 text-3xl font-bold text-primary-500">
                    {{ kpis.today }}
                </p>
            </div>
            <div class="rounded-lg border border-neutral-200 bg-white p-4">
                <p class="text-sm text-neutral-500">
                    {{ $t("absences.admin.kpis.weekAbsent") }}
                </p>
                <p class="mt-1 text-3xl font-bold text-primary-500">
                    {{ kpis.week }}
                </p>
            </div>
        </div>

        <MalioTabList v-model="activeTab" :tabs="tabs">
            <!-- Requests -->
            <template #requests>
                <div class="flex min-h-[30rem] flex-col gap-4 pt-10">
                    <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-48"
                        />
                        <MalioSelect
                            v-model="filters.type"
                            :label="$t('absences.table.type')"
                            :options="typeOptions"
                            :empty-option-label="
                                $t('absences.filters.allTypes')
                            "
                            group-class="w-48"
                        />
                        <MalioSelect
                            v-model="filters.user"
                            :label="$t('absences.table.employee')"
                            :options="employeeOptions"
                            :empty-option-label="
                                $t('absences.filters.allEmployees')
                            "
                            group-class="w-48"
                        />
                    </div>

                    <MalioDataTable
                        :columns="requestColumns"
                        :items="requestRows"
                        :total-items="requestRows.length"
                        :empty-message="$t('absences.noRequests')"
                        @row-click="openDetail"
                    >
                        <template #cell-status="{ item }">
                            <StatusBadge
                                :label="
                                    statusLabel((item as RequestRow).status)
                                "
                                :variant="
                                    statusVariant((item as RequestRow).status)
                                "
                                :icon="statusIcon((item as RequestRow).status)"
                            />
                        </template>
                        <template #cell-actions="{ item }">
                            <div
                                v-if="(item as RequestRow).status === 'pending'"
                                class="flex gap-1"
                                @click.stop
                            >
                                <MalioButtonIcon
                                    icon="mdi:check"
                                    :aria-label="$t('absences.review.approve')"
                                    button-class="!bg-green-100 !text-green-700"
                                    :icon-size="18"
                                    @click="approve(item as RequestRow)"
                                />
                                <MalioButtonIcon
                                    icon="mdi:close"
                                    :aria-label="$t('absences.review.reject')"
                                    button-class="!bg-red-100 !text-red-700"
                                    :icon-size="18"
                                    @click="openReject(item as RequestRow)"
                                />
                            </div>
                            <span v-else class="text-neutral-300">—</span>
                        </template>
                    </MalioDataTable>
                </div>
            </template>

            <!-- Calendar -->
            <template #calendar>
                <div class="min-h-[30rem] pt-10">
                    <AbsenceCalendar
                        :absences="calendarAbsences"
                        @range-change="loadCalendar"
                    />
                </div>
            </template>

            <!-- Balances -->
            <template #balances>
                <div class="min-h-[30rem] pt-10">
                    <MalioDataTable
                        :columns="balanceColumns"
                        :items="balanceRows"
                        :total-items="balanceRows.length"
                        :row-clickable="false"
                        :empty-message="$t('absences.noBalance')"
                    >
                        <template #cell-actions="{ item }">
                            <div class="flex justify-end">
                                <MalioButton
                                    :label="
                                        $t(
                                            'absences.admin.balancesTable.adjust',
                                        )
                                    "
                                    variant="secondary"
                                    icon-name="mdi:pencil"
                                    icon-position="left"
                                    button-class="w-auto"
                                    @click="openAdjust(item as BalanceRow)"
                                />
                            </div>
                        </template>
                    </MalioDataTable>
                </div>
            </template>

            <!-- Employees -->
            <template #employees>
                <div class="min-h-[30rem] pt-10">
                    <MalioDataTable
                        :columns="employeeColumns"
                        :items="employeeRows"
                        :total-items="employeeRows.length"
                        :empty-message="$t('absences.admin.employees.empty')"
                        @row-click="openEmployee"
                    />
                </div>
            </template>
        </MalioTabList>

        <AbsenceDetailDrawer
            v-model="detailOpen"
            :request="selectedRequest"
            :can-cancel="
                selectedRequest?.status === 'pending' ||
                selectedRequest?.status === 'approved'
            "
            @cancelled="reloadRequests"
        />
        <AbsenceRejectDrawer
            v-model="rejectOpen"
            :request="selectedRequest"
            @rejected="reloadRequests"
        />
        <AbsenceBalanceAdjustDrawer
            v-model="adjustOpen"
            :balance="selectedBalance"
            @adjusted="loadBalances"
        />
        <EmployeeDrawer
            v-model="employeeDrawerOpen"
            :user="selectedEmployee"
            @saved="loadEmployees"
        />
        </div>
    </div>
</template>

<script setup lang="ts">
import type {
    AbsenceBalance,
    AbsenceRequest,
    AbsenceStatus,
    AbsenceType,
} from "~/modules/absence/services/dto/absence";
import {
    useAbsenceService,
    type AbsenceRequestFilters,
} from "~/modules/absence/services/absences";
import { useUserService } from "~/services/users";
import type { UserData } from "~/services/dto/user-data";

definePageMeta({ middleware: ["admin"] });

type RequestRow = AbsenceRequest & {
    employeeText: string;
    typeLabelText: string;
    periodText: string;
    daysText: string;
    createdAtText: string;
};
type BalanceRow = AbsenceBalance & {
    employeeText: string;
    availableText: string;
};
type EmployeeRow = UserData & {
    contractText: string;
    cpTakenText: string;
    cpRemainingText: string;
};

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

useHead({ title: t("absences.teamTitle") });

const activeTab = ref("requests");
const tabs = [
    {
        key: "requests",
        label: t("absences.admin.tabs.requests"),
        icon: "mdi:format-list-bulleted",
    },
    {
        key: "calendar",
        label: t("absences.admin.tabs.calendar"),
        icon: "mdi:calendar-month",
    },
    {
        key: "balances",
        label: t("absences.admin.tabs.balances"),
        icon: "mdi:scale-balance",
    },
    {
        key: "employees",
        label: t("absences.admin.tabs.employees"),
        icon: "mdi:account-group",
    },
];

const requests = ref<AbsenceRequest[]>([]);
const balances = ref<AbsenceBalance[]>([]);
const calendarAbsences = ref<AbsenceRequest[]>([]);

const employees = ref<UserData[]>([]);
const employeeDrawerOpen = ref(false);
const selectedEmployee = ref<UserData | null>(null);

const detailOpen = ref(false);
const rejectOpen = ref(false);
const adjustOpen = ref(false);
const selectedRequest = ref<AbsenceRequest | null>(null);
const selectedBalance = ref<AbsenceBalance | null>(null);

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

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 = [
    { label: t("absences.types.cp"), value: "cp" },
    { label: t("absences.types.mariage_pacs"), value: "mariage_pacs" },
    { label: t("absences.types.conge_parental"), value: "conge_parental" },
    { label: t("absences.types.deces"), value: "deces" },
    { label: t("absences.types.maladie"), value: "maladie" },
];

const employeeOptions = computed(() => {
    const map = new Map<number, string>();
    for (const r of requests.value) map.set(r.user.id, r.user.username);
    for (const b of balances.value) map.set(b.user.id, b.user.username);
    return [...map.entries()].map(([value, label]) => ({ value, label }));
});

const requestColumns = [
    { key: "employeeText", label: t("absences.table.employee") },
    { 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") },
    { key: "actions", label: t("absences.table.actions") },
];

const requestRows = computed<RequestRow[]>(() =>
    requests.value.map((r) => ({
        ...r,
        employeeText: r.user.username,
        typeLabelText: r.label,
        periodText: formatRange(r),
        daysText: formatDays(r.countedDays),
        createdAtText: formatDate(r.createdAt),
    })),
);

const balanceColumns = [
    { key: "employeeText", label: t("absences.admin.balancesTable.employee") },
    { key: "label", label: t("absences.admin.balancesTable.type") },
    { key: "period", label: t("absences.admin.balancesTable.period") },
    { key: "acquired", label: t("absences.admin.balancesTable.acquired") },
    { key: "acquiring", label: t("absences.admin.balancesTable.acquiring") },
    { key: "taken", label: t("absences.admin.balancesTable.taken") },
    { key: "pending", label: t("absences.admin.balancesTable.pending") },
    {
        key: "availableText",
        label: t("absences.admin.balancesTable.available"),
    },
    { key: "actions", label: "" },
];

const balanceRows = computed<BalanceRow[]>(() =>
    balances.value.map((b) => ({
        ...b,
        employeeText: b.user.username,
        availableText: formatDays(b.available),
    })),
);

const employeeColumns = [
    { key: "username", label: t("absences.admin.employees.columns.name") },
    { key: "contractText", label: t("absences.admin.employees.columns.contract") },
    { key: "cpTakenText", label: t("absences.admin.employees.columns.cpTaken") },
    { key: "cpRemainingText", label: t("absences.admin.employees.columns.cpRemaining") },
];

const employeeRows = computed<EmployeeRow[]>(() => {
    // Map user.id -> solde CP de la période courante.
    const cpByUser = new Map<number, AbsenceBalance>();
    for (const b of balances.value) {
        if (b.type === "cp") cpByUser.set(b.user.id, b);
    }
    const dash = t("absences.admin.employees.noContract");
    return employees.value.map((u) => {
        const cp = cpByUser.get(u.id);
        return {
            ...u,
            contractText: u.contractType ?? dash,
            cpTakenText: cp ? formatDays(cp.taken) : dash,
            cpRemainingText: cp ? formatDays(cp.available) : dash,
        };
    });
});

const kpis = computed(() => {
    const today = new Date().toISOString().slice(0, 10);
    const now = new Date();
    const day = (now.getDay() + 6) % 7;
    const monday = new Date(now);
    monday.setDate(now.getDate() - day);
    const sunday = new Date(monday);
    sunday.setDate(monday.getDate() + 6);
    const mondayStr = monday.toISOString().slice(0, 10);
    const sundayStr = sunday.toISOString().slice(0, 10);

    const approved = requests.value.filter((r) => r.status === "approved");
    const todayUsers = new Set(
        approved
            .filter(
                (r) =>
                    r.startDate.slice(0, 10) <= today &&
                    r.endDate.slice(0, 10) >= today,
            )
            .map((r) => r.user.id),
    );
    const weekUsers = new Set(
        approved
            .filter(
                (r) =>
                    r.startDate.slice(0, 10) <= sundayStr &&
                    r.endDate.slice(0, 10) >= mondayStr,
            )
            .map((r) => r.user.id),
    );

    return {
        pending: requests.value.filter((r) => r.status === "pending").length,
        today: todayUsers.size,
        week: weekUsers.size,
    };
});

function openDetail(item: Record<string, unknown>) {
    selectedRequest.value = item as RequestRow;
    detailOpen.value = true;
}

function openReject(row: RequestRow) {
    selectedRequest.value = row;
    rejectOpen.value = true;
}

function openAdjust(row: BalanceRow) {
    selectedBalance.value = row;
    adjustOpen.value = true;
}

async function approve(row: RequestRow) {
    await service.approve(row.id);
    await reloadRequests();
}

async function reloadRequests() {
    const f: AbsenceRequestFilters = {};
    if (filters.status) f.status = filters.status;
    if (filters.type) f.type = filters.type;
    if (filters.user) f.user = filters.user;
    requests.value = await service.getRequests(f);
}

async function loadBalances() {
    balances.value = await service.getBalances();
}

async function loadEmployees() {
    const all = await useUserService().getAll();
    employees.value = all.filter((u) => u.isEmployee);
}

function openEmployee(item: Record<string, unknown>) {
    selectedEmployee.value = item as EmployeeRow;
    employeeDrawerOpen.value = true;
}

async function loadCalendar(from: string, to: string) {
    calendarAbsences.value = await service.getCalendar(from, to);
}

watch(() => [filters.status, filters.type, filters.user], reloadRequests);

onMounted(async () => {
    await Promise.all([reloadRequests(), loadBalances(), loadEmployees()]);
});
</script>

<style scoped>
/* MalioTabList (lib) : aère les onglets verticalement (espace haut/bas du texte) */
:deep([role="tab"]) {
    padding-top: 0.9rem;
    padding-bottom: 0.25rem;
}
</style>
