<script setup lang="ts">
import { useNuxtApp } from 'nuxt/app';

import { longtimeCookieSetting } from '#shared/cookieSettings.ts';
import { PermissionAreas } from '#shared/helpers.ts';
import type { Dataset } from '~/components/Chart.vue';
import useConfig from '~/composables/useConfig.ts';
import useDialogue from '~/composables/useDialogue.ts';
import useSimpleHead from '~/composables/useSimpleHead.ts';
import { getUrlForLocale } from '~/src/domain.ts';

const { $translator: translator } = useNuxtApp();
const dialogue = useDialogue();
useSimpleHead({
    title: `${translator.translate('admin.header')} • Users`,
}, translator);

const tokenCookie = useCookie('token', longtimeCookieSetting);
const impersonatorCookie = useCookie('impersonator', longtimeCookieSetting);

const statsAsyncData = useFetch('/api/admin/stats');
const chartAsyncData = useFetch<Dataset>('/api/admin/stats/users-chart/_', { immediate: false });
await statsAsyncData;

const config = useConfig();
const stats = statsAsyncData.data;

const showUsers = ref(false);
const userFilter = ref('');
const localeFilter = ref(true);
const adminsFilter = ref(false);

const profilesByLocale = computed(() => {
    if (!stats.value) {
        return {};
    }
    return Object.fromEntries(Object.entries(stats.value.locales)
        .map(([locale, localeStats]) => [locale, localeStats.users] as const)
        .sort(([_aLocale, aUsers], [_bLocale, bUsers]) => bUsers - aUsers));
});

const router = useRouter();
const impersonate = async (email: string) => {
    const { token } = await $fetch(`/api/admin/impersonate/${encodeURIComponent(email)}`);
    impersonatorCookie.value = tokenCookie.value;
    tokenCookie.value = token;
    await router.push(`/${config.user.route}`);
    setTimeout(() => window.location.reload(), 500);
};

const erasure = async (id: string, email: string) => {
    await dialogue.confirm(`Are you sure you want to remove this account (${email})? ` +
        'This should only be done in two cases: ' +
        'an explicit GPDR request directly from the user, ' +
        'or having proof that owner is not yet 13 years old.', 'danger');

    if (await $fetch(`/api/user/data-erasure/${id}`, { method: 'POST' })) {
        await dialogue.alert(`Account ${email} removed successfully`, 'success');
    } else {
        await dialogue.alert(translator.translate('error.generic'), 'danger');
    }
};

const fetchChart = () => {
    if (chartAsyncData.status.value === 'idle') {
        chartAsyncData.execute();
    }
};

const setPersonally = async (userId: string, personally: string | null) => {
    await $fetch(`/api/admin/users/${userId}/set-personally`, {
        method: 'POST',
        body: { personally },
    });
    await dialogue.alert('Saved', 'success');
};
</script>

