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

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", {
      inventoryExecutionId: db
        .uuid()
        .relation({
          type: "n-1",
          toward: { type: inventoryExecution },
          backward: "ledgerEntries",
        })
        .description(
          "Foreign key to InventoryExecution. Source documents are reached through the execution.",
        ),
      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"),
      stockType: db
        .enum([...STOCK_TYPES] as [string, ...string[]])
        .description("Stock type affected by this ledger row: AVAILABLE, BLOCKED, or IN_TRANSIT"),
      quantity: db
        .decimal()
        .description(
          "Quantity in the item's primary unit (always positive); dcIndicator determines direction",
        ),
      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({});
