import type { TailorAnyDBField } from "@tailor-platform/sdk";
import type { defineModule as defineBusinessPartnerModule } from "../business-partner";
import type { defineModule as defineItemManagementModule } from "../item-management";
import type { defineModule as defineOrganizationModule } from "../organization";
import type { defineModule as definePrimitivesModule } from "../primitives";
import { activatePurchasePaymentTerm } from "./command/activatePurchasePaymentTerm.generated";
import { activatePurchasePriceList } from "./command/activatePurchasePriceList.generated";
import { activatePurchasePriceRule } from "./command/activatePurchasePriceRule.generated";
import { approvePurchaseOrder } from "./command/approvePurchaseOrder.generated";
import { cancelGoodsReceipt } from "./command/cancelGoodsReceipt.generated";
import { cancelPurchaseBill } from "./command/cancelPurchaseBill.generated";
import { cancelPurchaseOrder } from "./command/cancelPurchaseOrder.generated";
import { closePurchaseOrder } from "./command/closePurchaseOrder.generated";
import { createGoodsReceipt } from "./command/createGoodsReceipt.generated";
import { createPurchaseBill } from "./command/createPurchaseBill.generated";
import { createPurchaseOrder } from "./command/createPurchaseOrder.generated";
import { createPurchasePaymentTerm } from "./command/createPurchasePaymentTerm.generated";
import { createPurchasePriceList } from "./command/createPurchasePriceList.generated";
import { createPurchasePriceRule } from "./command/createPurchasePriceRule.generated";
import { deactivatePurchasePaymentTerm } from "./command/deactivatePurchasePaymentTerm.generated";
import { deactivatePurchasePriceList } from "./command/deactivatePurchasePriceList.generated";
import { deactivatePurchasePriceRule } from "./command/deactivatePurchasePriceRule.generated";
import { matchPurchaseBill } from "./command/matchPurchaseBill.generated";
import { postGoodsReceipt } from "./command/postGoodsReceipt.generated";
import { rejectPurchaseOrder } from "./command/rejectPurchaseOrder.generated";
import { releasePurchaseBill } from "./command/releasePurchaseBill.generated";
import { setSupplierDefaultPurchasePaymentTerm } from "./command/setSupplierDefaultPurchasePaymentTerm.generated";
import { submitPurchaseOrder } from "./command/submitPurchaseOrder.generated";
import { updateGoodsReceipt } from "./command/updateGoodsReceipt.generated";
import { updatePurchaseBill } from "./command/updatePurchaseBill.generated";
import { updatePurchaseOrder } from "./command/updatePurchaseOrder.generated";
import { updatePurchasePaymentTerm } from "./command/updatePurchasePaymentTerm.generated";
import { updatePurchasePriceList } from "./command/updatePurchasePriceList.generated";
import { updatePurchasePriceRule } from "./command/updatePurchasePriceRule.generated";
import { createGoodsReceiptType, type CreateGoodsReceiptTypeParams } from "./db/goodsReceipt";
import { createPurchaseBillType, type CreatePurchaseBillTypeParams } from "./db/purchaseBill";
import { createPurchaseOrderType, type CreatePurchaseOrderTypeParams } from "./db/purchaseOrder";
import {
  createPurchasePaymentTermType,
  type CreatePurchasePaymentTermTypeParams,
} from "./db/purchasePaymentTerm";
import {
  createPurchasePriceListType,
  type CreatePurchasePriceListTypeParams,
} from "./db/purchasePriceList";
import {
  createPurchasePriceRuleType,
  type CreatePurchasePriceRuleTypeParams,
} from "./db/purchasePriceRule";
import {
  createSupplierProfileType,
  type CreateSupplierProfileTypeParams,
} from "./db/supplierProfile";
import { calculatePurchaseBillDueSchedule } from "./query/calculatePurchaseBillDueSchedule.generated";
import { calculatePurchasePrice } from "./query/calculatePurchasePrice.generated";
import { getGoodsReceipt } from "./query/getGoodsReceipt.generated";
import { getPurchaseBill } from "./query/getPurchaseBill.generated";
import { getPurchaseOrder } from "./query/getPurchaseOrder.generated";
import { getPurchasePaymentTerm } from "./query/getPurchasePaymentTerm.generated";
import { getPurchasePriceList } from "./query/getPurchasePriceList.generated";
import { getSupplierProfile } from "./query/getSupplierProfile.generated";

