import { Router } from "express";

import * as configFunctions from "../helpers/functions.config.js";

import * as authenticationFunctions from "../helpers/functions.authentication.js";

import { useTestDatabases } from "../data/databasePaths.js";

import { getApiKey } from "../helpers/functions.api.js";

import type * as recordTypes from "../types/recordTypes";

export const router = Router();

const safeRedirects = new Set([
    "/admin/fees",
    "/admin/occupancytypes",
    "/admin/tables",
    "/lotoccupancies",
    "/lotoccupancies/new",
    "/lots",
    "/lots/new",
    "/maps",
    "/maps/new",
    "/workorders",
    "/workorders/new",
    "/reports"
]);

const getSafeRedirectURL = (possibleRedirectURL = "") => {
    const urlPrefix = configFunctions.getProperty("reverseProxy.urlPrefix");

    if (typeof possibleRedirectURL === "string") {
        const urlToCheck = (
            possibleRedirectURL.startsWith(urlPrefix)
                ? possibleRedirectURL.slice(urlPrefix.length)
                : possibleRedirectURL
        ).toLowerCase();

        if (
            safeRedirects.has(urlToCheck) ||
            /^(\/maps\/)\d+(\/edit)?$/.test(urlToCheck) ||
            /^(\/lots\/)\d+(\/edit)?$/.test(urlToCheck) ||
            /^(\/lotoccupancies\/)\d+(\/edit)?$/.test(urlToCheck) ||
            /^(\/workorders\/)\d+(\/edit)?$/.test(urlToCheck)
        ) {
            return urlPrefix + urlToCheck;
        }
    }

    return urlPrefix + "/dashboard";
};

router
    .route("/")
    .get((request, response) => {
        const sessionCookieName =
            configFunctions.getProperty("session.cookieName");

        if (request.session.user && request.cookies[sessionCookieName]) {
            const redirectURL = getSafeRedirectURL(
                (request.query.redirect || "") as string
            );

            response.redirect(redirectURL);
        } else {
            response.render("login", {
                userName: "",
                message: "",
                redirect: request.query.redirect,
                useTestDatabases
            });
        }
    })
    .post(async (request, response) => {
        const userName = request.body.userName as string;
        const passwordPlain = request.body.password as string;

        const unsafeRedirectURL = request.body.redirect;

        const redirectURL = getSafeRedirectURL(
            typeof unsafeRedirectURL === "string" ? unsafeRedirectURL : ""
        );

        const isAuthenticated = await authenticationFunctions.authenticate(
            userName,
            passwordPlain
        );
        let userObject: recordTypes.User;

        if (isAuthenticated) {
            const userNameLowerCase = userName.toLowerCase();

            const canLogin = configFunctions
                .getProperty("users.canLogin")
                .some((currentUserName) => {
                    return userNameLowerCase === currentUserName.toLowerCase();
                });

            if (canLogin) {
                const canUpdate = configFunctions
                    .getProperty("users.canUpdate")
                    .some((currentUserName) => {
                        return (
                            userNameLowerCase === currentUserName.toLowerCase()
                        );
                    });

                const isAdmin = configFunctions
                    .getProperty("users.isAdmin")
                    .some((currentUserName) => {
                        return (
                            userNameLowerCase === currentUserName.toLowerCase()
                        );
                    });

                const apiKey = await getApiKey(userNameLowerCase);

                userObject = {
                    userName: userNameLowerCase,
                    userProperties: {
                        canUpdate,
                        isAdmin,
                        apiKey
                    }
                };
            }
        }

        if (isAuthenticated && userObject) {
            request.session.user = userObject;

            response.redirect(redirectURL);
        } else {
            response.render("login", {
                userName,
                message: "Login Failed",
                redirect: redirectURL,
                useTestDatabases
            });
        }
    });

export default router;
