import express from "express";
import { getLogin, getTrusted } from "../auth";
import { addChoice, addVolatileData, getDateForWeekIndex, getToday, removeChoice, removeChoices, updateDepartureTime, updateNote } from "../service";
import { getDayOfWeekIndex, parseToken } from "../utils";
import { getWebsocket } from "../websocket";
import { callNotifikace } from "../notifikace";
import { UdalostEnum } from "../../../types";

/**
 * Ověří a vrátí index dne v týdnu z požadavku, za předpokladu, že byl předán, a je zároveň
 * roven nebo vyšší indexu dnešního dne.
 * 
 * @param req request
 * @returns index dne v týdnu
 */
const parseValidateFutureDayIndex = (req: any) => {
    if (req.body.dayIndex == null) {
        throw Error(`Nebyl předán index dne v týdnu.`);
    }
    const todayDayIndex = getDayOfWeekIndex(getToday());
    const dayIndex = parseInt(req.body.dayIndex);
    if (isNaN(dayIndex)) {
        throw Error(`Neplatný index dne v týdnu: ${req.body.dayIndex}`);
    }
    if (dayIndex < todayDayIndex) {
        throw Error(`Předaný index dne v týdnu (${dayIndex}) nesmí být nižší než dnešní den (${todayDayIndex})`);
    }
    return dayIndex;
}

const router = express.Router();

router.post("/addChoice", async (req, res, next) => {
    const login = getLogin(parseToken(req));
    const trusted = getTrusted(parseToken(req));
    if (req.body.locationIndex > -1) {
        let date = undefined;
        if (req.body.dayIndex != null) {
            let dayIndex;
            try {
                dayIndex = parseValidateFutureDayIndex(req);
            } catch (e: any) {
                return res.status(400).json({ error: e.message });
            }
            date = getDateForWeekIndex(dayIndex);
        }
        try {
            const data = await addChoice(login, trusted, req.body.locationIndex, req.body.foodIndex, date);
            getWebsocket().emit("message", await addVolatileData(data));
            return res.status(200).json(data);
        } catch (e: any) { next(e) }
    }
    return res.status(400); // TODO přidat popis chyby
});

router.post("/removeChoices", async (req, res, next) => {
    const login = getLogin(parseToken(req));
    const trusted = getTrusted(parseToken(req));
    let date = undefined;
    if (req.body.dayIndex != null) {
        let dayIndex;
        try {
            dayIndex = parseValidateFutureDayIndex(req);
        } catch (e: any) {
            return res.status(400).json({ error: e.message });
        }
        date = getDateForWeekIndex(dayIndex);
    }
    try {
        const data = await removeChoices(login, trusted, req.body.locationIndex, date);
        getWebsocket().emit("message", await addVolatileData(data));
        res.status(200).json(data);
    } catch (e: any) { next(e) }
});

router.post("/removeChoice", async (req, res, next) => {
    const login = getLogin(parseToken(req));
    const trusted = getTrusted(parseToken(req));
    let date = undefined;
    if (req.body.dayIndex != null) {
        let dayIndex;
        try {
            dayIndex = parseValidateFutureDayIndex(req);
        } catch (e: any) {
            return res.status(400).json({ error: e.message });
        }
        date = getDateForWeekIndex(dayIndex);
    }
    try {
        const data = await removeChoice(login, trusted, req.body.locationIndex, req.body.foodIndex, date);
        getWebsocket().emit("message", await addVolatileData(data));
        res.status(200).json(data);
    } catch (e: any) { next(e) }
});

router.post("/updateNote", async (req, res, next) => {
    const login = getLogin(parseToken(req));
    const trusted = getTrusted(parseToken(req));
    const note = req.body.note;
    try {
        if (note && note.length > 70) {
            throw Error("Poznámka může mít maximálně 70 znaků");
        }
        let date = undefined;
        if (req.body.dayIndex != null) {
            let dayIndex;
            try {
                dayIndex = parseValidateFutureDayIndex(req);
            } catch (e: any) {
                return res.status(400).json({ error: e.message });
            }
            date = getDateForWeekIndex(dayIndex);
        }
        const data = await updateNote(login, trusted, note, date);
        getWebsocket().emit("message", await addVolatileData(data));
        res.status(200).json(data);
    } catch (e: any) { next(e) }
});

router.post("/changeDepartureTime", async (req, res, next) => {
    const login = getLogin(parseToken(req));
    let date = undefined;
    if (req.body.dayIndex != null) {
        let dayIndex;
        try {
            dayIndex = parseValidateFutureDayIndex(req);
        } catch (e: any) {
            return res.status(400).json({ error: e.message });
        }
        date = getDateForWeekIndex(dayIndex);
    }
    try {
        const data = await updateDepartureTime(login, req.body?.time, date);
        getWebsocket().emit("message", await addVolatileData(data));
        res.status(200).json(data);
    } catch (e: any) { next(e) }
});

router.post("/jdemeObed", async (req, res, next) => {
    const login = getLogin(parseToken(req));
    try {
        await callNotifikace({ input: { user: login, udalost: UdalostEnum.JDEME_OBED }, gotify: false })
        res.status(200).json({});
    } catch (e: any) { next(e) }
});

export default router;