type OrganizationModule = ReturnType<typeof defineOrganizationModule>;
type OrganizationDB = OrganizationModule["db"];
type BusinessPartnerModule = ReturnType<typeof defineBusinessPartnerModule>;
type BusinessPartnerDB = BusinessPartnerModule["db"];
type ItemManagementModule = ReturnType<typeof defineItemManagementModule>;
type ItemManagementDB = ItemManagementModule["db"];
type PrimitivesModule = ReturnType<typeof definePrimitivesModule>;
type PrimitivesDB = PrimitivesModule["db"];

export interface DefineModuleParams<
  SPF extends Record<string, TailorAnyDBField>,
  PTF extends Record<string, TailorAnyDBField>,
  PLF extends Record<string, TailorAnyDBField>,
  PRF extends Record<string, TailorAnyDBField>,
  POF extends Record<string, TailorAnyDBField>,
  GRF extends Record<string, TailorAnyDBField>,
  PBF extends Record<string, TailorAnyDBField>,
> {
  supplierProfile?: CreateSupplierProfileTypeParams<SPF>;
  purchasePaymentTerm?: CreatePurchasePaymentTermTypeParams<PTF>;
  purchasePriceList?: CreatePurchasePriceListTypeParams<PLF>;
  purchasePriceRule?: CreatePurchasePriceRuleTypeParams<PRF>;
  purchaseOrder?: CreatePurchaseOrderTypeParams<POF>;
  goodsReceipt?: CreateGoodsReceiptTypeParams<GRF>;
  purchaseBill?: CreatePurchaseBillTypeParams<PBF>;
  organization: {
    db: {
      company: OrganizationDB["company"];
      site: OrganizationDB["site"];
    };
  };
  businessPartner: {
    db: {
      businessPartner: BusinessPartnerDB["businessPartner"];
      partnerRole: BusinessPartnerDB["partnerRole"];
      partnerIdentification: BusinessPartnerDB["partnerIdentification"];
    };
  };
  itemManagement: {
    db: {
      item: ItemManagementDB["item"];
    };
  };
  primitives: {
    db: {
      currency: PrimitivesDB["currency"];
      unit: PrimitivesDB["unit"];
    };
  };
}

/* @__NO_SIDE_EFFECTS__ */
export const defineModule = <
  const SPF extends Record<string, TailorAnyDBField> = Record<never, never>,
  const PTF extends Record<string, TailorAnyDBField> = Record<never, never>,
  const PLF extends Record<string, TailorAnyDBField> = Record<never, never>,
  const PRF extends Record<string, TailorAnyDBField> = Record<never, never>,
  const POF extends Record<string, TailorAnyDBField> = Record<never, never>,
  const GRF extends Record<string, TailorAnyDBField> = Record<never, never>,
  const PBF extends Record<string, TailorAnyDBField> = Record<never, never>,
