import { db, type TailorAnyDBField } from "@tailor-platform/sdk";
import { defaultGqlPermission, defaultPermission } from "../../../shared/modelPermissions";
import { item as itemStub } from "../lib/_db_deps";
import { lot } from "./lot";
import { serialNumber } from "./serialNumber";
import { storageLocation } from "./storageLocation";

export const LEDGER_SOURCE_TYPES = [
  "GOODS_RECEIPT",
  "GOODS_ISSUE",
  "BLOCK",
  "UNBLOCK",
  "CORRECTION",
  "SCRAP",
] as const;

export const LEDGER_DC_INDICATORS = ["DR", "CR"] as const;

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

export function createInventoryLedgerType<const F extends Record<string, TailorAnyDBField>>(
  params: CreateInventoryLedgerTypeParams<F>,
) {
  return db
    .type("InventoryLedger", {
      sourceType: db
        .enum([...LEDGER_SOURCE_TYPES] as [string, ...string[]])
        .description("Source type: GOODS_RECEIPT, GOODS_ISSUE, BLOCK, UNBLOCK, CORRECTION, SCRAP"),
      sourceId: db
        .uuid()
        .description(
          "ID of the originating document (e.g., StockAdjustment, PurchaseOrder, SalesShipment, InventoryCount). Generic reference; not a typed foreign key.",
        ),
      dcIndicator: db
        .enum([...LEDGER_DC_INDICATORS] as [string, ...string[]])
        .description("Debit/Credit indicator (DR or CR) for accounting integration"),
      itemId: db
        .uuid()
        .relation({
          type: "n-1",
          toward: { type: itemStub },
          backward: "inventoryLedgerEntries",
        })
        .description("Foreign key to Item"),
      storageLocationId: db
        .uuid()
        .relation({
          type: "n-1",
          toward: { type: storageLocation },
          backward: "inventoryLedgerEntries",
        })
        .description("The storage location where the stock change occurs"),
      quantity: db
        .decimal()
        .description("Quantity (always positive); sourceType and dcIndicator determine direction"),
      amount: db
        .decimal({ optional: true })
        .description("Monetary amount (quantity × unitCost), used for accounting integration"),
      executedAt: db.datetime().description("Timestamp when the stock change was executed"),
      lotId: db
        .uuid({ optional: true })
        .relation({
          type: "n-1",
          toward: { type: lot },
          backward: "inventoryLedgerEntries",
        })
        .description("Optional foreign key to Lot for lot-tracked items"),
      serialNumberId: db
        .uuid({ optional: true })
        .relation({
          type: "n-1",
          toward: { type: serialNumber },
          backward: "inventoryLedgerEntries",
        })
        .description("Optional foreign key to SerialNumber for serial-tracked items"),
      ...((params.fields ?? {}) as F),
      createdAt: db.fields.timestamps().createdAt,
    })
    .permission(defaultPermission)
    .gqlPermission(defaultGqlPermission);
}

export const inventoryLedger = createInventoryLedgerType({});
