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

export const PERIOD_CLOSE_STATUSES: [
  string,
  string,
  string,
  string,
  string,
  string,
  string,
  string,
] = [
  "NOT_STARTED",
  "IN_PROGRESS",
  "SUBLEDGERS_VERIFIED",
  "ADJUSTMENTS_POSTED",
  "TRIAL_BALANCE_VERIFIED",
  "UNDER_REVIEW",
  "SOFT_LOCKED",
  "PERMANENTLY_CLOSED",
];

export interface CreatePeriodCloseTypeParams<F extends Record<string, TailorAnyDBField>> {
  fields?: F;
  accountingPeriodType?: TailorAnyDBType;
  initiatedByUserType?: TailorAnyDBType;
  approvedByUserType?: TailorAnyDBType;
  finalizedByUserType?: TailorAnyDBType;
}

export function createPeriodCloseType<const F extends Record<string, TailorAnyDBField>>(
  params: CreatePeriodCloseTypeParams<F>,
) {
  return db
    .type("PeriodClose", {
      accountingPeriodId: db
        .uuid()
        .relation({
          type: "n-1",
          toward: { type: params.accountingPeriodType ?? accountingPeriod },
          backward: "periodCloses",
        })
        .description("Foreign key to AccountingPeriod"),
      status: db.enum(PERIOD_CLOSE_STATUSES).description("Period close lifecycle status"),
      initiatedByUserId: db
        .uuid()
        .relation({
          type: "n-1",
          toward: { type: params.initiatedByUserType ?? userStub },
          backward: "initiatedPeriodCloses",
        })
        .description("Foreign key to User who initiated the close"),
      completionPercentage: db
        .int()
        .description("Completion percentage incremented per checklist step"),
      subledgerVerificationDetails: db
        .string({ optional: true })
        .description("Serialized JSON details of subledger verification"),
      trialBalanceId: db
        .uuid({ optional: true })
        .description("Reference to generated trial balance after verification"),
      preliminaryStatementIds: db
        .string({ optional: true })
        .description("Serialized JSON array of preliminary statement IDs"),
      approvedByUserId: db
        .uuid({ optional: true })
        .relation({
          type: "n-1",
          toward: { type: params.approvedByUserType ?? userStub },
          backward: "approvedPeriodCloses",
        })
        .description("Foreign key to User who approved the close"),
      finalizedByUserId: db
        .uuid({ optional: true })
        .relation({
          type: "n-1",
          toward: { type: params.finalizedByUserType ?? userStub },
          backward: "finalizedPeriodCloses",
        })
        .description("Foreign key to User who finalized the permanent close"),
      yearEndCloseExecuted: db.bool().description("Whether year-end close has been executed"),
      ...((params.fields ?? {}) as F),
      ...db.fields.timestamps(),
    })
    .permission(unsafeAllowAllTypePermission)
    .gqlPermission(unsafeAllowAllGqlPermission);
}

export const periodClose = createPeriodCloseType({});
