import "@/server/sentry.server.config";
import * as Sentry from "@sentry/bun";
import { Elysia } from "elysia";

import { swagger } from "@elysiajs/swagger";
import { apiRoutes } from "@/routes/api";
import { healthRoutes } from "@/routes/health";
import { baseLogger } from "@/utils/logger";
import { env } from "@/env";
import serverTiming from "@elysiajs/server-timing";
import { AuthenticationError } from "@/errors/AuthenticationError";
import { ModelValidationError } from "@/errors/ModelValidationError";

import { setupShutdown } from "@/shutdown";

setupShutdown();

const app = new Elysia()
    .use(serverTiming())
    .error("AUTHENTICATION_ERROR", AuthenticationError)
    .error("MODEL_VALIDATION_ERROR", ModelValidationError)

    .onError(({ code, error, set }) => {
        switch (code) {
            case "MODEL_VALIDATION_ERROR":
                set.status = 400;
                return getErrorReturn(error);
            case "AUTHENTICATION_ERROR":
                set.status = 401;
                return getErrorReturn(error);
            case "NOT_FOUND":
                set.status = 404;
                return getErrorReturn(error);
            case "INTERNAL_SERVER_ERROR":
                set.status = 500;
                baseLogger.error("Internal server error", error);
                Sentry.captureException(error);
                return getErrorReturn(error);
        }
    });

if (env.IS_DEV) {
    app.use(
        swagger({
            documentation: {
                info: {
                    title: "Redis API",
                    version: "1.0.0",
                },
            },
        })
    );
}

app.use(apiRoutes);
app.use(healthRoutes);

app.listen(env.PORT, (server) => {
    baseLogger.info(`🦊 REDISAPI@${env.VERSION} running on ${server.url}`);
});

function getErrorReturn(error: Error) {
    return {
        status: "error",
        message: error.toString(),
    };
}
