<script lang="ts">
    import { afterNavigate, goto } from "$app/navigation";
    import type { UserObj } from "$lib/User.svelte";
    import { env } from "$env/dynamic/public";
    import axios from "axios";
    import { onMount } from "svelte";
    import Modal from "$lib/Modal.svelte";
    import UserSvelte from "$lib/User.svelte";

    let users: UserObj[] = $state([]);
    let roles: string[] = $state([]);

    let showAddUser = $state(false);
    let addUserName = $state("");

    let showDeleteUser = $state(false);
    let showResetPassword = $state(false);
    let showChangeRole = $state(false);
    let selectedUser: UserObj | undefined = $state(undefined);
    let roleToChange: string = $state("");

    let error = $state("");

    async function loadUsers() {
        console.log("loading users");
        return axios
            .get(
                `${env.PUBLIC_JEOPARDY_SERVER_PROTOCOL}://${env.PUBLIC_JEOPARDY_SERVER}/admin/user/list`,
                {
                    withCredentials: true
                }
            )
            .then((response) => {
                if (response.status === 200) {
                    users = response.data;
                }
            })
            .catch((e) => {
                console.log(e);
            });
    }

    async function loadRoles() {
        console.log("loading roles");
        return axios
            .get(
                `${env.PUBLIC_JEOPARDY_SERVER_PROTOCOL}://${env.PUBLIC_JEOPARDY_SERVER}/admin/roles`,
                {
                    withCredentials: true
                }
            )
            .then((response) => {
                if (response.status === 200) {
                    roles = response.data;
                }
            })
            .catch((e) => {
                console.log(e);
            });
    }

    afterNavigate(() => {
        if (UserSvelte.role !== "admin") goto("/");
    });

    onMount(() => {
        if (UserSvelte.role !== "admin") goto("/");
        loadRoles().then(loadUsers);
    });

    async function addUserOk(): Promise<boolean> {
        error = "";
        if (addUserName.length <= 0) {
            error = "Gib einen Nutzernamen ein";
            return false;
        }

        return axios
            .put(
                `${env.PUBLIC_JEOPARDY_SERVER_PROTOCOL}://${env.PUBLIC_JEOPARDY_SERVER}/admin/user`,
                {
                    username: addUserName
                },
                {
                    withCredentials: true
                }
            )
            .then((response) => {
                if (response.status === 200) {
                    alert(`Passwort: ${response.data.password}`);
                    return true;
                } else {
                    throw false;
                }
            })
            .catch(() => {
                error = "Etwas ist schief gelaufen";
                return false;
            });
    }

    async function deleteUserOk(): Promise<boolean> {
        error = "";

        if (selectedUser === undefined) {
            error = "Etwas ist schief gelaufen. Kein Nutzer zum Löschen definiert.";
            return false;
        }

        return axios
            .delete(
                `${env.PUBLIC_JEOPARDY_SERVER_PROTOCOL}://${env.PUBLIC_JEOPARDY_SERVER}/admin/user`,
                {
                    withCredentials: true,
                    data: {
                        userid: selectedUser._id
                    }
                }
            )
            .then(() => {
                return true;
            })
            .catch(() => {
                error = "Nutzer konnte nicht gelöscht werden";
                return false;
            });
    }

    async function resetPasswordOk(): Promise<boolean> {
        error = "";

        if (selectedUser === undefined) {
            error = "Etwas ist schief gelaufen. Kein Nutzer zum Löschen definiert.";
            return false;
        }

        return axios
            .post(
                `${env.PUBLIC_JEOPARDY_SERVER_PROTOCOL}://${env.PUBLIC_JEOPARDY_SERVER}/admin/user/resetpw`,
                {
                    userid: selectedUser._id
                },
                {
                    withCredentials: true
                }
            )
            .then((response) => {
                if (response.status === 200) {
                    alert(`Passwort: ${response.data.password}`);
                    return true;
                } else {
                    throw false;
                }
            })
            .catch(() => {
                error = "Etwas ist schief gelaufen";
                return false;
            });
    }

    async function changeRoleOk(): Promise<boolean> {
        error = "";

        if (selectedUser === undefined) {
            error = "Etwas ist schief gelaufen. Kein Nutzer zum Löschen definiert.";
            return false;
        }

        if (roleToChange === selectedUser.role) {
            error = `${selectedUser.username} hat bereits die Rolle ${roleToChange}. Wähle eine andere Rolle aus.`;
            return false;
        }

        return axios
            .post(
                `${env.PUBLIC_JEOPARDY_SERVER_PROTOCOL}://${env.PUBLIC_JEOPARDY_SERVER}/admin/user/changerole`,
                {
                    userid: selectedUser._id,
                    role: roleToChange
                },
                {
                    withCredentials: true
                }
            )
            .then((response) => {
                if (response.status === 200) {
                    return true;
                } else {
                    throw false;
                }
            })
            .catch(() => {
                error = "Etwas ist schief gelaufen";
                return false;
            });
    }

    function addUserCancel() {
        error = "";
        addUserName = "";
    }

    function selectedUserCancel() {
        error = "";
        selectedUser = undefined;
        roleToChange = "";
    }
