import type { TailorAnyDBField } from "@tailor-platform/sdk";
import type { defineModule as defineCoaManagementModule } from "../coa-management";
import type { defineModule as defineFinanceLedgerModule } from "../finance-ledger";
import type { defineModule as defineOrganizationModule } from "../organization";
import type { defineModule as defineUserManagementModule } from "../user-management";
import { activateBudget } from "./command/activateBudget.generated";
import { activateCostElement } from "./command/activateCostElement.generated";
import { activateProfitCenter } from "./command/activateProfitCenter.generated";
import { approveBudget } from "./command/approveBudget.generated";
import { assignCostCenterToHierarchyNode } from "./command/assignCostCenterToHierarchyNode.generated";
import { assignProfitCenterToHierarchyNode } from "./command/assignProfitCenterToHierarchyNode.generated";
import { closeBudget } from "./command/closeBudget.generated";
import { closeInternalOrder } from "./command/closeInternalOrder.generated";
import { consumeCommitment } from "./command/consumeCommitment.generated";
import { createAllocationCycle } from "./command/createAllocationCycle.generated";
import { createAllocationRule } from "./command/createAllocationRule.generated";
import { createBudget } from "./command/createBudget.generated";
import { createBudgetLineItem } from "./command/createBudgetLineItem.generated";
import { createCostCenter } from "./command/createCostCenter.generated";
import { createCostCenterHierarchy } from "./command/createCostCenterHierarchy.generated";
import { createCostCenterHierarchyNode } from "./command/createCostCenterHierarchyNode.generated";
import { createCostElement } from "./command/createCostElement.generated";
import { createInternalOrder } from "./command/createInternalOrder.generated";
import { createPlanVersion } from "./command/createPlanVersion.generated";
import { createProfitCenter } from "./command/createProfitCenter.generated";
import { createProfitCenterHierarchy } from "./command/createProfitCenterHierarchy.generated";
import { createProfitCenterHierarchyNode } from "./command/createProfitCenterHierarchyNode.generated";
import { deactivateCostElement } from "./command/deactivateCostElement.generated";
import { deactivateProfitCenter } from "./command/deactivateProfitCenter.generated";
import { deleteAllocationCycle } from "./command/deleteAllocationCycle.generated";
import { deleteAllocationRule } from "./command/deleteAllocationRule.generated";
import { deleteBudget } from "./command/deleteBudget.generated";
import { deleteBudgetLineItem } from "./command/deleteBudgetLineItem.generated";
import { deleteCostCenter } from "./command/deleteCostCenter.generated";
import { deleteCostCenterHierarchyNode } from "./command/deleteCostCenterHierarchyNode.generated";
import { deleteCostElement } from "./command/deleteCostElement.generated";
import { deleteInternalOrder } from "./command/deleteInternalOrder.generated";
import { deleteProfitCenter } from "./command/deleteProfitCenter.generated";
import { deleteProfitCenterHierarchyNode } from "./command/deleteProfitCenterHierarchyNode.generated";
import { executeAllocationCycle } from "./command/executeAllocationCycle.generated";
import { finalizeVarianceReport } from "./command/finalizeVarianceReport.generated";
import { generateVarianceReport } from "./command/generateVarianceReport.generated";
import { invalidateAllocationCycle } from "./command/invalidateAllocationCycle.generated";
import { moveCostCenterHierarchyNode } from "./command/moveCostCenterHierarchyNode.generated";
import { postAllocationCycle } from "./command/postAllocationCycle.generated";
import { reactivateCostElement } from "./command/reactivateCostElement.generated";
import { reactivateProfitCenter } from "./command/reactivateProfitCenter.generated";
import { recordCommitment } from "./command/recordCommitment.generated";
import { rejectBudget } from "./command/rejectBudget.generated";
import { releaseCommitment } from "./command/releaseCommitment.generated";
import { releaseInternalOrder } from "./command/releaseInternalOrder.generated";
import { reverseAllocationCycle } from "./command/reverseAllocationCycle.generated";
import { submitBudget } from "./command/submitBudget.generated";
import { technicallyCompleteInternalOrder } from "./command/technicallyCompleteInternalOrder.generated";
import { updateAllocationCycle } from "./command/updateAllocationCycle.generated";
import { updateBudget } from "./command/updateBudget.generated";
import { updateCostCenter } from "./command/updateCostCenter.generated";
import { updateCostElement } from "./command/updateCostElement.generated";
import { updateInternalOrder } from "./command/updateInternalOrder.generated";
import { updateProfitCenter } from "./command/updateProfitCenter.generated";
import { validateAllocationCycle } from "./command/validateAllocationCycle.generated";
import {
  createAllocationCycleType,
  type CreateAllocationCycleTypeParams,
} from "./db/allocationCycle";
import {
  createAllocationResultType,
  type CreateAllocationResultTypeParams,
} from "./db/allocationResult";
import { createAllocationRuleType, type CreateAllocationRuleTypeParams } from "./db/allocationRule";
import { createBudgetType, type CreateBudgetTypeParams } from "./db/budget";
import { createBudgetLineItemType, type CreateBudgetLineItemTypeParams } from "./db/budgetLineItem";
import { createCommitmentType, type CreateCommitmentTypeParams } from "./db/commitment";
import { createCostCenterType, type CreateCostCenterTypeParams } from "./db/costCenter";
import {
  createCostCenterHierarchyType,
  type CreateCostCenterHierarchyTypeParams,
} from "./db/costCenterHierarchy";
import {
  createCostCenterHierarchyNodeType,
  type CreateCostCenterHierarchyNodeTypeParams,
} from "./db/costCenterHierarchyNode";
import { createCostElementType, type CreateCostElementTypeParams } from "./db/costElement";
import { createInternalOrderType, type CreateInternalOrderTypeParams } from "./db/internalOrder";
import { createPlanVersionType, type CreatePlanVersionTypeParams } from "./db/planVersion";
import { createProfitCenterType, type CreateProfitCenterTypeParams } from "./db/profitCenter";
import {
  createProfitCenterHierarchyType,
  type CreateProfitCenterHierarchyTypeParams,
} from "./db/profitCenterHierarchy";
import {
  createProfitCenterHierarchyAssignmentType,
  type CreateProfitCenterHierarchyAssignmentTypeParams,
} from "./db/profitCenterHierarchyAssignment";
import {
  createProfitCenterHierarchyNodeType,
  type CreateProfitCenterHierarchyNodeTypeParams,
} from "./db/profitCenterHierarchyNode";
import { createVarianceReportType, type CreateVarianceReportTypeParams } from "./db/varianceReport";
import {
  createVarianceReportLineType,
  type CreateVarianceReportLineTypeParams,
} from "./db/varianceReportLine";
import { calculateBudgetAvailability } from "./query/calculateBudgetAvailability.generated";
import { getAllocationCycle } from "./query/getAllocationCycle.generated";
import { getBudget } from "./query/getBudget.generated";
import { getCostCenter } from "./query/getCostCenter.generated";
import { getCostCenterHierarchy } from "./query/getCostCenterHierarchy.generated";
import { getCostElement } from "./query/getCostElement.generated";
import { getInternalOrder } from "./query/getInternalOrder.generated";
import { getProfitCenter } from "./query/getProfitCenter.generated";
import { getProfitCenterHierarchy } from "./query/getProfitCenterHierarchy.generated";
import { getVarianceReport } from "./query/getVarianceReport.generated";
import { listAllocationCycles } from "./query/listAllocationCycles.generated";
import { listBudgets } from "./query/listBudgets.generated";
import { listCostCenters } from "./query/listCostCenters.generated";
import { listCostElements } from "./query/listCostElements.generated";
import { listInternalOrders } from "./query/listInternalOrders.generated";
import { listProfitCenters } from "./query/listProfitCenters.generated";
import { type EmptyFields } from "@tailor-platform/erp-kit/module";

