// Stock Management types (docs/11-BACKEND-PHASE1.md §5; FR-STK-01..14, FR-WH-*).
// Mirrors the live backend DTOs. The list endpoints (GET /stock-transfers,
// /stock-adjustments, /stock-counts, /stock/on-hand/list) all exist as of 2026-07-16.
import { Requisition } from "@/types/procurement"

export type Currency = "LKR"

// --- 5.1 On-hand ----------------------------------------------------------------

export interface OnHand {
  itemId: number
  warehouseId: number
  onHand: number
  available: number
  onHold: number
  /** Reported for visibility only — dispatch already removed it from onHand, so it is
   *  NOT subtracted again from available (docs/10 C.9). */
  inTransit: number
  /** Always 0 in Phase 1 (sales reservation stub, FR-STK-11). */
  reserved: number
  asOf: string
}

// --- 5.2 Ledger -------------------------------------------------------------------

export type LedgerDirection = "In" | "Out"

export interface LedgerEntry {
  ledgerId: number
  itemId: number
  warehouseId: number
  binId: number | null
  batchId: number | null
  serialId: number | null
  direction: LedgerDirection
  qtyBase: number
  unitCost: number
  value: number
  runningBalance: number
  sourceDocType: string
  sourceDocId: number
  userId: number
  createdAt: string
}

// --- 5.3 Valuation ------------------------------------------------------------------

export interface ValuationLayer {
  layerId: number
  qtyRemaining: number
  unitCost: number
  value: number
  receiptDate: string
}

export interface Valuation {
  itemId: number
  warehouseId: number
  layers: ValuationLayer[]
  totalQty: number
  totalValue: number
  currency: Currency
  costingMethod: "FIFO"
}

// --- 5.4 Transfers ------------------------------------------------------------------

export type TransferStatus = "Draft" | "InTransit" | "Received" | "Closed"

export interface TransferLine {
  transferLineId: number
  itemId: number
  srcBinId: number | null
  destBinId: number | null
  batchId: number | null
  qty: number
  /** Accrues on partial receive; qty - qtyReceived is what is still in transit. */
  qtyReceived: number
}

export interface StockTransfer {
  transferId: number
  docNo: string
  srcWarehouseId: number
  destWarehouseId: number
  status: TransferStatus
  createdBy: number
  createdAt: string
  lines: TransferLine[]
}

export interface StockTransferSummary {
  transferId: number
  docNo: string
  srcWarehouseId: number
  destWarehouseId: number
  status: TransferStatus
  createdBy: number
  createdAt: string
  lineCount: number
}

export interface CreateTransferLineInput {
  itemId: number
  srcBinId?: number | null
  destBinId?: number | null
  batchId?: number | null
  qty: number
}

export interface CreateTransferRequest {
  srcWarehouseId: number
  destWarehouseId: number
  lines: CreateTransferLineInput[]
}

export interface ConsumedLayer {
  layerId: number
  qtyConsumed: number
  unitCost: number
}

export interface DispatchTransferResponse {
  transferId: number
  status: TransferStatus
  consumedLayers: ConsumedLayer[]
  ledgerRefs: number[]
}

export interface ReceiveTransferLineInput {
  transferLineId: number
  qty: number
}

export interface ReceiveTransferRequest {
  lines: ReceiveTransferLineInput[]
}

export interface CreatedTransferLayer {
  layerId: number
  warehouseId: number
  qtyReceived: number
  unitCost: number
}

export interface ReceiveTransferResponse {
  transferId: number
  status: TransferStatus
  createdLayers: CreatedTransferLayer[]
  ledgerRefs: number[]
}

// --- 5.5 Adjustments ------------------------------------------------------------------

/** Phase 1 auto-posts, so `Posted` is what you see; the other two exist for the deferred
 *  approval workflow (FR-STK-07) and are in the server enum. */
export type AdjustmentStatus = "Draft" | "PendingApproval" | "Posted"

export interface AdjustmentLine {
  adjLineId: number
  itemId: number
  binId: number | null
  batchId: number | null
  /** Signed: negative FIFO-consumes, positive creates a layer. */
  qtyDelta: number
}

export interface StockAdjustment {
  adjustmentId: number
  docNo: string
  warehouseId: number
  reasonCodeId: number
  status: AdjustmentStatus
  createdBy: number
  createdAt: string
  glJournalNo: string | null
  glPostedAt: string | null
  lines: AdjustmentLine[]
  ledgerRefs: number[]
}

export interface StockAdjustmentSummary {
  adjustmentId: number
  docNo: string
  warehouseId: number
  reasonCodeId: number
  status: AdjustmentStatus
  createdBy: number
  createdAt: string
  lineCount: number
  glJournalNo: string | null
}

export interface CreateAdjustmentLineInput {
  itemId: number
  binId?: number | null
  batchId?: number | null
  qtyDelta: number
}

export interface CreateAdjustmentRequest {
  warehouseId: number
  /** Mandatory (FR-STK-07); omitting it returns 400 REASON_CODE_REQUIRED. */
  reasonCodeId: number
  lines: CreateAdjustmentLineInput[]
}

// --- 5.6 Counts ------------------------------------------------------------------

export type CountType = "Cycle" | "Full"
export type CountStatus = "Draft" | "Counted" | "Posted"

export interface CountLine {
  countLineId: number
  itemId: number
  binId: number | null
  systemQty: number
  countedQty: number | null
  variance: number | null
}

export interface StockCount {
  countId: number
  docNo: string
  warehouseId: number
  countType: CountType
  status: CountStatus
  createdBy: number
  createdAt: string
  lines: CountLine[]
}

export interface StockCountSummary {
  countId: number
  docNo: string
  warehouseId: number
  countType: CountType
  status: CountStatus
  createdBy: number
  createdAt: string
  lineCount: number
}

export interface CreateCountRequest {
  warehouseId: number
  countType: CountType
  itemIds: number[]
}

export interface EnterCountLineInput {
  countLineId: number
  countedQty: number
}

export interface EnterCountsRequest {
  lines: EnterCountLineInput[]
}

export interface PostCountResponse {
  countId: number
  status: CountStatus
  /** Null when the count had no variance to post. */
  adjustmentId: number | null
  /** Null when there was no variance, or the variance's value was 0 either way. */
  glJournalNo: string | null
  ledgerRefs: number[]
}

// --- 5.7 Reorder alerts ------------------------------------------------------------------

export interface ReorderAlert {
  itemId: number
  warehouseId: number
  available: number
  reorderPoint: number
  reorderQty: number
  suggestedRequisitionQty: number
}

/** POST /stock/reorder-alerts/{itemId}/requisition returns a full Requisition. */
export type ReorderRequisitionResponse = Requisition

// --- §6 Reference data ------------------------------------------------------------------

/** Server enum is Adjustment | Return | Count (docs/11 §6). */
/** `Production` was added with Phase 2 (docs/30 §A.2) — scrap, leftover, cancel and rework loss. */
export type ReasonCodeContext = "Adjustment" | "Return" | "Count" | "Production"

export interface ReasonCode {
  reasonCodeId: number
  code: string
  description: string
  context: ReasonCodeContext
}
