import {
  db,
  type TailorAnyDBField,
  type TailorAnyDBType,
  unsafeAllowAllGqlPermission,
  unsafeAllowAllTypePermission,
} from "@tailor-platform/sdk";
import { accountingPeriod as accountingPeriodStub } from "../lib/_db_deps";
import { budget } from "./budget";
import { costElement } from "./costElement";

export interface CreateBudgetLineItemTypeParams<F extends Record<string, TailorAnyDBField>> {
  fields?: F;
  budgetType?: TailorAnyDBType;
  costElementType?: TailorAnyDBType;
  accountingPeriodType?: TailorAnyDBType;
}

export function createBudgetLineItemType<const F extends Record<string, TailorAnyDBField>>(
  params: CreateBudgetLineItemTypeParams<F>,
) {
  return db
    .type("BudgetLineItem", {
      budgetId: db
        .uuid()
        .relation({
          type: "n-1",
          toward: { type: params.budgetType ?? budget },
          backward: "lineItems",
        })
        .description("Foreign key to Budget"),
      costElementId: db
        .uuid()
        .relation({
          type: "n-1",
          toward: { type: params.costElementType ?? costElement },
          backward: "budgetLineItems",
        })
        .description("Foreign key to CostElement"),
      accountingPeriodId: db
        .uuid()
        .relation({
          type: "n-1",
          toward: { type: params.accountingPeriodType ?? accountingPeriodStub },
          backward: "budgetLineItems",
        })
        .description("Foreign key to AccountingPeriod (finance-ledger)"),
      glAccountId: db
        .uuid({ optional: true })
        .description("GL account ID derived from the primary cost element's GL account mapping"),
      plannedAmount: db.float().description("Planned budget amount"),
      ...((params.fields ?? {}) as F),
      ...db.fields.timestamps(),
    })
    .indexes({
      fields: ["budgetId", "costElementId", "accountingPeriodId"],
      unique: true,
      name: "budget_line_item_unique_idx",
    })
    .permission(unsafeAllowAllTypePermission)
    .gqlPermission(unsafeAllowAllGqlPermission);
}

export const budgetLineItem = createBudgetLineItemType({});