type OrganizationModule = ReturnType<typeof defineOrganizationModule>;
type OrganizationDB = OrganizationModule["db"];
type CoaManagementModule = ReturnType<typeof defineCoaManagementModule>;
type CoaManagementDB = CoaManagementModule["db"];
type FinanceLedgerModule = ReturnType<typeof defineFinanceLedgerModule>;
type FinanceLedgerDB = FinanceLedgerModule["db"];
type UserManagementModule = ReturnType<typeof defineUserManagementModule>;
type UserManagementDB = UserManagementModule["db"];

export interface DefineModuleParams<
  CeF extends Record<string, TailorAnyDBField> = EmptyFields,
  CcF extends Record<string, TailorAnyDBField> = EmptyFields,
  CchF extends Record<string, TailorAnyDBField> = EmptyFields,
  CchnF extends Record<string, TailorAnyDBField> = EmptyFields,
  PcF extends Record<string, TailorAnyDBField> = EmptyFields,
  PchF extends Record<string, TailorAnyDBField> = EmptyFields,
  PchaF extends Record<string, TailorAnyDBField> = EmptyFields,
  PchnF extends Record<string, TailorAnyDBField> = EmptyFields,
  IoF extends Record<string, TailorAnyDBField> = EmptyFields,
  AcF extends Record<string, TailorAnyDBField> = EmptyFields,
  ArF extends Record<string, TailorAnyDBField> = EmptyFields,
  AresF extends Record<string, TailorAnyDBField> = EmptyFields,
  PvF extends Record<string, TailorAnyDBField> = EmptyFields,
  BF extends Record<string, TailorAnyDBField> = EmptyFields,
  BliF extends Record<string, TailorAnyDBField> = EmptyFields,
  CmF extends Record<string, TailorAnyDBField> = EmptyFields,
  VrF extends Record<string, TailorAnyDBField> = EmptyFields,
  VrlF extends Record<string, TailorAnyDBField> = EmptyFields,
