import { createResolver, t } from "@tailor-platform/sdk";
import { createContext } from "@tailor-platform/erp-kit/app";
import { getDB } from "@/generated/kysely-tailordb";
import { umModules, auditModules } from "@/modules";

export default createResolver({
  name: "assignRoleToUser",
  operation: "mutation",
  input: {
    userId: t.string().description("User ID"),
    roleId: t.string().description("Role ID to assign"),
  },
  body: async (context) => {
    const db = getDB("main-db");
    const result = await db.transaction().execute(async (trx) => {
      const cmdResult = await umModules.commands.assignRoleToUser(
        trx,
        {
          userId: context.input.userId,
          roleId: context.input.roleId,
        },
        createContext(context),
      );
      if (!cmdResult.ok) {
        switch (cmdResult.error.code) {
          case "USER_MANAGEMENT_USER_NOT_FOUND":
            throw new Error(`User ${context.input.userId} does not exist`);
          case "USER_MANAGEMENT_ROLE_NOT_FOUND":
            throw new Error(`Role ${context.input.roleId} does not exist`);
          case "USER_MANAGEMENT_USER_NOT_ACTIVE":
            throw new Error("User is not in ACTIVE status");
          case "INSUFFICIENT_PERMISSION":
            throw cmdResult.error;
        }
      }
      return {
        userId: cmdResult.value.user.id,
        roleId: context.input.roleId,
      };
    });

    await db
      .transaction()
      .execute(async (trx) => {
        await auditModules.commands.logAuditEvent(
          trx,
          {
            eventId: crypto.randomUUID(),
            actorType: "USER",
            actorId: context.user.id,
            entityType: "UserRole",
            entityId: `${result.userId}:${result.roleId}`,
            operationType: "CREATE",
            changes: [
              { fieldName: "userId", newValue: result.userId },
              { fieldName: "roleId", newValue: result.roleId },
            ],
          },
          createContext(context),
        );
      })
      .catch(() => undefined);

    return result;
  },
  output: t
    .object({
      userId: t.string().description("User ID"),
      roleId: t.string().description("Assigned role ID"),
    })
    .description("Role assignment result"),
});
