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

const APPROVAL_DECISION_TYPES = ["APPROVE", "REJECT", "DELEGATE", "WITHDRAW", "CANCEL"] as const;

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

export function createApprovalDecisionType<const F extends Record<string, TailorAnyDBField>>(
  params: CreateApprovalDecisionTypeParams<F>,
) {
  return db
    .type("ApprovalDecision", {
      approvalRequestId: db
        .uuid()
        .relation({
          type: "n-1",
          toward: { type: approvalRequest },
          backward: "decisions",
        })
        .description("Foreign key to parent ApprovalRequest (always required)"),
      approvalStepId: db
        .uuid({ optional: true })
        .relation({
          type: "n-1",
          toward: { type: approvalStep },
          backward: "decisions",
        })
        .description(
          "Foreign key to ApprovalStep; set on APPROVE/REJECT/DELEGATE, null on WITHDRAW/CANCEL",
        ),
      decision: db
        .enum(APPROVAL_DECISION_TYPES)
        .description("Decision type: APPROVE, REJECT, DELEGATE, WITHDRAW, or CANCEL"),
      decidedByUserId: db
        .uuid()
        .relation({
          type: "n-1",
          toward: { type: params.userType },
          backward: "approvalDecisionsDecided",
        })
        .description("Foreign key to User who recorded the decision (set from ctx.actorId)"),
      delegatedToUserId: db
        .uuid({ optional: true })
        .relation({
          type: "n-1",
          toward: { type: params.userType },
          backward: "approvalDecisionsDelegatedTo",
        })
        .description("Delegate user; non-null on DELEGATE rows only"),
      comment: db
        .string({ optional: true })
        .description(
          "Optional free-text on APPROVE/DELEGATE/WITHDRAW; required on REJECT/CANCEL as reason",
        ),
      decidedAt: db
        .datetime()
        .description("Decision timestamp; chronological key for getApprovalDecisionHistory"),
      ...((params.fields ?? {}) as F),
      ...db.fields.timestamps(),
    })
    .permission(defaultPermission)
    .gqlPermission(defaultGqlPermission);
}

export const approvalDecision = createApprovalDecisionType({ userType: userStub });
