/*
 *   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/>.
 */

import type {EventFight} from "@type/event.js";
import {fetchWithToken, tokenStore} from "./repo";
import {z} from "zod";
import {EventFightSchema} from "@type/event.js";
import type {Dayjs} from "dayjs";
import {derived} from "svelte/store";

export interface CreateFight {
    spielmodus: string;
    map: string;
    blueTeam: number;
    redTeam: number;
    start: Dayjs;
    kampfleiter: number | null;
    group: string | null;
}

export interface UpdateFight {
    spielmodus: string | null;
    map: string | null;
    blueTeam: number | null;
    redTeam: number | null;
    start: Dayjs | null;
    kampfleiter: number | null;
    group: string | null;
}

export class FightRepo {
    constructor(private token: string) {
    }

    public async listFights(eventId: number): Promise<EventFight[]> {
        return await fetchWithToken(this.token, `/events/${eventId}/fights`)
            .then(value => value.json())
            .then(value => z.array(EventFightSchema).parse(value));
    }

    public async createFight(eventId: number, fight: CreateFight): Promise<EventFight> {
        return await fetchWithToken(this.token, "/fights", {
            method: "POST",
            body: JSON.stringify({
                event: eventId,
                spielmodus: fight.spielmodus,
                map: fight.map,
                blueTeam: fight.blueTeam,
                redTeam: fight.redTeam,
                start: +fight.start,
                kampfleiter: fight.kampfleiter,
                group: fight.group,
            }),
        }).then(value => value.json())
            .then(EventFightSchema.parse);
    }

    public async updateFight(fightId: number, fight: UpdateFight): Promise<EventFight> {
        return await fetchWithToken(this.token, `/fights/${fightId}`, {
            method: "PUT",
            body: JSON.stringify({
                spielmodus: fight.spielmodus,
                map: fight.map,
                blueTeam: fight.blueTeam,
                redTeam: fight.redTeam,
                start: fight.start?.valueOf(),
                kampfleiter: fight.kampfleiter,
                group: fight.group,
            }),
        }).then(value => value.json())
            .then(EventFightSchema.parse);
    }

    public async deleteFight(fightId: number): Promise<void> {
        const res = await fetchWithToken(this.token, `/fights/${fightId}`, {
            method: "DELETE",
        });

        if (!res.ok) {
            throw new Error("Could not delete fight: " + res.statusText);
        }
    }
}

export const fightRepo = derived(tokenStore, ($token) => new FightRepo($token));
