import express, { Request } from "express";
import { getLogin } from "../auth";
import { parseToken } from "../utils";
import { getWebsocket } from "../websocket";
import { createGroup, deleteGroup, addGroupMember, removeGroupMember, updateGroupMember, setGroupState, updateGroupTimes, updateGroupFees } from "../groups";
import { GroupState } from "../../../types/gen/types.gen";

const router = express.Router();

function broadcastExtra(data: any) {
    getWebsocket().emit("message", data);
}

router.post("/create", async (req: Request, res, next) => {
    const login = getLogin(parseToken(req));
    const { name } = req.body ?? {};
    if (!name || typeof name !== 'string') {
        return res.status(400).json({ error: 'Nebyl předán název skupiny' });
    }
    try {
        const data = await createGroup(login, name);
        broadcastExtra(data);
        res.status(200).json(data);
    } catch (e: any) { next(e); }
});

router.post("/delete", async (req: Request, res, next) => {
    const login = getLogin(parseToken(req));
    const { id } = req.body ?? {};
    if (!id) return res.status(400).json({ error: 'Nebylo předáno ID skupiny' });
    try {
        const data = await deleteGroup(login, id);
        broadcastExtra(data);
        res.status(200).json(data);
    } catch (e: any) { next(e); }
});

router.post("/addMember", async (req: Request, res, next) => {
    const login = getLogin(parseToken(req));
    const { id, login: targetLogin } = req.body ?? {};
    if (!id) return res.status(400).json({ error: 'Nebylo předáno ID skupiny' });
    if (targetLogin !== undefined && (typeof targetLogin !== 'string' || targetLogin.trim() === '')) {
        return res.status(400).json({ error: 'Neplatný login uživatele' });
    }
    const target = targetLogin ?? login;
    try {
        const data = await addGroupMember(login, id, target);
        broadcastExtra(data);
        res.status(200).json(data);
    } catch (e: any) { next(e); }
});

router.post("/removeMember", async (req: Request, res, next) => {
    const login = getLogin(parseToken(req));
    const { id, login: targetLogin } = req.body ?? {};
    if (!id) return res.status(400).json({ error: 'Nebylo předáno ID skupiny' });
    if (!targetLogin) return res.status(400).json({ error: 'Nebyl předán login uživatele' });
    try {
        const data = await removeGroupMember(login, id, targetLogin);
        broadcastExtra(data);
        res.status(200).json(data);
    } catch (e: any) { next(e); }
});

router.post("/updateMember", async (req: Request, res, next) => {
    const login = getLogin(parseToken(req));
    const { id, login: targetLogin, amount, note, surchargeText, surchargeAmount } = req.body ?? {};
    if (!id) return res.status(400).json({ error: 'Nebylo předáno ID skupiny' });
    if (!targetLogin) return res.status(400).json({ error: 'Nebyl předán login uživatele' });
    const patch: Record<string, any> = {};
    if (amount !== undefined) {
        if (typeof amount !== 'number' || !Number.isFinite(amount) || amount < 0) {
            return res.status(400).json({ error: 'Neplatná částka' });
        }
        patch.amount = amount;
    }
    if (note !== undefined) {
        if (typeof note !== 'string') return res.status(400).json({ error: 'Neplatná poznámka' });
        patch.note = note;
    }
    if (surchargeText !== undefined) {
        if (typeof surchargeText !== 'string') return res.status(400).json({ error: 'Neplatný text příplatku' });
        patch.surchargeText = surchargeText;
    }
    if (surchargeAmount !== undefined) {
        if (typeof surchargeAmount !== 'number' || !Number.isFinite(surchargeAmount) || surchargeAmount < 0) {
            return res.status(400).json({ error: 'Neplatná výše příplatku' });
        }
        patch.surchargeAmount = surchargeAmount;
    }
    try {
        const data = await updateGroupMember(login, id, targetLogin, patch);
        broadcastExtra(data);
        res.status(200).json(data);
    } catch (e: any) { next(e); }
});

router.post("/setState", async (req: Request, res, next) => {
    const login = getLogin(parseToken(req));
    const { id, state } = req.body ?? {};
    if (!id) return res.status(400).json({ error: 'Nebylo předáno ID skupiny' });
    if (!state || !Object.values(GroupState).includes(state)) {
        return res.status(400).json({ error: 'Neplatný stav skupiny' });
    }
    try {
        const data = await setGroupState(login, id, state as GroupState);
        broadcastExtra(data);
        res.status(200).json(data);
    } catch (e: any) { next(e); }
});

router.post("/updateFees", async (req: Request, res, next) => {
    const login = getLogin(parseToken(req));
    const { id, fees, shipping, tip, discountType, discountValue } = req.body ?? {};
    if (!id) return res.status(400).json({ error: 'Nebylo předáno ID skupiny' });
    if (fees !== undefined && (typeof fees !== 'number' || !Number.isFinite(fees) || fees < 0)) {
        return res.status(400).json({ error: 'Neplatná výše poplatků' });
    }
    if (shipping !== undefined && (typeof shipping !== 'number' || !Number.isFinite(shipping) || shipping < 0)) {
        return res.status(400).json({ error: 'Neplatná výše dopravy' });
    }
    if (tip !== undefined && (typeof tip !== 'number' || !Number.isFinite(tip) || tip < 0)) {
        return res.status(400).json({ error: 'Neplatná výše spropitného' });
    }
    if (discountType !== undefined && discountType !== '' && !['percent', 'fixed'].includes(discountType)) {
        return res.status(400).json({ error: 'Neplatný typ slevy' });
    }
    if (discountValue !== undefined && (typeof discountValue !== 'number' || !Number.isFinite(discountValue) || discountValue < 0)) {
        return res.status(400).json({ error: 'Neplatná výše slevy' });
    }
    try {
        const data = await updateGroupFees(login, id, fees, shipping, tip, discountType, discountValue);
        broadcastExtra(data);
        res.status(200).json(data);
    } catch (e: any) { next(e); }
});

router.post("/updateTimes", async (req: Request, res, next) => {
    const login = getLogin(parseToken(req));
    const { id, orderedAt, deliveryAt } = req.body ?? {};
    if (!id) return res.status(400).json({ error: 'Nebylo předáno ID skupiny' });
    const timeRegex = /^([01]\d|2[0-3]):[0-5]\d$/;
    if (orderedAt !== undefined && orderedAt !== '' && !timeRegex.test(orderedAt)) {
        return res.status(400).json({ error: 'Neplatný formát času objednání (očekáváno HH:MM)' });
    }
    if (deliveryAt !== undefined && deliveryAt !== '' && !timeRegex.test(deliveryAt)) {
        return res.status(400).json({ error: 'Neplatný formát času doručení (očekáváno HH:MM)' });
    }
    try {
        const data = await updateGroupTimes(login, id, orderedAt, deliveryAt);
        broadcastExtra(data);
        res.status(200).json(data);
    } catch (e: any) { next(e); }
});

export default router;