>(
  params: DefineModuleParams<SPF, PTF, PLF, PRF, POF, GRF, PBF>,
) => {
  const purchasePaymentTermDb = createPurchasePaymentTermType({
    ...params.purchasePaymentTerm,
    companyType: params.organization.db.company,
  });
  const supplierProfileDb = createSupplierProfileType({
    ...params.supplierProfile,
    companyType: params.organization.db.company,
    supplierType: params.businessPartner.db.businessPartner,
    paymentTermType: purchasePaymentTermDb,
  });
  const purchasePriceListDb = createPurchasePriceListType({
    ...params.purchasePriceList,
    companyType: params.organization.db.company,
    supplierType: params.businessPartner.db.businessPartner,
  });
  const purchasePriceRuleDb = createPurchasePriceRuleType({
    ...params.purchasePriceRule,
    priceListType: purchasePriceListDb,
    itemType: params.itemManagement.db.item,
    currencyType: params.primitives.db.currency,
    unitType: params.primitives.db.unit,
  });
  const purchaseOrderDb = createPurchaseOrderType({
    ...params.purchaseOrder,
    companyType: params.organization.db.company,
    supplierType: params.businessPartner.db.businessPartner,
    siteType: params.organization.db.site,
    paymentTermType: purchasePaymentTermDb,
  });
  const goodsReceiptDb = createGoodsReceiptType({
    ...params.goodsReceipt,
    companyType: params.organization.db.company,
    supplierType: params.businessPartner.db.businessPartner,
    purchaseOrderType: purchaseOrderDb,
  });
  const purchaseBillDb = createPurchaseBillType({
    ...params.purchaseBill,
    companyType: params.organization.db.company,
    supplierType: params.businessPartner.db.businessPartner,
  });

  return {
    db: {
      supplierProfile: supplierProfileDb,
      purchasePaymentTerm: purchasePaymentTermDb,
      purchasePriceList: purchasePriceListDb,
      purchasePriceRule: purchasePriceRuleDb,
      purchaseOrder: purchaseOrderDb,
      goodsReceipt: goodsReceiptDb,
      purchaseBill: purchaseBillDb,
    },
    commands: {
      activatePurchasePaymentTerm: activatePurchasePaymentTerm(),
      activatePurchasePriceList: activatePurchasePriceList(),
      activatePurchasePriceRule: activatePurchasePriceRule(),
      approvePurchaseOrder: approvePurchaseOrder(),
      cancelGoodsReceipt: cancelGoodsReceipt(),
      cancelPurchaseBill: cancelPurchaseBill(),
      cancelPurchaseOrder: cancelPurchaseOrder(),
      closePurchaseOrder: closePurchaseOrder(),
      createGoodsReceipt: createGoodsReceipt(),
      createPurchaseBill: createPurchaseBill(),
      createPurchaseOrder: createPurchaseOrder(),
      createPurchasePaymentTerm: createPurchasePaymentTerm(),
      createPurchasePriceList: createPurchasePriceList(),
      createPurchasePriceRule: createPurchasePriceRule(),
      deactivatePurchasePaymentTerm: deactivatePurchasePaymentTerm(),
      deactivatePurchasePriceList: deactivatePurchasePriceList(),
      deactivatePurchasePriceRule: deactivatePurchasePriceRule(),
      matchPurchaseBill: matchPurchaseBill(),
      postGoodsReceipt: postGoodsReceipt(),
      rejectPurchaseOrder: rejectPurchaseOrder(),
      releasePurchaseBill: releasePurchaseBill(),
      setSupplierDefaultPurchasePaymentTerm: setSupplierDefaultPurchasePaymentTerm(),
      submitPurchaseOrder: submitPurchaseOrder(),
      updateGoodsReceipt: updateGoodsReceipt(),
      updatePurchaseBill: updatePurchaseBill(),
      updatePurchaseOrder: updatePurchaseOrder(),
      updatePurchasePaymentTerm: updatePurchasePaymentTerm(),
      updatePurchasePriceList: updatePurchasePriceList(),
      updatePurchasePriceRule: updatePurchasePriceRule(),
    },
    queries: {
      calculatePurchaseBillDueSchedule,
      calculatePurchasePrice,
      getGoodsReceipt,
      getPurchaseBill,
      getPurchaseOrder,
      getPurchasePaymentTerm,
      getPurchasePriceList,
      getSupplierProfile,
    },
  };
};
