<!--
  -   This file is a part of the SteamWar software.
  -
  -   Copyright (C) 2023 SteamWar.de-Serverteam
  -
  -   This program is free software: you can redistribute it and/or modify
  -   it under the terms of the GNU Affero General Public License as published by
  -   the Free Software Foundation, either version 3 of the License, or
  -   (at your option) any later version.
  -
  -   This program is distributed in the hope that it will be useful,
  -   but WITHOUT ANY WARRANTY; without even the implied warranty of
  -   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  -   GNU Affero General Public License for more details.
  -
  -   You should have received a copy of the GNU Affero General Public License
  -   along with this program.  If not, see <https://www.gnu.org/licenses/>.
  -->

<script lang="ts">
    import { run, preventDefault } from "svelte/legacy";

    import { Button, Card, Checkbox, Input, Label, Navbar, NavBrand, Radio, Spinner } from "flowbite-svelte";
    import { ArrowLeftOutline } from "flowbite-svelte-icons";
    import { capitalize } from "../util.ts";
    import { permsRepo } from "@repo/perms.ts";
    import { me } from "@stores/me.ts";
    import SWButton from "@components/styled/SWButton.svelte";
    import SWModal from "@components/styled/SWModal.svelte";
    import { userRepo } from "@repo/user.ts";
    import { dataRepo } from "@repo/data.ts";
    import type { Player } from "@type/data";

    let search = $state("");
    let playersList: Player[] = $state([]);
    let debounceTimer: NodeJS.Timeout;

    function fetchPlayers(searchTerm: string) {
        clearTimeout(debounceTimer);
        debounceTimer = setTimeout(async () => {
            const res = await $dataRepo.queryPlayers(searchTerm || undefined, undefined, undefined, 100, 0, undefined, undefined);
            playersList = res.players;
        }, 300);
    }

    $effect(() => {
        fetchPlayers(search);
    });

    let selectedPlayer: string | null = $state(null);
    let selectedPlayerName: string = $state("");
    let playerPerms = $state(loadPlayer(selectedPlayer));

    let prefixEdit = $state("PREFIX_NONE");
    let activePerms: string[] = $state([]);

    let resetPasswordModal = $state(false);
    let resetPassword = $state("");
    let resetPasswordRepeat = $state("");

    function loadPlayer(id: string | null) {
        if (!id) {
            return;
        }
        return $permsRepo.getPerms(id).then((value) => {
            activePerms = value.perms;
            prefixEdit = value.prefix.name;
            return value;
        });
    }

    function togglePerm(perm: string) {
        return () => {
            if (activePerms.includes(perm)) {
                activePerms = activePerms.filter((value) => value !== perm);
            } else {
                activePerms = [...activePerms, perm];
            }
        };
    }

    function save() {
        playerPerms!.then(async (perms) => {
            if (perms.prefix.name != prefixEdit) {
                await $permsRepo.setPrefix(selectedPlayer!, prefixEdit);
            }

            for (let value of activePerms) {
                if (!perms.perms.includes(value)) {
                    await $permsRepo.addPerm(selectedPlayer!, value);
                }
            }

            for (let value of perms.perms) {
                if (!activePerms.includes(value)) {
                    await $permsRepo.removePerm(selectedPlayer!, value);
                }
            }

            playerPerms = loadPlayer(selectedPlayer);
        });
    }

    let permsFuture = $permsRepo.listPerms();

    function resetPW() {
        if (resetPassword === resetPasswordRepeat) {
            $userRepo.setPassword(selectedPlayer!, resetPassword);
        }
        resetResetPassword();
    }

    function resetResetPassword() {
        resetPassword = "";
        resetPasswordRepeat = "";
        resetPasswordModal = false;
    }

    run(() => {
        playerPerms = loadPlayer(selectedPlayer);
    });
</script>

<div class="flex flex-col h-screen overflow-hidden">
    <Navbar>
        {#snippet children({ hidden, toggle })}
            <NavBrand href="#">
                <ArrowLeftOutline></ArrowLeftOutline>
                <span class="ml-4 self-center whitespace-nowrap text-xl font-semibold dark:text-white"> Permissions </span>
            </NavBrand>
        {/snippet}
    </Navbar>

    <div class="p-4 flex-1 overflow-hidden">
        <div class="grid md:grid-cols-3 grid-cols-1 h-full gap-8">
            <Card class="h-full flex flex-col overflow-hidden !max-w-full">
                <div class="border-b border-b-gray-600 pb-2">
                    <Label for="user_search" class="mb-2">Search Users...</Label>
                    <Input type="text" id="user_search" placeholder="Name..." bind:value={search} />
                </div>
                {#if playersList.length < 100}
                    <ul class="flex-1 overflow-scroll">
                        {#each playersList as player (player.uuid)}
                            <li
                                class="p-4 transition-colors hover:bg-gray-700 cursor-pointer"
                                class:text-orange-500={player.uuid === selectedPlayer}
                                onclick={preventDefault(() => {
                                    selectedPlayer = player.uuid;
                                    selectedPlayerName = player.name;
                                })}
                            >
                                {player.name}
                            </li>
                        {/each}
                    </ul>
                {/if}
            </Card>
            <Card class="!max-w-full" style="grid-column: 2/4">
                {#if selectedPlayer}
                    <h1 class="text-3xl">{selectedPlayerName}</h1>
                    {#await permsFuture}
                        <Spinner></Spinner>
                    {:then perms}
                        {#await playerPerms}
                            <Spinner></Spinner>
                        {:then player}
                            <h1>Prefix</h1>
                            {#each Object.entries(perms.prefixes) as [key, prefix]}
                                <Radio name="prefix" bind:group={prefixEdit} value={prefix.name}>{capitalize(prefix.name.substring(7).toLowerCase())}</Radio>
                            {/each}
                            <h1>Permissions</h1>
                            {#each perms.perms as perm}
                                <Checkbox checked={activePerms.includes(perm)} onclick={togglePerm(perm)}>{capitalize(perm.toLowerCase())}</Checkbox>
                            {/each}
                            <div class="mt-4">
                                <Button disabled={prefixEdit === (player?.prefix.name ?? "") && activePerms === (player?.perms ?? [])} onclick={save}>Save</Button>
                                {#if $me != null && $me.perms.includes("ADMINISTRATION")}
                                    <Button onclick={() => (resetPasswordModal = true)}>Reset Password</Button>

                                    <SWModal bind:open={resetPasswordModal} title="Reset Password">
                                        <Label for="new_password">New Password</Label>
                                        <Input type="password" id="new_password" placeholder="New Password" bind:value={resetPassword} />
                                        <Label for="repeat_password">Repeat Password</Label>
                                        <Input type="password" id="repeat_password" placeholder="Repeat Password" bind:value={resetPasswordRepeat} />

                                        {#snippet footer()}
                                            <Button class="ml-auto mr-4" onclick={resetResetPassword}>Cancel</Button>
                                            <Button disabled={resetPassword === "" || resetPassword !== resetPasswordRepeat} onclick={resetPW}>Reset Password</Button>
                                        {/snippet}
                                    </SWModal>
                                {/if}
                            </div>
                        {:catch error}
                            <p>{error.toString()}</p>
                        {/await}
                    {:catch error}
                        <p>{error.toString()}</p>
                    {/await}
                {/if}
            </Card>
        </div>
    </div>
</div>
