import {
    banUserSchema,
    checkUsernameSchema,
    ensureAccountExistsSchema,
    rotatePasswordSchema,
} from "@pkg/logic/domains/user/data";
import {
    getFlowExecCtxForRemoteFuncs,
    unauthorized,
} from "$lib/core/server.utils";
import { getUserController } from "@pkg/logic/domains/user/controller";
import { command, getRequestEvent, query } from "$app/server";
import * as v from "valibot";

const uc = getUserController();

export const getMyInfoSQ = query(async () => {
    const event = getRequestEvent();
    const fctx = await getFlowExecCtxForRemoteFuncs(event.locals);

    if (!fctx.userId) {
        return unauthorized(fctx);
    }

    const res = await uc.getUserInfo(fctx, fctx.userId);
    return res.isOk()
        ? { data: res.value, error: null }
        : { data: null, error: res.error };
});

export const getUserInfoByIdSQ = query(
    v.object({ userId: v.string() }),
    async (input) => {
        const event = getRequestEvent();
        const fctx = await getFlowExecCtxForRemoteFuncs(event.locals);

        if (!fctx.userId) {
            return unauthorized(fctx);
        }

        const res = await uc.getUserInfo(fctx, input.userId);
        return res.isOk()
            ? { data: res.value, error: null }
            : { data: null, error: res.error };
    },
);

export const ensureAccountExistsSC = command(
    ensureAccountExistsSchema,
    async (payload) => {
        const event = getRequestEvent();
        const fctx = await getFlowExecCtxForRemoteFuncs(event.locals);

        if (!fctx.userId) {
            return unauthorized(fctx);
        }

        const res = await uc.ensureAccountExists(fctx, payload.userId);
        return res.isOk()
            ? { data: res.value, error: null }
            : { data: null, error: res.error };
    },
);

export const checkUsernameSC = command(checkUsernameSchema, async (payload) => {
    const event = getRequestEvent();
    const fctx = await getFlowExecCtxForRemoteFuncs(event.locals);

    if (!fctx.userId) {
        return unauthorized(fctx);
    }

    const res = await uc.isUsernameAvailable(fctx, payload.username);
    return res.isOk()
        ? { data: res.value, error: null }
        : { data: null, error: res.error };
});

export const update2faVerifiedSC = command(
    v.object({ userId: v.string() }),
    async (payload) => {
        const event = getRequestEvent();
        const fctx = await getFlowExecCtxForRemoteFuncs(event.locals);

        if (!fctx.userId) {
            return unauthorized(fctx);
        }

        const res = await uc.updateLastVerified2FaAtToNow(fctx, payload.userId);
        return res.isOk()
            ? { data: res.value, error: null }
            : { data: null, error: res.error };
    },
);

export const banUserSC = command(banUserSchema, async (payload) => {
    const event = getRequestEvent();
    const fctx = await getFlowExecCtxForRemoteFuncs(event.locals);

    if (!fctx.userId) {
        return unauthorized(fctx);
    }

    const res = await uc.banUser(
        fctx,
        payload.userId,
        payload.reason,
        payload.banExpiresAt,
    );
    return res.isOk()
        ? { data: res.value, error: null }
        : { data: null, error: res.error };
});

export const isUserBannedSQ = query(
    v.object({ userId: v.string() }),
    async (input) => {
        const event = getRequestEvent();
        const fctx = await getFlowExecCtxForRemoteFuncs(event.locals);

        if (!fctx.userId) {
            return unauthorized(fctx);
        }

        const res = await uc.isUserBanned(fctx, input.userId);
        return res.isOk()
            ? { data: res.value, error: null }
            : { data: null, error: res.error };
    },
);

export const getBanInfoSQ = query(
    v.object({ userId: v.string() }),
    async (input) => {
        const event = getRequestEvent();
        const fctx = await getFlowExecCtxForRemoteFuncs(event.locals);

        if (!fctx.userId) {
            return unauthorized(fctx);
        }

        const res = await uc.getBanInfo(fctx, input.userId);
        return res.isOk()
            ? { data: res.value, error: null }
            : { data: null, error: res.error };
    },
);

export const rotatePasswordSC = command(
    rotatePasswordSchema,
    async (payload) => {
        const event = getRequestEvent();
        const fctx = await getFlowExecCtxForRemoteFuncs(event.locals);

        if (!fctx.userId) {
            return unauthorized(fctx);
        }

        const res = await uc.rotatePassword(
            fctx,
            payload.userId,
            payload.password,
        );
        return res.isOk()
            ? { data: res.value, error: null }
            : { data: null, error: res.error };
    },
);
