export type SkuDefinition = {
  id: string;
  name: string;
  category: string;
  shelfLifeHours: number;
  unitCost: number;
  unitPrice: number;
  minOrder: number;
};

export type DemandWindows = {
  pickupMorning: number[];
  highDemandMorning: number[];
  highDemandLunch: number[];
  slowAfternoon: number[];
  evening: number[];
};

export type BusinessHours = {
  open: number;
  close: number;
};

export type InventoryEnvConfig = {
  skus: SkuDefinition[];
  businessHours: BusinessHours;
  demandWindows: DemandWindows;
  capacity: number;
  maxOrderPerSku: number;
  maxStepsPerEpisode: number;
  wasteRatePerHour: number;
  stockoutPenaltyMultiplier: number;
  targetServiceLevel: number;
  serviceShortfallPenaltyMultiplier: number;
  laborCostPerUnit: number;
  holdingCostPerUnit: number;
};

export type EnvironmentContext = {
  hour: number;
  weekday: number;
  isWeekend: boolean;
  isHoliday: boolean;
  temp: number;
  precip: number;
  sales7d: number[];
  lost7d: number[];
  waste7d: number[];
  capacity: number;
};

export type InventoryObservation = number[];

export type InventoryAction = number[];

export type InventoryState = {
  inventory: number[];
  context: EnvironmentContext;
  stepCount: number;
};

export type InventoryStepInfo = {
  sales: number[];
  waste: number[];
  lostSales: number[];
  order: number[];
  demand: number[];
  inventoryStart: number[];
  inventoryAfterOrder: number[];
  inventoryEnd: number[];
  margin: number;
  stockoutPenalty: number;
  servicePenalty: number;
  understockRiskPenalty: number;
  laborCost: number;
  holdingCost: number;
  event: "step" | "terminated" | "truncated";
};

export type ResetOptions = Partial<EnvironmentContext> & {
  inventory?: number[];
  seed?: number;
};

export type InventoryDatasetRow = {
  outletId: number;
  date: string;
  hour: number;
  skuId: string;
  demand: number;
  sales: number;
  inventoryStartOfHour: number;
  inventoryEndOfHour?: number;
  lostSales: number;
  isWeekend: boolean;
  isHoliday: boolean;
  temp: number;
  precip: number;
  weekday?: number;
  isPickupHour?: boolean;
  isHighDemandHour?: boolean;
  isSlowHour?: boolean;
  capacity?: number;
  orderQty?: number;
};

export type TrainingSample = {
  state: number[];
  action: number[];
  weight: number;
  meta: {
    outletId: number;
    date: string;
    hour?: number;
  };
};

export type TrainingTransition = {
  state: number[];
  action: number[];
  reward: number;
  nextState: number[];
  done: boolean;
  weight: number;
  meta: {
    outletId: number;
    date: string;
    hour: number;
  };
};

export type ValidationError = {
  row: number;
  field: string;
  message: string;
};

export type ValidationResult = {
  valid: boolean;
  errors: ValidationError[];
  warnings: string[];
};

export type TrainerOptions = {
  epochs: number;
  batchSize: number;
  learningRate: number;
  maxOrderPerSku: number;
  loss: "huber" | "mse";
  seed: number;
  l2: number;
  earlyStoppingPatience?: number;
  earlyStoppingMinDelta?: number;
};

export type TrainingEpochMetric = {
  epoch: number;
  loss: number;
  phase?: "bc" | "dqn" | "bcq_q" | "bcq_behavior" | "ddpg_critic" | "ddpg_actor";
};

export type ExpertPolicyEvaluation = {
  steps: number;
  days: number;
  totalReward: number;
  expectedStepReward: number;
  expectedDayReward: number;
  dayRewards: number[];
};

export type SerializedMlpPolicyWeight = {
  shape: number[];
  data: number[];
};

export type SerializedMlpPolicy = {
  modelType: "mlp_tfjs";
  stateDim: number;
  actionDim: number;
  maxOrderPerSku: number;
  hidden: number[];
  weights: SerializedMlpPolicyWeight[];
  skuIds: string[];
  createdAt: string;
};

export type SerializedBcqPolicy = {
  modelType: "bcq_tfjs";
  stateDim: number;
  actionDim: number;
  maxOrderPerSku: number;
  skuIds: string[];
  behaviorThreshold: number;
  actionBank: number[][];
  qHidden: number[];
  behaviorHidden: number[];
  qWeights: SerializedMlpPolicyWeight[];
  behaviorWeights: SerializedMlpPolicyWeight[];
  createdAt: string;
};

export type SerializedDdpgPolicy = {
  modelType: "ddpg_tfjs";
  stateDim: number;
  actionDim: number;
  maxOrderPerSku: number;
  skuIds: string[];
  actorHidden: number[];
  actorWeights: SerializedMlpPolicyWeight[];
  createdAt: string;
};

export type SerializedInventoryPolicy = SerializedMlpPolicy | SerializedBcqPolicy | SerializedDdpgPolicy;

// Backward-compatible alias for old name.
export type SerializedLinearPolicy = SerializedMlpPolicy;