> {
  costElement?: CreateCostElementTypeParams<CeF>;
  costCenter?: CreateCostCenterTypeParams<CcF>;
  costCenterHierarchy?: CreateCostCenterHierarchyTypeParams<CchF>;
  costCenterHierarchyNode?: CreateCostCenterHierarchyNodeTypeParams<CchnF>;
  profitCenter?: CreateProfitCenterTypeParams<PcF>;
  profitCenterHierarchy?: CreateProfitCenterHierarchyTypeParams<PchF>;
  profitCenterHierarchyAssignment?: CreateProfitCenterHierarchyAssignmentTypeParams<PchaF>;
  profitCenterHierarchyNode?: CreateProfitCenterHierarchyNodeTypeParams<PchnF>;
  internalOrder?: CreateInternalOrderTypeParams<IoF>;
  allocationCycle?: CreateAllocationCycleTypeParams<AcF>;
  allocationRule?: CreateAllocationRuleTypeParams<ArF>;
  allocationResult?: CreateAllocationResultTypeParams<AresF>;
  planVersion?: CreatePlanVersionTypeParams<PvF>;
  budget?: CreateBudgetTypeParams<BF>;
  budgetLineItem?: CreateBudgetLineItemTypeParams<BliF>;
  commitment?: CreateCommitmentTypeParams<CmF>;
  varianceReport?: CreateVarianceReportTypeParams<VrF>;
  varianceReportLine?: CreateVarianceReportLineTypeParams<VrlF>;
  organization: {
    db: {
      company: OrganizationDB["company"];
      department: OrganizationDB["department"];
    };
  };
  coaManagement: {
    db: {
      account: CoaManagementDB["account"];
    };
  };
  financeLedger: {
    db: {
      accountingPeriod: FinanceLedgerDB["accountingPeriod"];
      fiscalYear: FinanceLedgerDB["fiscalYear"];
    };
  };
  userManagement: {
    db: {
      user: UserManagementDB["user"];
    };
  };
}

/* @__NO_SIDE_EFFECTS__ */
export const defineModule = <
  const CeF extends Record<string, TailorAnyDBField> = EmptyFields,
  const CcF extends Record<string, TailorAnyDBField> = EmptyFields,
  const CchF extends Record<string, TailorAnyDBField> = EmptyFields,
  const CchnF extends Record<string, TailorAnyDBField> = EmptyFields,
  const PcF extends Record<string, TailorAnyDBField> = EmptyFields,
  const PchF extends Record<string, TailorAnyDBField> = EmptyFields,
  const PchaF extends Record<string, TailorAnyDBField> = EmptyFields,
  const PchnF extends Record<string, TailorAnyDBField> = EmptyFields,
  const IoF extends Record<string, TailorAnyDBField> = EmptyFields,
  const AcF extends Record<string, TailorAnyDBField> = EmptyFields,
  const ArF extends Record<string, TailorAnyDBField> = EmptyFields,
  const AresF extends Record<string, TailorAnyDBField> = EmptyFields,
  const PvF extends Record<string, TailorAnyDBField> = EmptyFields,
  const BF extends Record<string, TailorAnyDBField> = EmptyFields,
  const BliF extends Record<string, TailorAnyDBField> = EmptyFields,
  const CmF extends Record<string, TailorAnyDBField> = EmptyFields,
  const VrF extends Record<string, TailorAnyDBField> = EmptyFields,
  const VrlF extends Record<string, TailorAnyDBField> = EmptyFields,
