import { type TailorAnyDBField } from "@tailor-platform/sdk";
import type { defineModule as defineOrganizationModule } from "../organization";
import type { defineModule as defineItemManagementModule } from "../item-management";
import { createWarehouseType, type CreateWarehouseTypeParams } from "./db/warehouse";
import { createStorageLocationType } from "./db/storageLocation";
import { createValuationPolicyType } from "./db/valuationPolicy";
import { createStockLevelType } from "./db/stockLevel";
import { createStockMovementType } from "./db/stockMovement";
import { createStockMoveLineType } from "./db/stockMoveLine";
import { createLotType } from "./db/lot";
import { createLotStockLevelType } from "./db/lotStockLevel";
import { createSerialNumberType } from "./db/serialNumber";
import { createInventoryCountType } from "./db/inventoryCount";
import { createInventoryCountLineType } from "./db/inventoryCountLine";
import { createInventoryAdjustmentType } from "./db/inventoryAdjustment";
import { createItemValuationType } from "./db/itemValuation";
import { createCostLayerType } from "./db/costLayer";
import { createWarehouse } from "./command/createWarehouse.generated";
import { updateWarehouse } from "./command/updateWarehouse.generated";
import { deactivateWarehouse } from "./command/deactivateWarehouse.generated";
import { reactivateWarehouse } from "./command/reactivateWarehouse.generated";
import { createStorageLocation } from "./command/createStorageLocation.generated";
import { updateStorageLocation } from "./command/updateStorageLocation.generated";
import { deactivateStorageLocation } from "./command/deactivateStorageLocation.generated";
import { reactivateStorageLocation } from "./command/reactivateStorageLocation.generated";
import { createValuationPolicy } from "./command/createValuationPolicy.generated";
import { updateValuationPolicy } from "./command/updateValuationPolicy.generated";
import { createLot } from "./command/createLot.generated";
import { updateLot } from "./command/updateLot.generated";
import { assignSerialNumber } from "./command/assignSerialNumber.generated";
import { createStockMovement } from "./command/createStockMovement.generated";
import { updateStockMovement } from "./command/updateStockMovement.generated";
import { confirmStockMovement } from "./command/confirmStockMovement.generated";
import { executeStockMovement } from "./command/executeStockMovement.generated";
import { cancelStockMovement } from "./command/cancelStockMovement.generated";
import { reserveStock } from "./command/reserveStock.generated";
import { releaseReservation } from "./command/releaseReservation.generated";
import { createInventoryCount } from "./command/createInventoryCount.generated";
import { startInventoryCount } from "./command/startInventoryCount.generated";
import { recordCountLine } from "./command/recordCountLine.generated";
import { approveCountLine } from "./command/approveCountLine.generated";
import { rejectCountLine } from "./command/rejectCountLine.generated";
import { completeInventoryCount } from "./command/completeInventoryCount.generated";
import { cancelInventoryCount } from "./command/cancelInventoryCount.generated";
import { createInventoryAdjustment } from "./command/createInventoryAdjustment.generated";
import { submitInventoryAdjustment } from "./command/submitInventoryAdjustment.generated";
import { approveInventoryAdjustment } from "./command/approveInventoryAdjustment.generated";
import { rejectInventoryAdjustment } from "./command/rejectInventoryAdjustment.generated";
import { reviseInventoryAdjustment } from "./command/reviseInventoryAdjustment.generated";
import { confirmInventoryAdjustment } from "./command/confirmInventoryAdjustment.generated";
import { getWarehouse } from "./query/getWarehouse.generated";
import { getStorageLocation } from "./query/getStorageLocation.generated";
import { getValuationPolicy } from "./query/getValuationPolicy.generated";
import { getStockLevel } from "./query/getStockLevel.generated";
import { getStockMovement } from "./query/getStockMovement.generated";
import { getLot } from "./query/getLot.generated";
import { getSerialNumber } from "./query/getSerialNumber.generated";
import { getSerialNumberHistory } from "./query/getSerialNumberHistory.generated";
import { getInventoryCount } from "./query/getInventoryCount.generated";
import { getInventoryAdjustment } from "./query/getInventoryAdjustment.generated";
import { getItemValuation } from "./query/getItemValuation.generated";
import { getWarehouseStockSummary } from "./query/getWarehouseStockSummary.generated";
import { listWarehouses } from "./query/listWarehouses.generated";
import { listStorageLocations } from "./query/listStorageLocations.generated";
import { listValuationPolicies } from "./query/listValuationPolicies.generated";
import { listStockLevels } from "./query/listStockLevels.generated";
import { listStockMovements } from "./query/listStockMovements.generated";
import { listLots } from "./query/listLots.generated";
import { listSerialNumbers } from "./query/listSerialNumbers.generated";
import { listInventoryCounts } from "./query/listInventoryCounts.generated";
import { listInventoryAdjustments } from "./query/listInventoryAdjustments.generated";
import { listItemValuations } from "./query/listItemValuations.generated";
import { listCostLayers } from "./query/listCostLayers.generated";
import { listExpiringLots } from "./query/listExpiringLots.generated";
import { traceLotForward } from "./query/traceLotForward.generated";
import { traceLotBackward } from "./query/traceLotBackward.generated";
import { type EmptyFields, type FieldsToInsertable } from "@tailor-platform/erp-kit/module";

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

