import {
    admin,
    customSession,
    multiSession,
    username,
} from "better-auth/plugins";
import { drizzleAdapter } from "better-auth/adapters/drizzle";
import { UserRoleMap } from "@domains/user/data";
import { getRedisInstance } from "@pkg/keystore";
import { settings } from "@core/settings";
import { betterAuth } from "better-auth";
import { logger } from "@pkg/logger";
import { db, schema } from "@pkg/db";

const COOKIE_CACHE_MAX_AGE = 60 * 5;
const USERNAME_REGEX = /^[a-zA-Z0-9_]+$/;

export const auth = betterAuth({
    trustedOrigins: ["http://localhost:5173", settings.betterAuthUrl],
    advanced: { useSecureCookies: settings.nodeEnv === "production" },
    appName: settings.appName,
    emailAndPassword: {
        enabled: true,
        disableSignUp: true,
        requireEmailVerification: false,
    },
    plugins: [
        customSession(async ({ user, session }) => {
            session.id = session.token;
            return { user, session };
        }),
        username({
            minUsernameLength: 5,
            maxUsernameLength: 20,
            usernameValidator: async (username) => {
                return USERNAME_REGEX.test(username);
            },
        }),
        admin({
            defaultRole: UserRoleMap.admin,
            defaultBanReason:
                "Stop fanum taxing the server bub, losing aura points fr",
            defaultBanExpiresIn: 60 * 60 * 24,
        }),
        multiSession({ maximumSessions: 5 }),
    ],
    logger: {
        log: (level, message, metadata) => {
            logger.log(level, message, metadata);
        },
        level: "debug",
    },
    database: drizzleAdapter(db, { provider: "pg", schema: { ...schema } }),
    secondaryStorage: {
        get: async (key) => {
            const redis = getRedisInstance();
            return await redis.get(key);
        },
        set: async (key, value, ttl) => {
            const redis = getRedisInstance();
            if (ttl) {
                await redis.setex(key, ttl, value);
            } else {
                await redis.set(key, value);
            }
        },
        delete: async (key) => {
            const redis = getRedisInstance();
            const out = await redis.del(key);
            if (!out && out !== 0) {
                return null;
            }
            return out.toString() as any;
        },
    },
    session: {
        modelName: "session",
        expiresIn: 60 * 60 * 24 * 7,
        updateAge: 60 * 60 * 24,
        cookieCache: {
            enabled: true,
            maxAge: COOKIE_CACHE_MAX_AGE,
        },
    },
    user: {
        modelName: "user",
        additionalFields: {
            onboardingDone: {
                type: "boolean",
                defaultValue: false,
                required: false,
            },
            last2FAVerifiedAt: { type: "date", required: false },
            parentId: { required: false, type: "string" },
        },
    },
});

// - - -
