import { defaultGqlPermission, defaultPermission } from "@tailor-platform/erp-kit/core";
import { db, type TailorAnyDBType } from "@tailor-platform/sdk";
import { approvalStep } from "./approvalStep";
import { approvalStepAssigneeLifecycle } from "./approvalStepAssignee.lifecycle.generated";

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

export interface CreateApprovalStepAssigneeTypeParams {
  userType?: TailorAnyDBType;
  roleType?: TailorAnyDBType;
}

export function createApprovalStepAssigneeType(params: CreateApprovalStepAssigneeTypeParams) {
  const userId = db
    .uuid({ optional: true })
    .description("Concrete user voter; XOR with roleId before role expansion, set after");
  const roleId = db
    .uuid({ optional: true })
    .description(
      "Role placeholder; retained for traceability after expansion (XOR with userId before expansion)",
    );
  return db
    .type("ApprovalStepAssignee", {
      approvalStepId: db
        .uuid()
        .relation({
          type: "n-1",
          toward: { type: approvalStep },
          backward: "assignees",
        })
        .description("Foreign key to parent ApprovalStep"),
      userId: params.userType
        ? userId.relation({
            type: "n-1",
            toward: { type: params.userType },
            backward: "approvalStepAssignees",
          })
        : userId,
      roleId: params.roleType
        ? roleId.relation({
            type: "n-1",
            toward: { type: params.roleType },
            backward: "approvalStepAssignees",
          })
        : roleId,
      required: db
        .bool()
        .description(
          "User-assignee mandatory flag (meaningful only when roleId is null after expansion, ignored on role-expanded rows)",
        ),
      roleQuorum: db
        .enum(ROLE_QUORUM_TYPES, { optional: true })
        .description(
          "Group semantics propagated from the originating role assignee (meaningful only when roleId is set): ALL = every group member must approve, ANY = any one suffices, null = no group-level constraint",
        ),
      status: db
        .enum(approvalStepAssigneeLifecycle.states)
        .description("Per-assignee voting status: PENDING, APPROVED, REJECTED, or DELEGATED"),
      resolvedAt: db
        .datetime({ optional: true })
        .description("Set when status reaches APPROVED, REJECTED, or DELEGATED"),
      ...db.fields.timestamps(),
    })
    .permission(defaultPermission)
    .gqlPermission(defaultGqlPermission);
}

export const approvalStepAssignee = createApprovalStepAssigneeType({});