type ItemManagementModule = ReturnType<typeof defineItemManagementModule>;
type ItemManagementQueries = ItemManagementModule["queries"];

export interface DefineModuleParams<WF extends Record<string, TailorAnyDBField>> {
  warehouse?: Omit<CreateWarehouseTypeParams<WF>, "siteType">;
  organization: {
    db: { site: OrganizationDB["site"] };
    queries: { getSite: OrganizationQueries["getSite"] };
  };
  itemManagement: {
    queries: { getItem: ItemManagementQueries["getItem"] };
  };
}

/* @__NO_SIDE_EFFECTS__ */
export const defineModule = <const WF extends Record<string, TailorAnyDBField> = EmptyFields>(
  params: DefineModuleParams<WF>,
) => {
  const warehouse = createWarehouseType({
    ...params.warehouse,
    siteType: params.organization.db.site,
  });
  const storageLocation = createStorageLocationType({});
  const valuationPolicy = createValuationPolicyType({});
  const stockLevel = createStockLevelType({});
  const stockMovement = createStockMovementType({});
  const stockMoveLine = createStockMoveLineType({});
  const lot = createLotType({});
  const lotStockLevel = createLotStockLevelType({});
  const serialNumber = createSerialNumberType({});
  const inventoryCount = createInventoryCountType({});
  const inventoryCountLine = createInventoryCountLineType({});
  const inventoryAdjustment = createInventoryAdjustmentType({});
  const itemValuation = createItemValuationType({});
  const costLayer = createCostLayerType({});

  const orgQueries = params.organization.queries;
  const itemQueries = params.itemManagement.queries;

  return {
    db: {
      warehouse,
      storageLocation,
      valuationPolicy,
      stockLevel,
      stockMovement,
      stockMoveLine,
      lot,
      lotStockLevel,
      serialNumber,
      inventoryCount,
      inventoryCountLine,
      inventoryAdjustment,
      itemValuation,
      costLayer,
    },
    queries: {
      getWarehouse,
      getStorageLocation,
      getValuationPolicy,
      getStockLevel,
      getStockMovement,
      getLot,
      getSerialNumber,
      getSerialNumberHistory,
      getInventoryCount,
      getInventoryAdjustment,
      getItemValuation,
      getWarehouseStockSummary,
      listWarehouses,
      listStorageLocations,
      listValuationPolicies,
      listStockLevels,
      listStockMovements,
      listLots,
      listSerialNumbers,
      listInventoryCounts,
      listInventoryAdjustments,
      listItemValuations,
      listCostLayers,
      listExpiringLots,
      traceLotForward,
      traceLotBackward,
    },
    commands: {
      createWarehouse: createWarehouse<FieldsToInsertable<WF>>(orgQueries),
      updateWarehouse: updateWarehouse(),
      deactivateWarehouse: deactivateWarehouse(),
      reactivateWarehouse: reactivateWarehouse(orgQueries),
      createStorageLocation: createStorageLocation(),
      updateStorageLocation: updateStorageLocation(),
      deactivateStorageLocation: deactivateStorageLocation(),
      reactivateStorageLocation: reactivateStorageLocation(),
      createValuationPolicy: createValuationPolicy(),
      updateValuationPolicy: updateValuationPolicy(),
      createLot: createLot(itemQueries),
      updateLot: updateLot(),
      assignSerialNumber: assignSerialNumber(itemQueries),
      createStockMovement: createStockMovement(itemQueries),
      updateStockMovement: updateStockMovement(itemQueries),
      confirmStockMovement: confirmStockMovement(itemQueries),
      executeStockMovement: executeStockMovement(),
      cancelStockMovement: cancelStockMovement(),
      reserveStock: reserveStock(itemQueries),
      releaseReservation: releaseReservation(),
      createInventoryCount: createInventoryCount(),
      startInventoryCount: startInventoryCount(),
      recordCountLine: recordCountLine(),
      approveCountLine: approveCountLine(),
      rejectCountLine: rejectCountLine(),
      completeInventoryCount: completeInventoryCount(),
      cancelInventoryCount: cancelInventoryCount(),
      createInventoryAdjustment: createInventoryAdjustment(itemQueries),
      submitInventoryAdjustment: submitInventoryAdjustment(),
      approveInventoryAdjustment: approveInventoryAdjustment(),
      rejectInventoryAdjustment: rejectInventoryAdjustment(),
      reviseInventoryAdjustment: reviseInventoryAdjustment(),
      confirmInventoryAdjustment: confirmInventoryAdjustment(),
    },
  };
};
