<!--
  -   This file is a part of the SteamWar software.
  -
  -   Copyright (C) 2025 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 FightEditRow from "./FightEditRow.svelte";

    import type { EventFightEdit } from "@type/event";
    import { createSvelteTable, FlexRender } from "@components/ui/data-table";
    import { type ColumnFiltersState, getCoreRowModel, getFilteredRowModel, getGroupedRowModel, getSortedRowModel, type RowSelectionState, type SortingState } from "@tanstack/table-core";
    import { columns } from "./columns";
    import { Table, TableBody, TableCell, TableHead, TableHeader, TableRow } from "@components/ui/table";
    import { Checkbox } from "@components/ui/checkbox";
    import { Menubar, MenubarContent, MenubarItem, MenubarGroup, MenubarGroupHeading, MenubarMenu, MenubarTrigger, MenubarSub, MenubarSubTrigger, MenubarSubContent } from "@components/ui/menubar";
    import { Dialog, DialogContent, DialogDescription, DialogFooter, DialogHeader, DialogTitle } from "@components/ui/dialog";
    import FightEdit from "@components/moderator/components/FightEdit.svelte";
    import { Button } from "@components/ui/button";
    import { eventRepo } from "@components/repo/event";
    import GroupEditDialog from "./GroupEditDialog.svelte";
    import GroupResultsDialog from "./GroupResultsDialog.svelte";
    import type { ResponseGroups } from "@type/event";
    import { EditIcon, GroupIcon, LinkIcon } from "lucide-svelte";
    import { DropdownMenu, DropdownMenuContent, DropdownMenuItem, DropdownMenuTrigger } from "@components/ui/dropdown-menu";
    import GroupSelector from "@components/moderator/components/GroupSelector.svelte";
    import { fightRepo } from "@components/repo/fight";
    import type { EventModel } from "./eventmodel.svelte";

    let { data = $bindable(), refresh }: { data: EventModel; refresh: () => void } = $props();

    let sorting = $state<SortingState>([]);
    let columnFilters = $state<ColumnFiltersState>([]);
    let selection = $state<RowSelectionState>({});

    const table = createSvelteTable({
        get data() {
            return data.fights;
        },
        initialState: {
            columnOrder: ["auswahl", "begegnung", "group"],
        },
        state: {
            get sorting() {
                return sorting;
            },
            get columnFilters() {
                return columnFilters;
            },
            get grouping() {
                return ["group"];
            },
            get rowSelection() {
                return selection;
            },
        },
        onSortingChange: (updater) => {
            if (typeof updater === "function") {
                sorting = updater(sorting);
            } else {
                sorting = updater;
            }
        },
        onColumnFiltersChange: (updater) => {
            if (typeof updater === "function") {
                columnFilters = updater(columnFilters);
            } else {
                columnFilters = updater;
            }
        },
        onRowSelectionChange: (updater) => {
            if (typeof updater === "function") {
                selection = updater(selection);
            } else {
                selection = updater;
            }
        },
        columns,
        getCoreRowModel: getCoreRowModel(),
        getSortedRowModel: getSortedRowModel(),
        getFilteredRowModel: getFilteredRowModel(),
        getGroupedRowModel: getGroupedRowModel(),
        groupedColumnMode: "remove",
        getRowId: (row) => row.id.toString(),
    });

    let createOpen = $state(false);
    let editGroupOpen = $state(false);
    let selectedGroup: ResponseGroups | null = $state(null);
    let groupResultsOpen = $state(false);
    let selectedGroupForResults: ResponseGroups | null = $state(null);

    let groupChangeOpen = $state(false);
    let groupChangeSelected: number | null = $state(null);

    async function handleSave(fight: EventFightEdit) {
        await $eventRepo.createFight(data.event.id.toString(), {
            ...fight,
            blueTeam: fight.blueTeam.id,
            redTeam: fight.redTeam.id,
        });

        refresh();
        createOpen = false;
    }

    function openGroupEditDialog(group: ResponseGroups) {
        selectedGroup = group;
        editGroupOpen = true;
    }

    function openGroupResultsDialog(group: ResponseGroups) {
        selectedGroupForResults = group;
        groupResultsOpen = true;
    }
