import { type TailorAnyDBField } from "@tailor-platform/sdk";
import type { defineModule as defineOrganizationModule } from "../organization";
import type { defineModule as defineItemManagementModule } from "../item-management";
import { createWorkCenterType, type CreateWorkCenterTypeParams } from "./db/workCenter";
import { createRoutingType } from "./db/routing";
import { createRoutingOperationType } from "./db/routingOperation";
import { createBillOfMaterialType } from "./db/billOfMaterial";
import { createBillOfMaterialLineType } from "./db/billOfMaterialLine";
import { createProductionOrderType } from "./db/productionOrder";
import { createProductionOrderMaterialRequirementType } from "./db/productionOrderMaterialRequirement";
import { createProductionOrderBomSnapshotType } from "./db/productionOrderBomSnapshot";
import { createProductionOrderRoutingSnapshotType } from "./db/productionOrderRoutingSnapshot";
import { createProductionOrderCostBaselineType } from "./db/productionOrderCostBaseline";
import { createWorkOrderType } from "./db/workOrder";
import { createWorkOrderExecutionEventType } from "./db/workOrderExecutionEvent";
import { createManufacturingCostSummaryType } from "./db/manufacturingCostSummary";
import { createManufacturingCostLineType } from "./db/manufacturingCostLine";
import { createCostVarianceLineType } from "./db/costVarianceLine";
import { createManufacturingCostSettlementRecordType } from "./db/manufacturingCostSettlementRecord";
// Commands
import { createWorkCenter } from "./command/createWorkCenter.generated";
import { updateWorkCenter } from "./command/updateWorkCenter.generated";
import { activateWorkCenter } from "./command/activateWorkCenter.generated";
import { deactivateWorkCenter } from "./command/deactivateWorkCenter.generated";
import { createRouting } from "./command/createRouting.generated";
import { updateRouting } from "./command/updateRouting.generated";
import { activateRouting } from "./command/activateRouting.generated";
import { deactivateRouting } from "./command/deactivateRouting.generated";
import { createBillOfMaterial } from "./command/createBillOfMaterial.generated";
import { updateBillOfMaterial } from "./command/updateBillOfMaterial.generated";
import { activateBillOfMaterial } from "./command/activateBillOfMaterial.generated";
import { deactivateBillOfMaterial } from "./command/deactivateBillOfMaterial.generated";
import { createProductionOrder } from "./command/createProductionOrder.generated";
import { updateProductionOrder } from "./command/updateProductionOrder.generated";
import { releaseProductionOrder } from "./command/releaseProductionOrder.generated";
import { unreleaseProductionOrder } from "./command/unreleaseProductionOrder.generated";
import { rescheduleProductionOrder } from "./command/rescheduleProductionOrder.generated";
import { cancelProductionOrder } from "./command/cancelProductionOrder.generated";
import { reopenProductionOrder } from "./command/reopenProductionOrder.generated";
import { completeProductionOrder } from "./command/completeProductionOrder.generated";
import { technicallyCompleteProductionOrder } from "./command/technicallyCompleteProductionOrder.generated";
import { closeProductionOrder } from "./command/closeProductionOrder.generated";
import { startWorkOrder } from "./command/startWorkOrder.generated";
import { pauseWorkOrder } from "./command/pauseWorkOrder.generated";
import { resumeWorkOrder } from "./command/resumeWorkOrder.generated";
import { completeWorkOrder } from "./command/completeWorkOrder.generated";
import { reportWorkOrderProgress } from "./command/reportWorkOrderProgress.generated";
import { recordInventoryIssueOutcome } from "./command/recordInventoryIssueOutcome.generated";
import { reviewManufacturingCostSummary } from "./command/reviewManufacturingCostSummary.generated";
import { recordManufacturingCostSettlementAcknowledgment } from "./command/recordManufacturingCostSettlementAcknowledgment.generated";
// Queries
import { getWorkCenter } from "./query/getWorkCenter.generated";
import { listWorkCentersBySite } from "./query/listWorkCentersBySite.generated";
import { getRouting } from "./query/getRouting.generated";
import { listRoutingsByItem } from "./query/listRoutingsByItem.generated";
import { getBillOfMaterial } from "./query/getBillOfMaterial.generated";
import { listBillOfMaterialsByItem } from "./query/listBillOfMaterialsByItem.generated";
import { detectBillOfMaterialCircularReference } from "./query/detectBillOfMaterialCircularReference.generated";
import { explodeBillOfMaterial } from "./query/explodeBillOfMaterial.generated";
import { getProductionOrder } from "./query/getProductionOrder.generated";
import { listProductionOrdersByStatus } from "./query/listProductionOrdersByStatus.generated";
import { getWorkOrder } from "./query/getWorkOrder.generated";
import { listWorkOrdersByProductionOrder } from "./query/listWorkOrdersByProductionOrder.generated";
import { listWorkOrdersByWorkCenter } from "./query/listWorkOrdersByWorkCenter.generated";
import { getManufacturingCostSummary } from "./query/getManufacturingCostSummary.generated";
import { listManufacturingCostSummariesByStatus } from "./query/listManufacturingCostSummariesByStatus.generated";
import { type EmptyFields, type FieldsToInsertable } from "@tailor-platform/erp-kit/module";

type OrganizationModule = ReturnType<typeof defineOrganizationModule>;
type OrganizationDB = OrganizationModule["db"];

type ItemManagementModule = ReturnType<typeof defineItemManagementModule>;
type ItemManagementDB = ItemManagementModule["db"];

