import { type EmptyFields, type FieldsToInsertable } from "@tailor-platform/erp-kit/core";
import { type TailorAnyDBField } from "@tailor-platform/sdk";
import type { defineModule as defineItemManagementModule } from "../item-management";
import type { defineModule as defineOrganizationModule } from "../organization";
import { assignSerialNumber } from "./command/assignSerialNumber.generated";
import { cancelStockAdjustment } from "./command/cancelStockAdjustment.generated";
import { confirmStockAdjustment } from "./command/confirmStockAdjustment.generated";
import { createLot } from "./command/createLot.generated";
import { createStockAdjustment } from "./command/createStockAdjustment.generated";
import { createStorageLocation } from "./command/createStorageLocation.generated";
import { createValuationPolicy } from "./command/createValuationPolicy.generated";
import { deactivateStorageLocation } from "./command/deactivateStorageLocation.generated";
import { issueStock } from "./command/issueStock.generated";
import { reactivateStorageLocation } from "./command/reactivateStorageLocation.generated";
import { receiveStock } from "./command/receiveStock.generated";
import { receiveStockWithInspection } from "./command/receiveStockWithInspection.generated";
import { rejectStockAdjustment } from "./command/rejectStockAdjustment.generated";
import { releaseReservation } from "./command/releaseReservation.generated";
import { reserveStock } from "./command/reserveStock.generated";
import { submitStockAdjustment } from "./command/submitStockAdjustment.generated";
import { updateLot } from "./command/updateLot.generated";
import { updateStockAdjustment } from "./command/updateStockAdjustment.generated";
import { updateStorageLocation } from "./command/updateStorageLocation.generated";
import { updateValuationPolicy } from "./command/updateValuationPolicy.generated";
import { createCostLayerType } from "./db/costLayer";
import { createInventoryLedgerType } from "./db/inventoryLedger";
import { createItemValuationType } from "./db/itemValuation";
import { createLotType } from "./db/lot";
import { createLotStockLevelType } from "./db/lotStockLevel";
import { createSerialNumberType } from "./db/serialNumber";
import { createStockAdjustmentType } from "./db/stockAdjustment";
import { createStockAdjustmentLineType } from "./db/stockAdjustmentLine";
import { createStockLevelType } from "./db/stockLevel";
import {
  createStorageLocationType,
  type CreateStorageLocationTypeParams,
} from "./db/storageLocation";
import { createValuationPolicyType } from "./db/valuationPolicy";
import { getItemValuation } from "./query/getItemValuation.generated";
import { getLot } from "./query/getLot.generated";
import { getSerialNumber } from "./query/getSerialNumber.generated";
import { getSerialNumberHistory } from "./query/getSerialNumberHistory.generated";
import { getSiteStockSummary } from "./query/getSiteStockSummary.generated";
import { getStockAdjustment } from "./query/getStockAdjustment.generated";
import { getStockLevel } from "./query/getStockLevel.generated";
import { getStorageLocation } from "./query/getStorageLocation.generated";
import { getValuationPolicy } from "./query/getValuationPolicy.generated";
import { listCostLayers } from "./query/listCostLayers.generated";
import { listExpiringLots } from "./query/listExpiringLots.generated";
import { listItemValuations } from "./query/listItemValuations.generated";
import { listLots } from "./query/listLots.generated";
import { listSerialNumbers } from "./query/listSerialNumbers.generated";
import { listStockAdjustments } from "./query/listStockAdjustments.generated";
import { listStockLevels } from "./query/listStockLevels.generated";
import { listStorageLocations } from "./query/listStorageLocations.generated";
import { listValuationPolicies } from "./query/listValuationPolicies.generated";
import { traceLotBackward } from "./query/traceLotBackward.generated";
import { traceLotForward } from "./query/traceLotForward.generated";

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<SF extends Record<string, TailorAnyDBField>> {
  storageLocation?: Omit<CreateStorageLocationTypeParams<SF>, "siteType">;
  organization: {
    db: { site: OrganizationDB["site"] };
    queries: { getSite: OrganizationQueries["getSite"] };
  };
  itemManagement: {
    queries: { getItem: ItemManagementQueries["getItem"] };
  };
}

/* @__NO_SIDE_EFFECTS__ */
export const defineModule = <const SF extends Record<string, TailorAnyDBField> = EmptyFields>(
  params: DefineModuleParams<SF>,
) => {
  const storageLocation = createStorageLocationType({
    ...params.storageLocation,
    siteType: params.organization.db.site,
  });
  const valuationPolicy = createValuationPolicyType({});
  const stockLevel = createStockLevelType({});
  const stockAdjustment = createStockAdjustmentType({});
  const stockAdjustmentLine = createStockAdjustmentLineType({});
  const inventoryLedger = createInventoryLedgerType({});
  const lot = createLotType({});
  const lotStockLevel = createLotStockLevelType({});
  const serialNumber = createSerialNumberType({});
  const itemValuation = createItemValuationType({});
  const costLayer = createCostLayerType({});

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

  return {
    db: {
      storageLocation,
      valuationPolicy,
      stockLevel,
      stockAdjustment,
      stockAdjustmentLine,
      inventoryLedger,
      lot,
      lotStockLevel,
      serialNumber,
      itemValuation,
      costLayer,
    },
    queries: {
      getStorageLocation,
      getValuationPolicy,
      getStockLevel,
      getStockAdjustment,
      getLot,
      getSerialNumber,
      getSerialNumberHistory,
      getItemValuation,
      getSiteStockSummary,
      listStorageLocations,
      listValuationPolicies,
      listStockLevels,
      listStockAdjustments,
      listLots,
      listSerialNumbers,
      listItemValuations,
      listCostLayers,
      listExpiringLots,
      traceLotForward,
      traceLotBackward,
    },
    commands: {
      createStorageLocation: createStorageLocation<FieldsToInsertable<SF>>(orgQueries),
      updateStorageLocation: updateStorageLocation(),
      deactivateStorageLocation: deactivateStorageLocation(),
      reactivateStorageLocation: reactivateStorageLocation(orgQueries),
      createValuationPolicy: createValuationPolicy(),
      updateValuationPolicy: updateValuationPolicy(),
      createLot: createLot(itemQueries),
      updateLot: updateLot(),
      assignSerialNumber: assignSerialNumber(itemQueries),
      receiveStock: receiveStock(itemQueries),
      receiveStockWithInspection: receiveStockWithInspection(itemQueries),
      issueStock: issueStock(itemQueries),
      createStockAdjustment: createStockAdjustment(itemQueries),
      updateStockAdjustment: updateStockAdjustment(itemQueries),
      submitStockAdjustment: submitStockAdjustment(),
      confirmStockAdjustment: confirmStockAdjustment(),
      rejectStockAdjustment: rejectStockAdjustment(),
      cancelStockAdjustment: cancelStockAdjustment(),
      reserveStock: reserveStock(itemQueries),
      releaseReservation: releaseReservation(),
    },
  };
};