<template>
    <Page>
        <NotFound v-if="!$multiIsGranted([PermissionAreas.Users, PermissionAreas.Community])" />
        <div v-else>
            <p>
                <nuxt-link to="/admin">
                    <Icon v="user-cog" />
                    <T>admin.header</T>
                </nuxt-link>
            </p>
            <h2>
                <Icon v="user-cog" />
                Users
            </h2>

            <section>
                <details class="border mb-3" @click="showUsers = true">
                    <summary class="bg-light p-3">
                        <Icon v="users" />
                        Users
                        ({{ stats?.overall.users }} overall, {{ stats?.overall.admins }} admins)
                    </summary>
                    <div v-if="showUsers" class="border-top">
                        <ServerTable
                            endpoint="/api/admin/users"
                            :query="{ filter: userFilter || undefined, localeFilter: localeFilter || undefined, adminsFilter: adminsFilter || undefined }"
                            :columns="5"
                            count
                        >
                            <template #filter>
                                <input v-model="userFilter" class="form-control" :placeholder="$t('crud.filterLong')">
                                <button
                                    type="button"
                                    :class="['btn', adminsFilter ? 'btn-secondary' : 'btn-outline-secondary']"
                                    @click="adminsFilter = !adminsFilter"
                                >
                                    Only admins
                                </button>
                                <button
                                    type="button"
                                    :class="['btn', localeFilter ? 'btn-secondary' : 'btn-outline-secondary']"
                                    :disabled="!$multiIsGranted([
                                        PermissionAreas.Users,
                                        PermissionAreas.Community,
                                    ], '*')"
                                    @click="localeFilter = !localeFilter"
                                >
                                    Only this version
                                </button>
                            </template>

                            <template #header>
                                <th class="text-nowrap">
                                    <T>admin.user.user</T>
                                </th>
                                <th class="text-nowrap">
                                    <T>admin.user.createdAt</T>
                                </th>
                                <th class="text-nowrap">
                                    <T>admin.user.email</T>
                                </th>
                                <th class="text-nowrap">
                                    <T>admin.user.roles</T>
                                </th>
                                <th class="text-nowrap">
                                    <T>admin.user.profiles</T>
                                </th>
                            </template>

                            <template #row="s">
                                <td>
                                    <a :href="`${getUrlForLocale('_')}/@${s.el.username}`">@{{ s.el.username }}</a>
                                    <a
                                        v-if="$multiIsGranted([PermissionAreas.Superuser, PermissionAreas.Impersonate])"
                                        href="#"
                                        class="badge bg-primary text-white"
                                        @click.prevent="impersonate(s.el.email)"
                                    >
                                        <Icon v="user-secret" />
                                    </a>
                                    <nuxt-link
                                        v-if="$isGranted(PermissionAreas.Superuser)"
                                        :to="`/admin/audit-log/${s.el.username}/${s.el.id}`"
                                        class="badge bg-primary text-white"
                                    >
                                        <Icon v="file-search" />
                                    </nuxt-link>
                                    <a
                                        v-if="$multiIsGranted([PermissionAreas.Superuser, PermissionAreas.Community])"
                                        href="#"
                                        class="badge bg-danger text-white"
                                        @click.prevent="erasure(s.el.id, s.el.email)"
                                    >
                                        <Icon v="truck-plow" />
                                    </a>
                                </td>
                                <td>
                                    {{ $datetime($ulidTime(s.el.id)) }}
                                </td>
                                <td>
                                    <p>
                                        <a :href="`mailto:${s.el.email}`" target="_blank" rel="noopener">
                                            {{ s.el.email }}
                                        </a>
                                    </p>
                                    <form class="input-group" @submit.prevent="setPersonally(s.el.id, s.el.personally)">
                                        <input v-model="s.el.personally" type="text" placeholder="Met the team at… (Comma separated event names)" class="form-control form-control-sm">
                                        <button type="submit" class="btn btn-sm btn-outline-primary mt-1">
                                            Save
                                        </button>
                                    </form>

                                    <!--
                                    <ul v-if="s.el.socialConnections.length" class="list-inline">
                                        <li v-for="conn in s.el.socialConnections" class="list-inline-item">
                                            <Icon :v="socialProviders[conn].icon || conn" set="b"/>
                                        </li>
                                    </ul>
                                    -->
                                </td>
                                <td>
                                    <Roles :user="s.el" />
                                </td>
                                <td>
                                    <ul class="list-unstyled">
                                        <template v-for="locale in s.el.profiles">
                                            <li v-if="$locales[locale]" :key="locale">
                                                <LocaleLink :link="`/@${s.el.username}`" :locale="locale">
                                                    {{ $locales[locale].fullName }}
                                                </LocaleLink>
                                            </li>
                                        </template>
                                    </ul>
                                </td>
                            </template>
                        </ServerTable>
                    </div>
                </details>
            </section>

            <section>
                <details class="border" @toggle="fetchChart()">
                    <summary class="bg-light p-3">
                        <Icon v="chart-line" />
                        Chart
                    </summary>
                    <Loading :value="chartAsyncData.data.value" class="m-0">
                        <ChartSet name="users" :data="chartAsyncData.data.value!" init="cumulative" />
                    </Loading>
                </details>
            </section>

            <section>
                <Chart
                    label="number of profiles by locale"
                    :data="profilesByLocale"
                    type="bar"
                    :options="{
                        indexAxis: 'y',
                        responsive: true,
                        interaction: {
                            intersect: false,
                            mode: 'y',
                        },
                    }"
                />
            </section>
        </div>
    </Page>
</template>
