import { ok, err } from "@tailor-platform/erp-kit/core";
import { Transaction } from "../generated/kysely-tailordb";
import {
  RoleAlreadyExistsError,
  MissingRequiredFieldError,
  InvalidPermissionError,
} from "../lib/errors.generated";
import { validatePermissionKey } from "../lib/validatePermissionKey";

interface CreateRoleInput {
  name: string;
  description?: string;
  permissions?: string[];
}

/**
 * Function: createRole
 *
 * Creates a new role with the specified name.
 * Validates that the name is unique within the system.
 */
export async function run<CF extends Record<string, unknown>>(
  db: Transaction,
  input: CreateRoleInput & CF,
) {
  const { name, description, permissions, ...customFields } = input;

  if (!name || name.trim() === "") {
    return err(new MissingRequiredFieldError("name"));
  }

  if (permissions) {
    for (const key of permissions) {
      if (!validatePermissionKey(key)) {
        return err(new InvalidPermissionError(key));
      }
    }
  }

  const existingRole = await db
    .selectFrom("Role")
    .selectAll()
    .where("name", "=", name)
    .forUpdate()
    .executeTakeFirst();

  if (existingRole) {
    return err(new RoleAlreadyExistsError(name));
  }

  // 3. Create role
  const role = await db
    .insertInto("Role")
    .values({
      ...(customFields as Record<string, unknown>),
      name,
      description: description ?? null,
      permissions: permissions ?? null,
      status: "ACTIVE",
    })
    .returningAll()
    .executeTakeFirstOrThrow();

  return ok({ role });
}
