import { Middleware } from "@lib/router.ts";
import admin from "@lib/admin.ts";
import {
    queryExecutionError,
    tooManyRequestsError,
    unauthorizedError,
} from "@src/lib/errors.ts";
import { err, ok } from "@shared/utils/result.ts";
import { eta } from "../../main.ts";

const EXCLUDE = new Set(["/login", "/setup", "/version"]);

const authMiddleware: Middleware = async (c, next) => {
    const token = c.cookies.get("token");
    const isValid = token
        .map((token) => admin.sessions.verifyToken(token)).match(
            (r) => r,
            () => ok(false),
        );

    if (isValid.isErr()) {
        return c.matchPreferredType(
            () => c.html(eta.render("./internal_error.html", {})),
            () =>
                c.json(
                    err(queryExecutionError("Server failed to execute query")),
                ),
            () => new Response("500 Internal server error", { status: 500 }),
        );
    }

    const path = c.path;

    if (
        !isValid.value && !path.startsWith("/public") && !EXCLUDE.has(path)
    ) {
        if (!isValid.value) {
            c.cookies.delete("token");
        }

        if (c.preferredType.isNone()) {
            return new Response("401 unautorized", { status: 401 });
        }

        switch (c.preferredType.value) {
            case "json":
                return c.json(
                    err(unauthorizedError("Unauthorized")),
                    { status: 401 },
                );
            case "html":
                return c.redirect("/login");
        }
    }
    await next();
};

export default authMiddleware;
