import { AuthContext, MiddlewareContext, MiddlewareOptions } from "better-auth";
import { AccountRepository } from "../user/account.repository";
import { FlowExecCtx } from "@/core/flow.execution.context";
import { ResultAsync } from "neverthrow";
import { authErrors } from "./errors";
import { logger } from "@pkg/logger";
import { nanoid } from "nanoid";
import { db } from "@pkg/db";

export class AuthController {
    constructor(private accountRepo: AccountRepository) {}

    swapAccountPasswordForTwoFactor(
        fctx: FlowExecCtx,
        ctx: MiddlewareContext<
            MiddlewareOptions,
            AuthContext & { returned?: unknown; responseHeaders?: Headers }
        >,
    ) {
        logger.info("Swapping account password for 2FA", {
            ...fctx,
        });

        if (!ctx.path.includes("two-factor")) {
            return ResultAsync.fromSafePromise(Promise.resolve(ctx));
        }

        if (!ctx.body.password || ctx.body.password.length === 0) {
            return ResultAsync.fromSafePromise(Promise.resolve(ctx));
        }

        logger.info("Rotating password for 2FA setup for user", {
            ...fctx,
            userId: ctx.body.userId,
        });

        return this.accountRepo
            .rotatePassword(fctx, ctx.body.userId, nanoid())
            .mapErr((err) => {
                logger.error("Failed to rotate password for 2FA", {
                    ...fctx,
                    error: err,
                });
                return authErrors.passwordRotationFailed(fctx, err.detail);
            })
            .map((newPassword) => {
                logger.info("Password rotated successfully for 2FA setup", {
                    ...fctx,
                });
                return {
                    ...ctx,
                    body: { ...ctx.body, password: newPassword },
                };
            });
    }
}

export function getAuthController(): AuthController {
    return new AuthController(new AccountRepository(db));
}
