import {
  type CommonReservedFields,
  type NoReservedFields,
  defaultGqlPermission,
  defaultPermission,
} from "@tailor-platform/erp-kit/core";
import { db, type TailorAnyDBField } from "@tailor-platform/sdk";
import { NOTIFICATION_CHANNEL_IDS } from "./notificationChannel";

const builtins = {
  targetType: db
    .string()
    .description("Polymorphic discriminator of the bound source entity (e.g. PurchaseOrder)"),
  targetId: db.string().description("Polymorphic id of the bound source entity (no FK constraint)"),
  channelId: db
    .enum(NOTIFICATION_CHANNEL_IDS)
    .description("DESTINATION channel this binding routes to (e.g. SLACK, TEAMS)"),
  externalChannelRef: db
    .string()
    .description(
      "Opaque destination identifier the adapter posts to (e.g. Slack channel id C0123456789)",
    ),
  displayLabel: db
    .string({ optional: true })
    .description("Human-readable destination label at bind time (e.g. #po-acme)"),
  isActive: db
    .bool()
    .description("Per-binding kill-switch; inactive bindings are skipped at dispatch"),
};

type ReservedFields = keyof typeof builtins | CommonReservedFields;

export interface CreateChannelRoutingBindingTypeParams<F extends Record<string, TailorAnyDBField>> {
  fields?: NoReservedFields<F, ReservedFields>;
}

export function createChannelRoutingBindingType<const F extends Record<string, TailorAnyDBField>>(
  params: CreateChannelRoutingBindingTypeParams<F>,
) {
  return db
    .type("ChannelRoutingBinding", {
      ...builtins,
      ...((params.fields ?? {}) as F),
      ...db.fields.timestamps(),
    })
    .indexes({
      // A source entity may hold multiple bindings on the same destination
      // channel as long as each routes to a distinct externalChannelRef
      // (e.g. two Slack channels via distinct rows); the ref is part of the key.
      fields: ["targetType", "targetId", "channelId", "externalChannelRef"],
      unique: true,
      name: "channel_routing_binding_unique_idx",
    })
    .permission(defaultPermission)
    .gqlPermission(defaultGqlPermission);
}

export const channelRoutingBinding = createChannelRoutingBindingType({});
