// Express routing
const express = require('express');
const router = express.Router();
// Database connection
const db = require('../db');
// Param validation and transformation functions
const paramValidation = require('../param_validation');
const paramTransformation = require('../param_transformation');
// Error handling functions
const errorHandling = require('../error_handling');
const { DatabaseError } = require('pg');

/* GET Read Notifications */
router.get('/read_notifications', async function (req, res, next) {
    const user_id = req.query.user_id;
    if (user_id) {
        let validation_tuple = await paramValidation.validate_user_id(
            user_id,
            paramValidation.ParamType.QUERY
        );
        if (!validation_tuple.is_valid) {
            return res
                .status(404)
                .json(
                    errorHandling.return_error_404(validation_tuple.error_msg)
                );
        }
    }

    const query = db.prepare_select_statement('read_notifications', req.query);

    // Retrieve rows from database
    try {
        const result = await db.query(query, Object.values(req.query));
        return res.status(200).json(result.rows);
    } catch (error) {
        return res
            .status(500)
            .json(errorHandling.return_error_500(error.message));
    }
});

/* CREATE Read Notification */
router.post('/read_notifications', async function (req, res, next) {
    // Create dict to store SQL "INSERT INTO"/"VALUES" params
    let params = {};
    // Retrieve request body properties
    const notification_id = req.body.notification_id || null;
    const user_id = req.body.user_id || null;

    let validation_tuple;
    validation_tuple = await paramValidation.validate_notification_id(
        notification_id,
        paramValidation.ParamType.BODY
    );
    if (!validation_tuple.is_valid) {
        return res
            .status(404)
            .json(errorHandling.return_error_404(validation_tuple.error_msg));
    }
    params.notification_id = notification_id;

    validation_tuple = await paramValidation.validate_user_id(
        user_id,
        paramValidation.ParamType.BODY
    );
    if (!validation_tuple.is_valid) {
        return res
            .status(404)
            .json(errorHandling.return_error_404(validation_tuple.error_msg));
    }
    params.user_id = user_id;

    // Assemble SQL query based on provided query params
    const query = db.prepare_insert_statement('read_notifications', params);
    // Attempt to write row to database
    try {
        const result = await db.query(query, Object.values(params));
        // Make sure row was created
        if (!result.rowCount) {
            throw new DatabaseError(
                'Database insertion failed: no rows affected.'
            );
        }

        return res.status(201).json(result.rows[0]);
    } catch (error) {
        return res
            .status(500)
            .json(errorHandling.return_error_500(error.message));
    }
});

/* GET Read Notification by ID */
router.get(
    '/read_notifications/:read_notification_id',
    async function (req, res, next) {
        const read_notification_id = req.params.read_notification_id;
        if (read_notification_id) {
            let validation_tuple =
                await paramValidation.validate_read_notification_id(
                    read_notification_id,
                    paramValidation.ParamType.PATH
                );
            if (!validation_tuple.is_valid) {
                return res
                    .status(404)
                    .json(
                        errorHandling.return_error_404(
                            validation_tuple.error_msg
                        )
                    );
            }
        }
        // Retrieve row from database
        try {
            const result = await db.query(
                'SELECT * FROM read_notifications WHERE read_notification_id = $1',
                [read_notification_id]
            );
            return res.status(200).json(result.rows[0]);
        } catch (error) {
            return res
                .status(500)
                .json(errorHandling.return_error_500(error.message));
        }
    }
);

/* DELETE Notification by ID */
router.delete(
    '/read_notifications/:read_notification_id',
    async function (req, res, next) {
        // Validate path param
        const read_notification_id = req.params.read_notification_id;
        if (read_notification_id) {
            let validation_tuple =
                await paramValidation.validate_read_notification_id(
                    read_notification_id,
                    paramValidation.ParamType.PATH
                );
            if (!validation_tuple.is_valid) {
                return res
                    .status(404)
                    .json(
                        errorHandling.return_error_404(
                            validation_tuple.error_msg
                        )
                    );
            }
        }

        // Delete row from database
        try {
            const result = await db.query(
                'DELETE FROM read_notifications WHERE read_notification_id = $1',
                [read_notification_id]
            );

            if (result.rowCount === 1) {
                return res.status(204).send();
            } else {
                throw new DatabaseError(
                    'Database delete failed: no rows affected.'
                );
            }
        } catch (error) {
            return res
                .status(500)
                .json(errorHandling.return_error_500(error.message));
        }
    }
);

module.exports = router;
