import { db, type TailorAnyDBField, type TailorAnyDBType } from "@tailor-platform/sdk";
import { defaultGqlPermission, defaultPermission } from "../../../shared/modelPermissions";
import { role as roleStub, user as userStub } from "../lib/_db_deps";
import { approvalPolicyStep } from "./approvalPolicyStep";

const ROLE_QUORUM_TYPES = ["ALL", "ANY"] as const;

export interface CreateApprovalPolicyStepAssigneeTypeParams<
  F extends Record<string, TailorAnyDBField>,
> {
  fields?: F;
  userType: TailorAnyDBType;
  roleType: TailorAnyDBType;
}

export function createApprovalPolicyStepAssigneeType<
  const F extends Record<string, TailorAnyDBField>,
>(params: CreateApprovalPolicyStepAssigneeTypeParams<F>) {
  return db
    .type("ApprovalPolicyStepAssignee", {
      approvalPolicyStepId: db
        .uuid()
        .relation({
          type: "n-1",
          toward: { type: approvalPolicyStep },
          backward: "assignees",
        })
        .description("Foreign key to ApprovalPolicyStep"),
      userId: db
        .uuid({ optional: true })
        .relation({
          type: "n-1",
          toward: { type: params.userType },
          backward: "approvalPolicyStepAssignees",
        })
        .description("Specific user assignee (XOR with roleId)"),
      roleId: db
        .uuid({ optional: true })
        .relation({
          type: "n-1",
          toward: { type: params.roleType },
          backward: "approvalPolicyStepAssignees",
        })
        .description(
          "Role assignee, expanded to current ACTIVE members at runtime (XOR with userId)",
        ),
      required: db
        .bool()
        .description(
          "User-assignee mandatory flag (meaningful only when userId is set, ignored on role assignees)",
        ),
      roleQuorum: db
        .enum(ROLE_QUORUM_TYPES, { optional: true })
        .description(
          "Role-assignee group semantics (meaningful only when roleId is set): ALL = every member must approve, ANY = a single member's approval suffices, null = no group-level constraint (only step.minimumApprovals applies)",
        ),
      ...((params.fields ?? {}) as F),
      ...db.fields.timestamps(),
    })
    .permission(defaultPermission)
    .gqlPermission(defaultGqlPermission);
}

export const approvalPolicyStepAssignee = createApprovalPolicyStepAssigneeType({
  userType: userStub,
  roleType: roleStub,
});