</script>

<Dialog bind:open={createOpen}>
    <DialogContent>
        <DialogHeader>
            <DialogTitle>Fight Erstellen</DialogTitle>
            <DialogDescription>Hier kannst du einen neuen Fight erstellen</DialogDescription>
        </DialogHeader>
        <FightEdit fight={null} {data} onSave={handleSave}>
            {#snippet actions(dirty, submit)}
                <DialogFooter>
                    <Button disabled={!dirty} onclick={submit}>Speichern</Button>
                </DialogFooter>
            {/snippet}
        </FightEdit>
    </DialogContent>
</Dialog>

{#if selectedGroup}
    <GroupEditDialog bind:open={editGroupOpen} group={selectedGroup} event={data.event} bind:groups={data.groups} />
{/if}

{#if selectedGroupForResults}
    <GroupResultsDialog bind:open={groupResultsOpen} group={selectedGroupForResults} teams={data.teams} fights={data.fights} />
{/if}

<Dialog bind:open={groupChangeOpen}>
    <DialogContent>
        <DialogHeader>
            <DialogTitle>Gruppe Ändern</DialogTitle>
            <DialogDescription>Hier kannst du die Gruppe der ausgewählten Kämpfe ändern</DialogDescription>
        </DialogHeader>
        <GroupSelector event={data.event} bind:groups={data.groups} bind:value={groupChangeSelected} />
        <DialogFooter>
            <Button
                onclick={async () => {
                    groupChangeOpen = false;
                    let group = data.groups.find((g) => g.id === groupChangeSelected);
                    if (group) {
                        let selectedGroups = table.getSelectedRowModel().rows.map((row) => row.original);
                        for (const g of selectedGroups) {
                            await $fightRepo.updateFight(data.event.id, g.id, {
                                group: group.id,
                                spielmodus: null,
                                map: null,
                                blueTeam: null,
                                redTeam: null,
                                start: null,
                                spectatePort: null,
                            });
                        }

                        refresh();
                    }
                }}>Speichern</Button
            >
        </DialogFooter>
    </DialogContent>
</Dialog>

<div class="flex items-center justify-between">
    <Menubar>
        <MenubarMenu>
            <MenubarTrigger>Mehrfach Bearbeiten</MenubarTrigger>
            <MenubarContent>
                <MenubarItem onclick={() => (groupChangeOpen = true)}>Gruppe Ändern</MenubarItem>
                <MenubarItem disabled>Startzeit Verschieben</MenubarItem>
                <MenubarItem disabled>Spectate Port Ändern</MenubarItem>
                <MenubarItem
                    onclick={async () => {
                        let selectedGroups = table.getSelectedRowModel().rows.map((row) => row.original);
                        for (const g of selectedGroups) {
                            await $fightRepo.deleteFight(data.event.id, g.id);
                        }

                        refresh();
                    }}>Kämpfe Löschen</MenubarItem
                >
            </MenubarContent>
        </MenubarMenu>
        <MenubarMenu>
            <MenubarTrigger>Erstellen</MenubarTrigger>
            <MenubarContent>
                <MenubarItem onclick={() => (createOpen = true)}>Fight Erstellen</MenubarItem>
                <MenubarGroup>
                    <MenubarGroupHeading>Generatoren</MenubarGroupHeading>
                    <a href="#/event/{data.event.id}/generate">
                        <MenubarItem>Gruppenphase</MenubarItem>
                    </a>
                </MenubarGroup>
            </MenubarContent>
        </MenubarMenu>
        <MenubarMenu>
            <MenubarTrigger disabled={!data.groups.length}>Gruppen</MenubarTrigger>
            <MenubarContent>
                {#each data.groups as group (group.id)}
                    <MenubarSub>
                        <MenubarSubTrigger>
                            {group.name}
                        </MenubarSubTrigger>
                        <MenubarSubContent>
                            <MenubarItem onclick={() => openGroupEditDialog(group)}>Bearbeiten</MenubarItem>
                            <MenubarItem onclick={() => openGroupResultsDialog(group)}>Gruppen Ergebnisse</MenubarItem>
                        </MenubarSubContent>
                    </MenubarSub>
                {/each}
            </MenubarContent>
        </MenubarMenu>
    </Menubar>
    <Button variant="outline" class="ml-4" onclick={refresh}>Neu laden</Button>
</div>

<Table>
    <TableHeader>
        {#each table.getHeaderGroups() as headerGroup (headerGroup.id)}
            <TableRow>
                {#each headerGroup.headers as header (header.id)}
                    <TableHead>
                        {#if !header.isPlaceholder}
                            <FlexRender content={header.column.columnDef.header} context={header.getContext()} />
                        {/if}
                    </TableHead>
                {/each}
                <TableHead></TableHead>
            </TableRow>
        {/each}
    </TableHeader>
    <TableBody>
        {#each table.getRowModel().rows as groupRow (groupRow.id)}
            {#if groupRow.getIsGrouped()}
                {@const group = data.groups.find((g) => g.id == groupRow.getValue("group"))}
                <TableRow class="font-bold">
                    <TableCell colspan={columns.length - 1}>
                        <Checkbox
                            checked={groupRow.getIsSelected()}
                            indeterminate={groupRow.getIsSomeSelected() && !groupRow.getIsSelected()}
                            onCheckedChange={() => groupRow.toggleSelected()}
                            class="mr-4"
                        />
                        {group?.name ?? "Keine Gruppe"}
                    </TableCell>
                    <TableCell class="text-right">
                        {#if group}
                            <Button variant="ghost" size="icon" onclick={() => openGroupEditDialog(group!)}>
                                <EditIcon />
                            </Button>
                            <Button variant="ghost" size="icon" onclick={() => openGroupResultsDialog(group!)}>
                                <GroupIcon />
                            </Button>
                        {/if}
                        <DropdownMenu>
                            <DropdownMenuTrigger>
                                <Button variant="ghost" size="icon">
                                    <LinkIcon />
                                </Button>
                            </DropdownMenuTrigger>
                            <DropdownMenuContent>
                                <DropdownMenuItem
                                    onclick={() => navigator.clipboard.writeText(`<group-table data-event="${data.event.id}"${group ? ` data-group="${group?.id}"` : ""}> </group-table>`)}
                                    >Punkte Tabelle</DropdownMenuItem
                                >
                                <DropdownMenuItem
                                    onclick={() => navigator.clipboard.writeText(`<fight-table data-event="${data.event.id}"${group ? ` data-group="${group?.id}"` : ""}> </group-table>`)}
                                    >Kampf Tabelle</DropdownMenuItem
                                >
                            </DropdownMenuContent>
                        </DropdownMenu>
                    </TableCell>
                </TableRow>
                {#each groupRow.subRows as row (row.id)}
                    <TableRow data-state={row.getIsSelected() && "selected"}>
                        {#each row.getVisibleCells() as cell (cell.id)}
                            <TableCell>
                                <FlexRender content={cell.column.columnDef.cell} context={cell.getContext()} />
                            </TableCell>
                        {/each}
                        <TableCell class="text-right">
                            <FightEditRow fight={row.original} {data} onupdate={(update) => (data._fights = data._fights.map((v) => (v.id === update.id ? update : v)))} {refresh}></FightEditRow>
                        </TableCell>
                    </TableRow>
                {/each}
            {:else}
                <TableRow data-state={groupRow.getIsSelected() && "selected"}>
                    {#each groupRow.getVisibleCells() as cell (cell.id)}
                        <TableCell>
                            <FlexRender content={cell.column.columnDef.cell} context={cell.getContext()} />
                        </TableCell>
                    {/each}
                </TableRow>
            {/if}
        {:else}
            <TableRow>
                <TableCell colspan={columns.length} class="h-24 text-center">No results.</TableCell>
            </TableRow>
        {/each}
    </TableBody>
</Table>