</script>

<div class="flex flex-col gap-4 p-4">
    <div class="flex items-center">
        <h2 class="text-4xl font-bold">Administration</h2>
        <div class="grow"></div>
        <button type="button" class="btn" onclick={() => goto("/")}>Zurück</button>
    </div>
    <div class="flex flex-col gap-2">
        {#each users as user (user._id)}
            <div class="flex justify-between gap-4 rounded-md border-1 p-2">
                <div class="shrink-0 grow-0 text-center align-middle">{user._id}</div>
                <div>{user.username}</div>
                <div>{user.role}</div>
                <div class="flex gap-2">
                    <!-- svelte-ignore a11y_consider_explicit_label -->
                    <button
                        type="button"
                        class="btn"
                        disabled={user._id === UserSvelte.id}
                        onclick={() => {
                            selectedUser = user;
                            roleToChange = selectedUser.role;
                            showChangeRole = true;
                        }}><i class="fa-solid fa-user"></i> Rolle ändern</button
                    >
                    <!-- svelte-ignore a11y_consider_explicit_label -->
                    <button
                        type="button"
                        class="btn"
                        disabled={user._id === UserSvelte.id}
                        onclick={() => {
                            selectedUser = user;
                            showResetPassword = true;
                        }}
                        ><i class="fa-solid fa-arrow-rotate-right"></i> Passwort zurücksetzen</button
                    >
                    <!-- svelte-ignore a11y_consider_explicit_label -->
                    <button
                        disabled={user._id === UserSvelte.id}
                        type="button"
                        class="btn border-red-600 text-red-600"
                        onclick={() => {
                            selectedUser = user;
                            showDeleteUser = true;
                        }}><i class="fa-solid fa-trash"></i></button
                    >
                </div>
            </div>
        {/each}
    </div>
    <button type="button" class="btn" onclick={() => (showAddUser = true)}>Nutzer hinzufügen</button
    >
</div>

<Modal bind:showModal={showAddUser} okFn={addUserOk} cancelFn={addUserCancel} oncloseFn={loadUsers}>
    {#snippet header()}
        <h2 class="text-3xl">Nutzer hinzufügen</h2>
    {/snippet}

    <div>
        <label for="username" class="">Name</label>
        <div>
            <input
                type="text"
                name="username"
                id="username"
                class="borders mt-2 mb-2 w-full"
                bind:value={addUserName}
            />
        </div>
        {#if error.length > 0}
            <div class="text-red-700">{error}</div>
        {/if}
    </div>
</Modal>

<Modal
    bind:showModal={showDeleteUser}
    okFn={deleteUserOk}
    cancelFn={selectedUserCancel}
    oncloseFn={loadUsers}
>
    {#snippet header()}
        <h2 class="text-3xl">Nutzer löschen</h2>
    {/snippet}

    <div>Soll Nutzer {selectedUser?.username} wirklich gelöscht werden?</div>
    {#if error.length > 0}
        <div class="text-red-700">{error}</div>
    {/if}
</Modal>

<Modal
    bind:showModal={showResetPassword}
    okFn={resetPasswordOk}
    cancelFn={selectedUserCancel}
    oncloseFn={loadUsers}
>
    {#snippet header()}
        <h2 class="text-3xl">Passwort zurücksetzen</h2>
    {/snippet}

    <div>
        Soll das Passwort von Nutzer {selectedUser?.username} wirklich zurückgesetzt werden?
    </div>
    {#if error.length > 0}
        <div class="text-red-700">{error}</div>
    {/if}
</Modal>

<Modal
    bind:showModal={showChangeRole}
    okFn={changeRoleOk}
    cancelFn={selectedUserCancel}
    oncloseFn={loadUsers}
>
    {#snippet header()}
        <h2 class="text-3xl">Rolle von {selectedUser?.username} ändern</h2>
    {/snippet}

    <div>
        {#if selectedUser}
            <select name="roles" id="role-select" class="btn w-full" bind:value={roleToChange}>
                {#each roles as role, index (index)}
                    <option value={role}>{role}</option>
                {/each}
            </select>
        {/if}
    </div>
    {#if error.length > 0}
        <div class="text-red-700">{error}</div>
    {/if}
</Modal>

<style>
    .borders {
        border: 1px solid black;
        border-radius: 5px;
        display: flex;
        padding: 2px;
    }
</style>
