import Router, {NextFunction, Response} from 'express';
import {AuthenticatedRequest, hasRank} from "../middlewares/authenticate";
import {Rank} from "../../models/User";
import Multer from "multer";
import path from "path";
import {bucket} from "../../controller/bucket";
import {createMedia, deleteMedia, getMediaById, getMediaObject} from "../../controller/media";

const app = Router();

const multer = Multer({
    storage: Multer.memoryStorage(),
    limits: {fileSize: 100 * 1024 * 1024},
});

const fileSizeErrorHandler = (err: Error, req: AuthenticatedRequest, res: Response, next: NextFunction) => {
    if (err) return res.status(413).json({message: "The provided file is too big"});
    next();
}

app.get("/:id", hasRank(Rank.TEAM_MEMBER), async (req: AuthenticatedRequest, res: Response) => {
    const media = await getMediaById(req.params.id);
    if (!media) return res.status(404).json({message: "The provided asset could not be found"});

    if (!(req.user.rank === Rank.TEAM_MEMBER && media.clientId === req.user.clientId || req.user.rank === Rank.ADMIN))
        return res.status(401).json({message: "You don't have the permission to show information about this media"});

    res.json(media);
});

app.post("/upload", hasRank(Rank.TEAM_MEMBER), multer.any(), fileSizeErrorHandler, async (req: AuthenticatedRequest, res: Response) => {
    if (!req.files) return res.status(400).json({message: "No file uploaded"});
    const files = req.files as Express.Multer.File[]

    const media = await createMedia(req.user.clientId, files[0].originalname, path.extname(files[0].originalname).substring(1));

    const blobStream = bucket.file(media.assetId!).createWriteStream();

    blobStream.on('error', async () => {
        await media.destroy();
        res.status(500).json({message: "An internal error occurred"});
    });

    blobStream.on('finish', () => res.json({
        message: "Successfully uploaded the provided asset",
        assetId: media.assetId
    }));

    blobStream.end(files[0].buffer);
});

app.delete("/:id", hasRank(Rank.TEAM_MEMBER), async (req: AuthenticatedRequest, res: Response) => {
    const media = await getMediaObject(req.params.id);
    if (!media) return res.status(404).json({message: "The provided asset could not be found"});

    if (!(req.user.rank === Rank.TEAM_MEMBER && media.clientId === req.user.clientId || req.user.rank === Rank.ADMIN))
        return res.status(401).json({message: "You don't have the permission to delete this media"});

    await deleteMedia(req.params.id);
    res.json({message: "The provided media got successfully deleted"});
});

module.exports = app;