import { FlowExecCtx } from "@/core/flow.execution.context";
import { traceResultAsync } from "@core/observability";
import { AccountRepository } from "./account.repository";
import { UserRepository } from "./repository";
import { db } from "@pkg/db";

export class UserController {
    constructor(
        private userRepository: UserRepository,
        private accountRepo: AccountRepository,
    ) {}

    getUserInfo(fctx: FlowExecCtx, userId: string) {
        return traceResultAsync({
            name: "logic.user.controller.getUserInfo",
            fctx,
            attributes: { "app.user.id": userId },
            fn: () => this.userRepository.getUserInfo(fctx, userId),
        });
    }

    ensureAccountExists(fctx: FlowExecCtx, userId: string) {
        return traceResultAsync({
            name: "logic.user.controller.ensureAccountExists",
            fctx,
            attributes: { "app.user.id": userId },
            fn: () => this.accountRepo.ensureAccountExists(fctx, userId),
        });
    }

    isUsernameAvailable(fctx: FlowExecCtx, username: string) {
        return traceResultAsync({
            name: "logic.user.controller.isUsernameAvailable",
            fctx,
            attributes: { "app.user.username": username },
            fn: () => this.userRepository.isUsernameAvailable(fctx, username),
        });
    }

    updateLastVerified2FaAtToNow(fctx: FlowExecCtx, userId: string) {
        return traceResultAsync({
            name: "logic.user.controller.updateLastVerified2FaAtToNow",
            fctx,
            attributes: { "app.user.id": userId },
            fn: () => this.userRepository.updateLastVerified2FaAtToNow(fctx, userId),
        });
    }

    banUser(
        fctx: FlowExecCtx,
        userId: string,
        reason: string,
        banExpiresAt: Date,
    ) {
        return traceResultAsync({
            name: "logic.user.controller.banUser",
            fctx,
            attributes: { "app.user.id": userId },
            fn: () => this.userRepository.banUser(fctx, userId, reason, banExpiresAt),
        });
    }

    isUserBanned(fctx: FlowExecCtx, userId: string) {
        return traceResultAsync({
            name: "logic.user.controller.isUserBanned",
            fctx,
            attributes: { "app.user.id": userId },
            fn: () => this.userRepository.isUserBanned(fctx, userId),
        });
    }

    getBanInfo(fctx: FlowExecCtx, userId: string) {
        return traceResultAsync({
            name: "logic.user.controller.getBanInfo",
            fctx,
            attributes: { "app.user.id": userId },
            fn: () => this.userRepository.getBanInfo(fctx, userId),
        });
    }

    rotatePassword(fctx: FlowExecCtx, userId: string, password: string) {
        return traceResultAsync({
            name: "logic.user.controller.rotatePassword",
            fctx,
            attributes: { "app.user.id": userId },
            fn: () => this.accountRepo.rotatePassword(fctx, userId, password),
        });
    }
}

export function getUserController(): UserController {
    return new UserController(
        new UserRepository(db),
        new AccountRepository(db),
    );
}