export interface DefineModuleParams<WCF extends Record<string, TailorAnyDBField>> {
  workCenter?: Omit<CreateWorkCenterTypeParams<WCF>, "companyType" | "siteType">;
  organization: {
    db: { company: OrganizationDB["company"]; site: OrganizationDB["site"] };
  };
  itemManagement: {
    db: { item: ItemManagementDB["item"] };
  };
}

/* @__NO_SIDE_EFFECTS__ */
export const defineModule = <const WCF extends Record<string, TailorAnyDBField> = EmptyFields>(
  params: DefineModuleParams<WCF>,
) => {
  const companyType = params.organization.db.company;
  const siteType = params.organization.db.site;
  const itemType = params.itemManagement.db.item;

  // Master data
  const workCenter = createWorkCenterType({
    ...params.workCenter,
    companyType,
    siteType,
  });
  const routing = createRoutingType({ companyType, siteType, itemType });
  const routingOperation = createRoutingOperationType({
    routingType: routing,
    workCenterType: workCenter,
  });
  const billOfMaterial = createBillOfMaterialType({
    companyType,
    siteType,
    itemType,
  });
  const billOfMaterialLine = createBillOfMaterialLineType({
    billOfMaterialType: billOfMaterial,
    itemType,
  });

  // Production orders
  const productionOrder = createProductionOrderType({
    companyType,
    siteType,
    itemType,
  });
  const productionOrderMaterialRequirement = createProductionOrderMaterialRequirementType({
    productionOrderType: productionOrder,
    itemType,
  });
  const productionOrderBomSnapshot = createProductionOrderBomSnapshotType({
    productionOrderType: productionOrder,
  });
  const productionOrderRoutingSnapshot = createProductionOrderRoutingSnapshotType({
    productionOrderType: productionOrder,
  });
  const productionOrderCostBaseline = createProductionOrderCostBaselineType({
    productionOrderType: productionOrder,
  });

  // Work orders
  const workOrder = createWorkOrderType({
    productionOrderType: productionOrder,
    workCenterType: workCenter,
  });
  const workOrderExecutionEvent = createWorkOrderExecutionEventType({
    workOrderType: workOrder,
  });

  // Cost management
  const manufacturingCostSummary = createManufacturingCostSummaryType({
    productionOrderType: productionOrder,
  });
  const manufacturingCostLine = createManufacturingCostLineType({
    costSummaryType: manufacturingCostSummary,
  });
  const costVarianceLine = createCostVarianceLineType({
    costSummaryType: manufacturingCostSummary,
  });
  const manufacturingCostSettlementRecord = createManufacturingCostSettlementRecordType({
    costSummaryType: manufacturingCostSummary,
  });

  return {
    db: {
      workCenter,
      routing,
      routingOperation,
      billOfMaterial,
      billOfMaterialLine,
      productionOrder,
      productionOrderMaterialRequirement,
      productionOrderBomSnapshot,
      productionOrderRoutingSnapshot,
      productionOrderCostBaseline,
      workOrder,
      workOrderExecutionEvent,
      manufacturingCostSummary,
      manufacturingCostLine,
      costVarianceLine,
      manufacturingCostSettlementRecord,
    },
    queries: {
      getWorkCenter,
      listWorkCentersBySite,
      getRouting,
      listRoutingsByItem,
      getBillOfMaterial,
      listBillOfMaterialsByItem,
      detectBillOfMaterialCircularReference,
      explodeBillOfMaterial,
      getProductionOrder,
      listProductionOrdersByStatus,
      getWorkOrder,
      listWorkOrdersByProductionOrder,
      listWorkOrdersByWorkCenter,
      getManufacturingCostSummary,
      listManufacturingCostSummariesByStatus,
    },
    commands: {
      createWorkCenter: createWorkCenter<FieldsToInsertable<WCF>>(),
      updateWorkCenter: updateWorkCenter(),
      activateWorkCenter: activateWorkCenter(),
      deactivateWorkCenter: deactivateWorkCenter(),
      createRouting: createRouting(),
      updateRouting: updateRouting(),
      activateRouting: activateRouting(),
      deactivateRouting: deactivateRouting(),
      createBillOfMaterial: createBillOfMaterial(),
      updateBillOfMaterial: updateBillOfMaterial(),
      activateBillOfMaterial: activateBillOfMaterial(),
      deactivateBillOfMaterial: deactivateBillOfMaterial(),
      createProductionOrder: createProductionOrder(),
      updateProductionOrder: updateProductionOrder(),
      releaseProductionOrder: releaseProductionOrder(),
      unreleaseProductionOrder: unreleaseProductionOrder(),
      rescheduleProductionOrder: rescheduleProductionOrder(),
      cancelProductionOrder: cancelProductionOrder(),
      reopenProductionOrder: reopenProductionOrder(),
      completeProductionOrder: completeProductionOrder(),
      technicallyCompleteProductionOrder: technicallyCompleteProductionOrder(),
      closeProductionOrder: closeProductionOrder(),
      startWorkOrder: startWorkOrder(),
      pauseWorkOrder: pauseWorkOrder(),
      resumeWorkOrder: resumeWorkOrder(),
      completeWorkOrder: completeWorkOrder(),
      reportWorkOrderProgress: reportWorkOrderProgress(),
      recordInventoryIssueOutcome: recordInventoryIssueOutcome(),
      reviewManufacturingCostSummary: reviewManufacturingCostSummary(),
      recordManufacturingCostSettlementAcknowledgment:
        recordManufacturingCostSettlementAcknowledgment(),
    },
  };
};
