const express = require("express");
const sharp = require("sharp");

const upload =
    require("../middleware/upload");

const stego =
    require("../stego/engine");

const router =
    express.Router();


router.get(
    "/health",
    (req, res) => {
        res.json({
            status: "ok"
        });
    }
);


router.post(
    "/encode",
    upload.fields([
        {
            name: "image",
            maxCount: 1
        },
        {
            name: "file",
            maxCount: 1
        }
    ]),
    async (req, res) => {

        try {

            const imageFile =
                req.files?.image?.[0];

            const secretFile =
                req.files?.file?.[0];

            if (!imageFile) {
                return res.status(400).json({
                    error: "Image is required"
                });
            }

            const {
                message,
                password
            } = req.body;


            if (
                !message &&
                !secretFile
            ) {
                return res.status(400).json({
                    error:
                        "Message or file is required"
                });
            }


            const image =
                await sharp(
                    imageFile.buffer
                )
                    .ensureAlpha()
                    .raw()
                    .toBuffer({
                        resolveWithObject: true
                    });


            const result =
                await stego.encode({
                    pixels:
                        image.data,

                    width:
                        image.info.width,

                    height:
                        image.info.height,

                    message,

                    password:
                        password || undefined,

                    file:
                        secretFile
                });


            const output =
                await sharp(
                    result.pixels,
                    {
                        raw: {
                            width:
                                image.info.width,

                            height:
                                image.info.height,

                            channels: 4
                        }
                    }
                )
                    .png()
                    .toBuffer();


            res.type("png");

            res.send(output);

        } catch (error) {

            console.error(error);

            res.status(400).json({
                error:
                    error.message
            });
        }
    }
);


router.post(
    "/decode",
    upload.single("image"),
    async (req, res) => {

        try {

            if (!req.file) {
                return res.status(400).json({
                    error:
                        "Image is required"
                });
            }


            const image =
                await sharp(
                    req.file.buffer
                )
                    .ensureAlpha()
                    .raw()
                    .toBuffer({
                        resolveWithObject: true
                    });


            const result =
                await stego.decode({
                    pixels:
                        image.data,

                    password:
                        req.body.password ||
                        undefined
                });


            if (
                result.type === "file"
            ) {

                res.setHeader(
                    "Content-Type",
                    result.mimetype
                );

                res.setHeader(
                    "Content-Disposition",
                    `attachment; filename="${result.filename}"`
                );

                return res.send(
                    result.file
                );
            }


            return res.json({
                type: "message",
                message:
                    result.message
            });

        } catch (error) {

            console.error(error);

            res.status(400).json({
                error:
                    error.message
            });
        }
    }
);


router.post(
    "/info",
    upload.single("image"),
    async (req, res) => {

        try {

            if (!req.file) {
                return res.status(400).json({
                    error:
                        "Image is required"
                });
            }


            const image =
                await sharp(
                    req.file.buffer
                )
                    .ensureAlpha()
                    .metadata();


            const capacity =
                stego.getCapacity(
                    image.width,
                    image.height
                );


            res.json({
                format:
                    image.format,

                width:
                    image.width,

                height:
                    image.height,

                channels:
                    4,

                capacityBytes:
                    capacity,

                capacityKB:
                    Math.round(
                        capacity /
                        1024 *
                        100
                    ) / 100
            });

        } catch (error) {

            console.error(error);

            res.status(400).json({
                error:
                    error.message
            });
        }
    }
);


module.exports = router;