import {
  db,
  type TailorAnyDBField,
  type TailorAnyDBType,
  unsafeAllowAllGqlPermission,
  unsafeAllowAllTypePermission,
} from "@tailor-platform/sdk";
import { chartOfAccounts as chartOfAccountsStub, company as companyStub } from "../lib/_db_deps";
import { trialBalance } from "./trialBalance";

export const FINANCIAL_STATEMENT_STATUSES: [string, string] = ["DRAFT", "FINALIZED"];

export const STATEMENT_TYPES: [string, string, string] = [
  "BALANCE_SHEET",
  "PROFIT_AND_LOSS",
  "CASH_FLOW",
];

export interface CreateFinancialStatementTypeParams<F extends Record<string, TailorAnyDBField>> {
  fields?: F;
  companyType?: TailorAnyDBType;
  chartOfAccountsType?: TailorAnyDBType;
  trialBalanceType?: TailorAnyDBType;
}

export function createFinancialStatementType<const F extends Record<string, TailorAnyDBField>>(
  params: CreateFinancialStatementTypeParams<F>,
) {
  return db
    .type("FinancialStatement", {
      companyId: db
        .uuid()
        .relation({
          type: "n-1",
          toward: { type: params.companyType ?? companyStub },
          backward: "financialStatements",
        })
        .description("Foreign key to Company"),
      chartOfAccountsId: db
        .uuid()
        .relation({
          type: "n-1",
          toward: { type: params.chartOfAccountsType ?? chartOfAccountsStub },
          backward: "financialStatements",
        })
        .description("Foreign key to ChartOfAccounts"),
      trialBalanceId: db
        .uuid()
        .relation({
          type: "n-1",
          toward: { type: params.trialBalanceType ?? trialBalance },
          backward: "financialStatements",
        })
        .description("Foreign key to the TrialBalance this statement was generated from"),
      comparativePeriodTrialBalanceId: db
        .uuid({ optional: true })
        .relation({
          type: "n-1",
          toward: { type: params.trialBalanceType ?? trialBalance },
          backward: "comparativeFinancialStatements",
        })
        .description("Optional foreign key to a prior-period TrialBalance for comparative data"),
      statementType: db.enum(STATEMENT_TYPES).description("Type of financial statement"),
      status: db
        .enum(FINANCIAL_STATEMENT_STATUSES)
        .description("Financial statement lifecycle status"),
      reportingDate: db
        .date({ optional: true })
        .description("As-of date for Balance Sheet statements"),
      startDate: db
        .date({ optional: true })
        .description("Start date of the reporting period for P&L and Cash Flow statements"),
      endDate: db
        .date({ optional: true })
        .description("End date of the reporting period for P&L and Cash Flow statements"),
      cashFlowMethod: db
        .string({ optional: true })
        .description(
          "Cash flow method — DIRECT or INDIRECT — applicable only to Cash Flow statements",
        ),
      generatedAt: db.datetime().description("Timestamp when the statement was generated"),
      finalizedAt: db
        .datetime({ optional: true })
        .description("Timestamp when the statement was finalized"),
      ...((params.fields ?? {}) as F),
      ...db.fields.timestamps(),
    })
    .permission(unsafeAllowAllTypePermission)
    .gqlPermission(unsafeAllowAllGqlPermission);
}

export const financialStatement = createFinancialStatementType({});
