import {
  db,
  type TailorAnyDBField,
  type TailorAnyDBType,
  unsafeAllowAllGqlPermission,
  unsafeAllowAllTypePermission,
} from "@tailor-platform/sdk";
import { businessPartner as businessPartnerStub, company as companyStub } from "../lib/_db_deps";
import { channel } from "./channel";
import { salesPaymentTerm } from "./salesPaymentTerm";

export const SALES_ORDER_STATUSES: [
  string,
  string,
  string,
  string,
  string,
  string,
  string,
  string,
  string,
  string,
] = [
  "DRAFT",
  "SUBMITTED",
  "CONFIRMED",
  "CREDIT_HOLD",
  "PARTIALLY_SHIPPED",
  "SHIPPED",
  "PARTIALLY_INVOICED",
  "INVOICED",
  "CANCELLED",
  "CLOSED",
];

export interface CreateSalesOrderTypeParams<F extends Record<string, TailorAnyDBField>> {
  fields?: F;
  companyType?: TailorAnyDBType;
  customerType?: TailorAnyDBType;
  channelType?: TailorAnyDBType;
  paymentTermType?: TailorAnyDBType;
}

export function createSalesOrderType<const F extends Record<string, TailorAnyDBField>>(
  params: CreateSalesOrderTypeParams<F>,
) {
  return db
    .type("SalesOrder", {
      companyId: db
        .uuid()
        .relation({
          type: "n-1",
          toward: { type: params.companyType ?? companyStub },
          backward: "salesOrders",
        })
        .description("Foreign key to Company"),
      customerId: db
        .uuid()
        .relation({
          type: "n-1",
          toward: { type: params.customerType ?? businessPartnerStub },
          backward: "salesOrders",
        })
        .description("Foreign key to Customer"),
      channelId: db
        .uuid({ optional: true })
        .relation({
          type: "n-1",
          toward: { type: params.channelType ?? channel },
          backward: "salesOrders",
        })
        .description("Optional channel"),
      paymentTermId: db
        .uuid({ optional: true })
        .relation({
          type: "n-1",
          toward: { type: params.paymentTermType ?? salesPaymentTerm },
          backward: "salesOrders",
        })
        .description("Optional payment term"),
      status: db.enum(SALES_ORDER_STATUSES).description("Sales-order lifecycle status"),
      orderDate: db.date().description("Order date"),
      requestedShipDate: db.date({ optional: true }).description("Optional requested ship date"),
      shippingAddressSnapshot: db
        .string({ optional: true })
        .description("Serialized shipping address snapshot"),
      billingAddressSnapshot: db
        .string({ optional: true })
        .description("Serialized billing address snapshot"),
      paymentTermSnapshot: db
        .string({ optional: true })
        .description("Serialized payment-term snapshot"),
      rejectionReason: db.string({ optional: true }).description("Latest rejection reason"),
      holdReason: db.string({ optional: true }).description("Latest credit-hold reason"),
      closeReason: db.string({ optional: true }).description("Close reason"),
      ...((params.fields ?? {}) as F),
      ...db.fields.timestamps(),
    })
    .permission(unsafeAllowAllTypePermission)
    .gqlPermission(unsafeAllowAllGqlPermission);
}

export const salesOrder = createSalesOrderType({});