>(
  params: DefineModuleParams<
    CeF,
    CcF,
    CchF,
    CchnF,
    PcF,
    PchF,
    PchaF,
    PchnF,
    IoF,
    AcF,
    ArF,
    AresF,
    PvF,
    BF,
    BliF,
    CmF,
    VrF,
    VrlF
  >,
) => {
  const costElementDb = createCostElementType({
    ...params.costElement,
    companyType: params.organization.db.company,
    accountType: params.coaManagement.db.account,
  });
  const costCenterHierarchyDb = createCostCenterHierarchyType({
    ...params.costCenterHierarchy,
    companyType: params.organization.db.company,
  });
  const costCenterHierarchyNodeDb = createCostCenterHierarchyNodeType({
    ...params.costCenterHierarchyNode,
    costCenterHierarchyType: costCenterHierarchyDb,
  });
  const costCenterDb = createCostCenterType({
    ...params.costCenter,
    companyType: params.organization.db.company,
    costCenterHierarchyNodeType: costCenterHierarchyNodeDb,
    userType: params.userManagement.db.user,
    departmentType: params.organization.db.department,
  });
  const profitCenterHierarchyDb = createProfitCenterHierarchyType({
    ...params.profitCenterHierarchy,
    companyType: params.organization.db.company,
  });
  const profitCenterHierarchyNodeDb = createProfitCenterHierarchyNodeType({
    ...params.profitCenterHierarchyNode,
    profitCenterHierarchyType: profitCenterHierarchyDb,
  });
  const profitCenterDb = createProfitCenterType({
    ...params.profitCenter,
    companyType: params.organization.db.company,
    userType: params.userManagement.db.user,
  });
  const profitCenterHierarchyAssignmentDb = createProfitCenterHierarchyAssignmentType({
    ...params.profitCenterHierarchyAssignment,
    profitCenterType: profitCenterDb,
    profitCenterHierarchyType: profitCenterHierarchyDb,
    profitCenterHierarchyNodeType: profitCenterHierarchyNodeDb,
  });
  const internalOrderDb = createInternalOrderType({
    ...params.internalOrder,
    companyType: params.organization.db.company,
    costCenterType: costCenterDb,
    userType: params.userManagement.db.user,
  });
  const allocationCycleDb = createAllocationCycleType({
    ...params.allocationCycle,
    companyType: params.organization.db.company,
    accountingPeriodType: params.financeLedger.db.accountingPeriod,
  });
  const allocationRuleDb = createAllocationRuleType({
    ...params.allocationRule,
    allocationCycleType: allocationCycleDb,
    costCenterType: costCenterDb,
  });
  const allocationResultDb = createAllocationResultType({
    ...params.allocationResult,
    allocationCycleType: allocationCycleDb,
    costCenterType: costCenterDb,
    costElementType: costElementDb,
  });
  const planVersionDb = createPlanVersionType({
    ...params.planVersion,
    companyType: params.organization.db.company,
  });
  const budgetDb = createBudgetType({
    ...params.budget,
    companyType: params.organization.db.company,
    userType: params.userManagement.db.user,
    fiscalYearType: params.financeLedger.db.fiscalYear,
    planVersionType: planVersionDb,
  });
  const budgetLineItemDb = createBudgetLineItemType({
    ...params.budgetLineItem,
    budgetType: budgetDb,
    costElementType: costElementDb,
    accountingPeriodType: params.financeLedger.db.accountingPeriod,
  });
  const commitmentDb = createCommitmentType({
    ...params.commitment,
    costElementType: costElementDb,
    companyType: params.organization.db.company,
    accountingPeriodType: params.financeLedger.db.accountingPeriod,
  });
  const varianceReportDb = createVarianceReportType({
    ...params.varianceReport,
    companyType: params.organization.db.company,
    accountingPeriodType: params.financeLedger.db.accountingPeriod,
  });
  const varianceReportLineDb = createVarianceReportLineType({
    ...params.varianceReportLine,
    varianceReportType: varianceReportDb,
    costElementType: costElementDb,
    accountingPeriodType: params.financeLedger.db.accountingPeriod,
  });

  return {
    db: {
      costElement: costElementDb,
      costCenter: costCenterDb,
      costCenterHierarchy: costCenterHierarchyDb,
      costCenterHierarchyNode: costCenterHierarchyNodeDb,
      profitCenter: profitCenterDb,
      profitCenterHierarchy: profitCenterHierarchyDb,
      profitCenterHierarchyAssignment: profitCenterHierarchyAssignmentDb,
      profitCenterHierarchyNode: profitCenterHierarchyNodeDb,
      internalOrder: internalOrderDb,
      allocationCycle: allocationCycleDb,
      allocationRule: allocationRuleDb,
      allocationResult: allocationResultDb,
      planVersion: planVersionDb,
      budget: budgetDb,
      budgetLineItem: budgetLineItemDb,
      commitment: commitmentDb,
      varianceReport: varianceReportDb,
      varianceReportLine: varianceReportLineDb,
    },
    commands: {
      activateBudget: activateBudget(),
      activateCostElement: activateCostElement(),
      activateProfitCenter: activateProfitCenter(),
      approveBudget: approveBudget(),
      assignCostCenterToHierarchyNode: assignCostCenterToHierarchyNode(),
      assignProfitCenterToHierarchyNode: assignProfitCenterToHierarchyNode(),
      closeBudget: closeBudget(),
      closeInternalOrder: closeInternalOrder(),
      consumeCommitment: consumeCommitment(),
      createAllocationCycle: createAllocationCycle(),
      createAllocationRule: createAllocationRule(),
      createBudget: createBudget(),
      createBudgetLineItem: createBudgetLineItem(),
      createCostCenter: createCostCenter(),
      createCostCenterHierarchy: createCostCenterHierarchy(),
      createCostCenterHierarchyNode: createCostCenterHierarchyNode(),
      createCostElement: createCostElement(),
      createInternalOrder: createInternalOrder(),
      createPlanVersion: createPlanVersion(),
      createProfitCenter: createProfitCenter(),
      createProfitCenterHierarchy: createProfitCenterHierarchy(),
      createProfitCenterHierarchyNode: createProfitCenterHierarchyNode(),
      deactivateCostElement: deactivateCostElement(),
      deactivateProfitCenter: deactivateProfitCenter(),
      deleteAllocationCycle: deleteAllocationCycle(),
      deleteAllocationRule: deleteAllocationRule(),
      deleteBudget: deleteBudget(),
      deleteBudgetLineItem: deleteBudgetLineItem(),
      deleteCostCenter: deleteCostCenter(),
      deleteCostCenterHierarchyNode: deleteCostCenterHierarchyNode(),
      deleteCostElement: deleteCostElement(),
      deleteInternalOrder: deleteInternalOrder(),
      deleteProfitCenter: deleteProfitCenter(),
      deleteProfitCenterHierarchyNode: deleteProfitCenterHierarchyNode(),
      executeAllocationCycle: executeAllocationCycle(),
      finalizeVarianceReport: finalizeVarianceReport(),
      generateVarianceReport: generateVarianceReport(),
      invalidateAllocationCycle: invalidateAllocationCycle(),
      moveCostCenterHierarchyNode: moveCostCenterHierarchyNode(),
      postAllocationCycle: postAllocationCycle(),
      reactivateCostElement: reactivateCostElement(),
      reactivateProfitCenter: reactivateProfitCenter(),
      recordCommitment: recordCommitment(),
      rejectBudget: rejectBudget(),
      releaseCommitment: releaseCommitment(),
      releaseInternalOrder: releaseInternalOrder(),
      reverseAllocationCycle: reverseAllocationCycle(),
      submitBudget: submitBudget(),
      technicallyCompleteInternalOrder: technicallyCompleteInternalOrder(),
      updateAllocationCycle: updateAllocationCycle(),
      updateBudget: updateBudget(),
      updateCostCenter: updateCostCenter(),
      updateCostElement: updateCostElement(),
      updateInternalOrder: updateInternalOrder(),
      updateProfitCenter: updateProfitCenter(),
      validateAllocationCycle: validateAllocationCycle(),
    },
    queries: {
      calculateBudgetAvailability,
      getAllocationCycle,
      getBudget,
      getCostCenter,
      getCostCenterHierarchy,
      getCostElement,
      getInternalOrder,
      getProfitCenter,
      getProfitCenterHierarchy,
      getVarianceReport,
      listAllocationCycles,
      listBudgets,
      listCostCenters,
      listCostElements,
      listInternalOrders,
      listProfitCenters,
    },
  };
};
