import {
  db,
  type TailorAnyDBField,
  type TailorAnyDBType,
  unsafeAllowAllGqlPermission,
  unsafeAllowAllTypePermission,
} from "@tailor-platform/sdk";
import {
  company as companyStub,
  fiscalYear as fiscalYearStub,
  user as userStub,
} from "../lib/_db_deps";
import { planVersion } from "./planVersion";

export const BUDGET_STATUSES = ["DRAFT", "SUBMITTED", "APPROVED", "ACTIVE", "CLOSED"] as const;

export interface CreateBudgetTypeParams<F extends Record<string, TailorAnyDBField>> {
  fields?: F;
  companyType?: TailorAnyDBType;
  userType?: TailorAnyDBType;
  fiscalYearType?: TailorAnyDBType;
  planVersionType?: TailorAnyDBType;
}

export function createBudgetType<const F extends Record<string, TailorAnyDBField>>(
  params: CreateBudgetTypeParams<F>,
) {
  return db
    .type("Budget", {
      name: db.string().description("Budget name"),
      description: db.string({ optional: true }).description("Budget description"),
      budgetHolderId: db
        .uuid()
        .relation({
          type: "n-1",
          toward: { type: params.userType ?? userStub },
          backward: "heldBudgets",
        })
        .description("Foreign key to User who holds the budget"),
      fiscalYearId: db
        .uuid()
        .relation({
          type: "n-1",
          toward: { type: params.fiscalYearType ?? fiscalYearStub },
          backward: "budgets",
        })
        .description("Foreign key to FiscalYear (finance-ledger)"),
      companyId: db
        .uuid()
        .relation({
          type: "n-1",
          toward: { type: params.companyType ?? companyStub },
          backward: "budgets",
        })
        .description("Foreign key to Company"),
      costObjectType: db.string().description("Polymorphic cost object type"),
      costObjectId: db.uuid().description("Polymorphic cost object ID"),
      planVersionId: db
        .uuid()
        .relation({
          type: "n-1",
          toward: { type: params.planVersionType ?? planVersion },
          backward: "budgets",
        })
        .description("Foreign key to PlanVersion"),
      totalAmount: db.float().description("Total budget amount"),
      rejectionReason: db.string({ optional: true }).description("Reason for budget rejection"),
      status: db.enum([...BUDGET_STATUSES]).description("Budget lifecycle status"),
      createdByUserId: db
        .uuid()
        .relation({
          type: "n-1",
          toward: { type: params.userType ?? userStub },
          backward: "createdBudgets",
        })
        .description("Foreign key to User who created the budget"),
      ...((params.fields ?? {}) as F),
      ...db.fields.timestamps(),
    })
    .permission(unsafeAllowAllTypePermission)
    .gqlPermission(unsafeAllowAllGqlPermission);
}

export const budget = createBudgetType({});
