// In-memory sample data backing every lib/api/*.ts module — the app has no
// fetch-based backend connection (lib/api-client.ts and lib/auth-token.ts were
// removed). Shapes mirror docs/11-BACKEND-PHASE1.md.
import { Bin, Brand, Category, Item, Uom, Vendor, VariantCategory, Warehouse } from "@/types/master-data"
import { PurchaseOrder, Quotation, Requisition, Rfq, PurchaseReturn } from "@/types/procurement"
import { Grn } from "@/types/grn"
import {
  AdjustmentStatus,
  CountStatus,
  CountType,
  LedgerDirection,
  LedgerEntry,
  ReasonCode,
  TransferStatus,
} from "@/types/stock"

export const mockWarehouses: Warehouse[] = [
  { warehouseId: 1, code: "WH-MAIN", name: "Main Warehouse - Negombo" },
  { warehouseId: 2, code: "WH-COLOMBO", name: "Colombo Distribution Center" },
]

export const mockBins: Bin[] = [
  { binId: 1, warehouseId: 1, code: "A-01-01", binType: "Shelf" },
  { binId: 2, warehouseId: 1, code: "A-01-02", binType: "Shelf" },
  { binId: 3, warehouseId: 1, code: "B-02-01", binType: "Pallet" },
  { binId: 4, warehouseId: 2, code: "C-01-01", binType: "Shelf" },
  { binId: 5, warehouseId: 2, code: "C-01-02", binType: "Shelf" },
]

let nextWarehouseId = 3
let nextBinId = 6

export function allocateWarehouseId() {
  return nextWarehouseId++
}

export function allocateBinId() {
  return nextBinId++
}

export const mockUoms: Uom[] = [
  { uomId: 1, name: "EA" },
  { uomId: 2, name: "Box-12" },
  { uomId: 3, name: "KG" },
]

let nextUomId = 4

export function allocateUomId() {
  return nextUomId++
}

export const mockCategories: Category[] = [
  { categoryId: 3, name: "Hardware", parentId: null, createdAt: "2026-06-01T08:00:00Z" },
  { categoryId: 12, name: "Fasteners", parentId: 3, createdAt: "2026-06-01T08:05:00Z" },
  { categoryId: 20, name: "Power Tools", parentId: null, createdAt: "2026-06-02T09:00:00Z" },
]

let nextCategoryId = 21

export function allocateCategoryId() {
  return nextCategoryId++
}

export const mockBrands: Brand[] = [
  { brandId: 1, name: "Bosch", createdAt: "2026-06-01T08:00:00Z" },
  { brandId: 2, name: "Makita", createdAt: "2026-06-02T09:00:00Z" },
]

let nextBrandId = 3

export function allocateBrandId() {
  return nextBrandId++
}

export const mockVariantCategories: VariantCategory[] = [
  { variantCategoryId: 1, name: "Color", createdAt: "2026-06-01T08:00:00Z" },
  { variantCategoryId: 2, name: "Size", createdAt: "2026-06-01T08:00:00Z" },
]

let nextVariantCategoryId = 3

export function allocateVariantCategoryId() {
  return nextVariantCategoryId++
}

export const mockVendors: Vendor[] = [
  {
    vendorId: 5,
    code: "VN-005",
    name: "Lanka Steel Traders (Pvt) Ltd",
    terms: "NET30",
    taxReg: "134567890-7000",
    currency: "LKR",
    status: "Active",
    createdAt: "2026-06-01T08:00:00Z",
    updatedAt: null,
  },
  {
    vendorId: 8,
    code: "VN-008",
    name: "Ceylon Hardware Supplies",
    terms: "NET45",
    taxReg: "198765432-1000",
    currency: "LKR",
    status: "Active",
    createdAt: "2026-06-05T08:00:00Z",
    updatedAt: null,
  },
]

// A handful more so the vendors list has something real to paginate/search through.
const extraVendorNames = [
  "Colombo Timber & Plywood Co.",
  "Kandy Electrical Distributors",
  "Galle Packaging Solutions",
  "Jaffna Agro Supplies",
  "Negombo Fasteners (Pvt) Ltd",
  "Kurunegala Paints & Coatings",
  "Trinco Marine Hardware",
  "Ratnapura Gems & Tools",
]
for (let i = 0; i < extraVendorNames.length; i++) {
  const vendorId = 9 + i
  mockVendors.push({
    vendorId,
    code: `VN-${String(vendorId).padStart(3, "0")}`,
    name: extraVendorNames[i],
    terms: i % 2 === 0 ? "NET30" : "NET60",
    taxReg: `1${String(10000000 + vendorId * 137)}-${7000 + i}`,
    currency: "LKR",
    status: i % 5 === 0 ? "Inactive" : "Active",
    createdAt: new Date(Date.UTC(2026, 6, 1 + i, 9, 0, 0)).toISOString(),
    updatedAt: null,
  })
}

let nextVendorId = 9 + extraVendorNames.length

export function allocateVendorId() {
  return nextVendorId++
}

// Concurrency token per vendor (stands in for the real backend's xmin/RowVersion
// ETag, docs/11 §1.6) — kept out-of-band since the public Vendor type has no
// version field of its own (it travels as an HTTP ETag header, not a body field).
const mockVendorVersions = new Map<number, number>(mockVendors.map((v) => [v.vendorId, 1]))

export function getVendorVersion(vendorId: number): number {
  return mockVendorVersions.get(vendorId) ?? 1
}

export function bumpVendorVersion(vendorId: number): number {
  const next = getVendorVersion(vendorId) + 1
  mockVendorVersions.set(vendorId, next)
  return next
}

export function initVendorVersion(vendorId: number) {
  mockVendorVersions.set(vendorId, 1)
}

// Full Item records (docs/11 §2.1). ItemListItem (the list/GRN-picker view) is
// derived from these in lib/api/items.ts, same "full record → mapped summary"
// pattern as mockPurchaseOrders → PurchaseOrderSummary.
export const mockItems: Item[] = [
  {
    itemId: 1001,
    sku: "ITM-1001",
    name: "Steel Bolt M8x40",
    description: "Grade 8.8 zinc-plated hex bolt",
    categoryId: 12,
    baseUomId: 1,
    defaultVendorId: 5,
    itemType: "Stocked",
    trackingMode: "Batch",
    taxClass: "STD",
    status: "Active",
    reorder: [{ warehouseId: 1, reorderPoint: 2500, reorderQty: 5000 }],
    conversions: [{ conversionId: 33, fromUom: 2, toUom: 1, factor: 12 }],
    createdAt: "2026-06-01T08:00:00Z",
    updatedAt: null,
  },
  {
    itemId: 1002,
    sku: "ITM-1002",
    name: "Steel Nut M8",
    description: "Grade 8 zinc-plated hex nut",
    categoryId: 12,
    baseUomId: 1,
    defaultVendorId: 5,
    itemType: "Stocked",
    trackingMode: "None",
    taxClass: "STD",
    status: "Active",
    reorder: [{ warehouseId: 1, reorderPoint: 5000, reorderQty: 8000 }],
    conversions: [],
    createdAt: "2026-06-01T08:05:00Z",
    updatedAt: null,
  },
  {
    itemId: 1003,
    sku: "ITM-1003",
    name: "Cordless Drill 18V",
    description: "18V lithium-ion cordless drill/driver, includes charger",
    categoryId: 20,
    baseUomId: 1,
    defaultVendorId: 8,
    itemType: "Stocked",
    trackingMode: "Serial",
    taxClass: "STD",
    status: "Active",
    reorder: [{ warehouseId: 2, reorderPoint: 15, reorderQty: 20 }],
    conversions: [],
    createdAt: "2026-06-05T08:10:00Z",
    updatedAt: null,
  },
]

let nextItemId = 1004

export function allocateItemId() {
  return nextItemId++
}

// Concurrency token per item (same out-of-band ETag pattern as mockVendorVersions).
const mockItemVersions = new Map<number, number>(mockItems.map((i) => [i.itemId, 1]))

export function getItemVersion(itemId: number): number {
  return mockItemVersions.get(itemId) ?? 1
}

export function bumpItemVersion(itemId: number): number {
  const next = getItemVersion(itemId) + 1
  mockItemVersions.set(itemId, next)
  return next
}

export function initItemVersion(itemId: number) {
  mockItemVersions.set(itemId, 1)
}

export const mockPurchaseOrders: PurchaseOrder[] = [
  {
    poId: 342,
    docNo: "PO-2026-00342",
    vendorId: 5,
    requisitionId: 210,
    status: "Approved",
    approvalRequired: false,
    createdBy: 17,
    createdAt: "2026-07-07T09:40:00Z",
    updatedAt: null,
    totals: { subTotal: 112100.0, tax: 20178.0, grandTotal: 132278.0, currency: "LKR" },
    lines: [
      { poLineId: 900, itemId: 1001, uomId: 1, warehouseId: 1, qty: 5000, unitPrice: 12.5, tax: 0.18, qtyReceived: 0 },
      { poLineId: 901, itemId: 1002, uomId: 1, warehouseId: 1, qty: 8000, unitPrice: 6.2, tax: 0.18, qtyReceived: 0 },
    ],
  },
  {
    poId: 350,
    docNo: "PO-2026-00350",
    vendorId: 8,
    requisitionId: null,
    status: "PartiallyReceived",
    approvalRequired: false,
    createdBy: 17,
    createdAt: "2026-07-09T09:00:00Z",
    updatedAt: "2026-07-10T11:00:00Z",
    totals: { subTotal: 22500.0, tax: 4050.0, grandTotal: 26550.0, currency: "LKR" },
    lines: [
      { poLineId: 910, itemId: 1003, uomId: 1, warehouseId: 2, qty: 50, unitPrice: 450.0, tax: 0.18, qtyReceived: 20 },
    ],
  },
]

let nextPoId = 351

export function allocatePoId() {
  return nextPoId++
}

// Concurrency token per PO (same out-of-band ETag pattern as mockVendorVersions,
// docs/11 §1.6) — backs PUT /purchase-orders/{poId}'s If-Match (FR-PROC-05, Option B).
const mockPoVersions = new Map<number, number>(mockPurchaseOrders.map((p) => [p.poId, 1]))

export function getPoVersion(poId: number): number {
  return mockPoVersions.get(poId) ?? 1
}

export function bumpPoVersion(poId: number): number {
  const next = getPoVersion(poId) + 1
  mockPoVersions.set(poId, next)
  return next
}

export function initPoVersion(poId: number) {
  mockPoVersions.set(poId, 1)
}

export const mockGrns: Grn[] = [
  {
    grnId: 780,
    docNo: "GRN-2026-00780",
    poId: 342,
    vendorId: 5,
    warehouseId: 1,
    status: "Draft",
    createdBy: 17,
    createdAt: "2026-07-11T10:00:00Z",
    lines: [
      {
        grnLineId: 1300,
        poLineId: 900,
        itemId: 1001,
        uomId: 1,
        binId: 1,
        qty: 5000,
        unitCost: 12.5,
        receivedValue: 62500.0,
        holdStatus: "OnHold",
        batchId: 410,
      },
    ],
  },
  {
    grnId: 781,
    docNo: "GRN-2026-00781",
    poId: null,
    vendorId: 8,
    warehouseId: 2,
    status: "Confirmed",
    createdBy: 17,
    createdAt: "2026-07-10T14:30:00Z",
    lines: [
      {
        grnLineId: 1310,
        poLineId: null,
        itemId: 1003,
        uomId: 1,
        binId: 4,
        qty: 5,
        unitCost: 450.0,
        receivedValue: 2250.0,
        holdStatus: "Available",
        batchId: null,
      },
    ],
  },
]

// A handful more so the list screen's pagination/search/filter controls have
// something real to page through (10 items total across statuses/warehouses).
const extraStatuses: Grn["status"][] = ["Draft", "Confirmed", "Closed", "Confirmed", "Draft", "Confirmed", "Closed", "Draft"]
for (let i = 0; i < extraStatuses.length; i++) {
  const grnId = 782 + i
  const warehouseId = i % 2 === 0 ? 1 : 2
  const vendorId = i % 2 === 0 ? 5 : 8
  const itemId = i % 2 === 0 ? 1001 : 1003
  const status = extraStatuses[i]
  mockGrns.push({
    grnId,
    docNo: `GRN-2026-${String(grnId).padStart(5, "0")}`,
    poId: i % 3 === 0 ? null : 342,
    vendorId,
    warehouseId,
    status,
    createdBy: 17,
    createdAt: new Date(Date.UTC(2026, 6, 1 + i, 9, 0, 0)).toISOString(),
    lines: [
      {
        grnLineId: 2000 + i,
        poLineId: i % 3 === 0 ? null : 900,
        itemId,
        uomId: 1,
        binId: warehouseId === 1 ? 1 : 4,
        qty: 100 * (i + 1),
        unitCost: 10 + i,
        receivedValue: 100 * (i + 1) * (10 + i),
        holdStatus: status === "Draft" ? "OnHold" : "Available",
        batchId: null,
      },
    ],
  })
}

let nextGrnId = 782 + extraStatuses.length
let nextGrnLineId = 2000 + extraStatuses.length

export function allocateGrnId() {
  return nextGrnId++
}

export function allocateGrnLineId() {
  return nextGrnLineId++
}

/** Small delay so loading states are visible when reviewing the UI. */
export function mockDelay<T>(value: T, ms = 300): Promise<T> {
  return new Promise((resolve) => setTimeout(() => resolve(value), ms))
}

// ============================================================================
// Stock Core (FIFO layers + immutable ledger) — docs/10 Part C.5, FR-STK-01..04.
// GRN confirm and every stock transaction below post through these helpers so
// Stock Enquiry / Ledger / Valuation reflect what actually happened this session.
// ============================================================================

export interface MockStockLayer {
  layerId: number
  itemId: number
  warehouseId: number
  batchId: number | null
  serialId: number | null
  grnLineId: number | null
  qtyReceived: number
  qtyRemaining: number
  unitCost: number
  receiptDate: string
}

export const mockStockLayers: MockStockLayer[] = []
export const mockStockLedger: LedgerEntry[] = []

let nextLayerId = 9001
let nextLedgerId = 55010

export function allocateLayerId() {
  return nextLayerId++
}

export function allocateLedgerId() {
  return nextLedgerId++
}

function round2(n: number) {
  return Math.round(n * 100) / 100
}

function latestRunningBalance(itemId: number, warehouseId: number): number {
  for (let i = mockStockLedger.length - 1; i >= 0; i--) {
    const entry = mockStockLedger[i]
    if (entry.itemId === itemId && entry.warehouseId === warehouseId) return entry.runningBalance
  }
  return 0
}

export function postLedgerEntry(input: {
  itemId: number
  warehouseId: number
  binId?: number | null
  batchId?: number | null
  serialId?: number | null
  userId: number
  direction: LedgerDirection
  qtyBase: number
  unitCost: number
  sourceDocType: string
  sourceDocId: number
}): LedgerEntry {
  const prior = latestRunningBalance(input.itemId, input.warehouseId)
  const delta = input.direction === "In" ? input.qtyBase : -input.qtyBase
  const entry: LedgerEntry = {
    ledgerId: allocateLedgerId(),
    itemId: input.itemId,
    warehouseId: input.warehouseId,
    binId: input.binId ?? null,
    batchId: input.batchId ?? null,
    serialId: input.serialId ?? null,
    direction: input.direction,
    qtyBase: input.qtyBase,
    unitCost: input.unitCost,
    value: round2(input.qtyBase * input.unitCost),
    runningBalance: round2(prior + delta),
    sourceDocType: input.sourceDocType,
    sourceDocId: input.sourceDocId,
    userId: input.userId,
    createdAt: new Date().toISOString(),
  }
  mockStockLedger.push(entry)
  return entry
}

/** Creates a FIFO layer + posts the matching inbound ledger entry (FR-GRN-06 / FR-STK-02). */
export function receiveLayer(input: {
  itemId: number
  warehouseId: number
  binId?: number | null
  batchId?: number | null
  serialId?: number | null
  grnLineId?: number | null
  qty: number
  unitCost: number
  userId: number
  sourceDocType: string
  sourceDocId: number
}): { layer: MockStockLayer; ledger: LedgerEntry } {
  const layer: MockStockLayer = {
    layerId: allocateLayerId(),
    itemId: input.itemId,
    warehouseId: input.warehouseId,
    batchId: input.batchId ?? null,
    serialId: input.serialId ?? null,
    grnLineId: input.grnLineId ?? null,
    qtyReceived: input.qty,
    qtyRemaining: input.qty,
    unitCost: input.unitCost,
    receiptDate: new Date().toISOString(),
  }
  mockStockLayers.push(layer)
  const ledger = postLedgerEntry({
    itemId: input.itemId,
    warehouseId: input.warehouseId,
    binId: input.binId,
    batchId: input.batchId,
    serialId: input.serialId,
    userId: input.userId,
    direction: "In",
    qtyBase: input.qty,
    unitCost: input.unitCost,
    sourceDocType: input.sourceDocType,
    sourceDocId: input.sourceDocId,
  })
  return { layer, ledger }
}

/** 409 STOCK_NEGATIVE_BLOCKED (docs/11 §7) — thrown by consumeFifo when available < requested. */
export class StockNegativeError extends Error {
  code = "STOCK_NEGATIVE_BLOCKED"
  constructor(itemId: number, warehouseId: number) {
    super(`Not enough available stock for item #${itemId} at warehouse #${warehouseId}.`)
  }
}

/** A layer is unavailable while its originating GRN line is still on hold/rejected (docs/10 C.9). */
function isLayerOnHold(layer: MockStockLayer): boolean {
  if (!layer.grnLineId) return false
  for (const grn of mockGrns) {
    const line = grn.lines.find((l) => l.grnLineId === layer.grnLineId)
    if (line) return line.holdStatus === "OnHold" || line.holdStatus === "Rejected"
  }
  return false
}

/** Consumes the oldest open (non-held) layers first (FR-STK-03); throws StockNegativeError if insufficient. */
export function consumeFifo(
  itemId: number,
  warehouseId: number,
  qty: number
): { layerId: number; qtyConsumed: number; unitCost: number }[] {
  let remaining = qty
  const consumed: { layerId: number; qtyConsumed: number; unitCost: number }[] = []
  const candidates = mockStockLayers
    .filter((l) => l.itemId === itemId && l.warehouseId === warehouseId && l.qtyRemaining > 0 && !isLayerOnHold(l))
    .sort((a, b) => new Date(a.receiptDate).getTime() - new Date(b.receiptDate).getTime())

  for (const layer of candidates) {
    if (remaining <= 0) break
    const take = Math.min(layer.qtyRemaining, remaining)
    layer.qtyRemaining = round2(layer.qtyRemaining - take)
    remaining = round2(remaining - take)
    consumed.push({ layerId: layer.layerId, qtyConsumed: take, unitCost: layer.unitCost })
  }
  if (remaining > 0.0001) throw new StockNegativeError(itemId, warehouseId)
  return consumed
}

/** "Last cost" for an adjustment increase (FR-STK-07) when no more specific cost is supplied. */
export function lastKnownCost(itemId: number, warehouseId: number): number {
  const layers = mockStockLayers
    .filter((l) => l.itemId === itemId && l.warehouseId === warehouseId)
    .sort((a, b) => new Date(b.receiptDate).getTime() - new Date(a.receiptDate).getTime())
  return layers[0]?.unitCost ?? 10
}

/**
 * Consumes stock for a Purchase Return against the specific layer its GRN line created
 * (FR-PROC-08) — deliberately not routed through consumeFifo: a return disposes of the
 * exact received batch (often On-hold/Rejected, which consumeFifo's isLayerOnHold filter
 * would otherwise skip), not just "the oldest open layer for this item/warehouse".
 * Throws StockNegativeError (409 STOCK_NEGATIVE_BLOCKED, docs/11 §3.4) if the return
 * qty exceeds what remains on that layer.
 */
export function consumeLayerByGrnLine(
  grnLineId: number,
  qty: number
): { layerId: number; qtyConsumed: number; unitCost: number; itemId: number; warehouseId: number } {
  const layer = mockStockLayers.find((l) => l.grnLineId === grnLineId)
  if (!layer || layer.qtyRemaining < qty) {
    const itemId = layer?.itemId ?? 0
    const warehouseId = layer?.warehouseId ?? 0
    throw new StockNegativeError(itemId, warehouseId)
  }
  layer.qtyRemaining = round2(layer.qtyRemaining - qty)
  return { layerId: layer.layerId, qtyConsumed: qty, unitCost: layer.unitCost, itemId: layer.itemId, warehouseId: layer.warehouseId }
}

export function computeOnHand(itemId: number, warehouseId: number) {
  const layers = mockStockLayers.filter((l) => l.itemId === itemId && l.warehouseId === warehouseId)
  const onHand = round2(layers.reduce((sum, l) => sum + l.qtyRemaining, 0))
  const onHold = round2(layers.filter(isLayerOnHold).reduce((sum, l) => sum + l.qtyRemaining, 0))
  const inTransit = round2(
    mockStockTransfers
      .filter((t) => t.status === "InTransit" && t.destWarehouseId === warehouseId)
      .flatMap((t) => t.lines)
      .filter((l) => l.itemId === itemId)
      .reduce((sum, l) => sum + l.qty, 0)
  )
  const reserved = 0
  const available = Math.max(0, round2(onHand - onHold - reserved))
  return { onHand, onHold, inTransit, reserved, available }
}

/** Every item/warehouse combination that currently has (or ever had) a layer — drives the Enquiry screen. */
export function knownStockKeys(): { itemId: number; warehouseId: number }[] {
  const seen = new Map<string, { itemId: number; warehouseId: number }>()
  for (const layer of mockStockLayers) {
    seen.set(`${layer.itemId}:${layer.warehouseId}`, { itemId: layer.itemId, warehouseId: layer.warehouseId })
  }
  return [...seen.values()]
}

// --- Reference data (docs/11 §6) --------------------------------------------------

export interface MockItemReorder {
  itemId: number
  warehouseId: number
  reorderPoint: number
  reorderQty: number
}

export const mockItemReorders: MockItemReorder[] = [
  { itemId: 1001, warehouseId: 1, reorderPoint: 2500, reorderQty: 5000 },
  { itemId: 1002, warehouseId: 1, reorderPoint: 5000, reorderQty: 8000 },
  { itemId: 1003, warehouseId: 2, reorderPoint: 15, reorderQty: 20 },
]

export const mockReasonCodes: ReasonCode[] = [
  { reasonCodeId: 1, code: "DMG", description: "Damage", context: "Adjustment" },
  { reasonCodeId: 2, code: "LOSS", description: "Theft/Loss", context: "Adjustment" },
  { reasonCodeId: 3, code: "CNTVAR", description: "Count Variance", context: "Adjustment" },
  { reasonCodeId: 4, code: "EXPWO", description: "Expiry Write-off", context: "Adjustment" },
  { reasonCodeId: 5, code: "SYSCORR", description: "System Correction", context: "Adjustment" },
  { reasonCodeId: 22, code: "QREJ", description: "Quality Reject", context: "Return" },
]

// --- Seed some prior receipts so Enquiry/Ledger/Valuation aren't empty on first load ---

receiveLayer({
  itemId: 1001, warehouseId: 1, binId: 1, batchId: 411, qty: 3000, unitCost: 12.5,
  userId: 17, sourceDocType: "GRN", sourceDocId: 779,
})
receiveLayer({
  itemId: 1002, warehouseId: 1, binId: 2, qty: 6000, unitCost: 6.2,
  userId: 17, sourceDocType: "GRN", sourceDocId: 779,
})
receiveLayer({
  itemId: 1003, warehouseId: 2, binId: 4, qty: 20, unitCost: 450,
  userId: 17, sourceDocType: "GRN", sourceDocId: 781,
})

// ============================================================================
// Transfers (FR-STK-05/06) — create → dispatch (consume src) → receive (create dest).
// ============================================================================

export interface MockTransferLine {
  transferLineId: number
  itemId: number
  srcBinId: number | null
  destBinId: number | null
  batchId: number | null
  qty: number
  /** Recorded on dispatch so receive() can create cost-preserving destination layers (FR-STK-06). */
  dispatchedChunks: { layerId: number; qtyConsumed: number; unitCost: number }[]
}

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

export const mockStockTransfers: MockStockTransfer[] = []
let nextTransferId = 55
let nextTransferLineId = 300

export function allocateTransferId() {
  return nextTransferId++
}

export function allocateTransferLineId() {
  return nextTransferLineId++
}

// ============================================================================
// Adjustments (FR-STK-07) — auto-post on creation.
// ============================================================================

export interface MockAdjustmentLine {
  adjLineId: number
  itemId: number
  binId: number | null
  batchId: number | null
  qtyDelta: number
}

export interface MockStockAdjustment {
  adjustmentId: number
  docNo: string
  warehouseId: number
  reasonCodeId: number
  status: AdjustmentStatus
  createdBy: number
  createdAt: string
  lines: MockAdjustmentLine[]
  ledgerRefs: number[]
}

export const mockStockAdjustments: MockStockAdjustment[] = []
let nextAdjustmentId = 77
let nextAdjLineId = 210

export function allocateAdjustmentId() {
  return nextAdjustmentId++
}

export function allocateAdjLineId() {
  return nextAdjLineId++
}

// ============================================================================
// Counts (FR-STK-08) — snapshot system qty → enter counted qty → post variance.
// ============================================================================

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

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

export const mockStockCounts: MockStockCount[] = []
let nextCountId = 30
let nextCountLineId = 400

export function allocateCountId() {
  return nextCountId++
}

export function allocateCountLineId() {
  return nextCountLineId++
}

// ============================================================================
// Procurement (FR-PROC-01..09) — Requisition → RFQ → Quotations → PO → Return.
// No Procurement backend exists yet; same frontend-only posture as GRN/Stock.
// ============================================================================

export const mockRequisitions: Requisition[] = [
  // Seeded to match mockPurchaseOrders[0].requisitionId (PO-2026-00342 was raised
  // against this requisition) so the two screens cross-reference consistently.
  {
    requisitionId: 210,
    docNo: "PR-2026-00210",
    status: "Submitted",
    requestedBy: 17,
    createdAt: "2026-07-06T08:30:00Z",
    lines: [
      { reqLineId: 501, itemId: 1001, qty: 5000, requiredBy: "2026-07-20" },
      { reqLineId: 502, itemId: 1002, qty: 8000, requiredBy: "2026-07-20" },
    ],
  },
]

let nextRequisitionId = 211
let nextReqLineId = 503

export function allocateRequisitionId() {
  return nextRequisitionId++
}

export function allocateReqLineId() {
  return nextReqLineId++
}

export const mockRfqs: Rfq[] = []
let nextRfqId = 89
let nextRfqLineId = 703

export function allocateRfqId() {
  return nextRfqId++
}

export function allocateRfqLineId() {
  return nextRfqLineId++
}

export const mockQuotations: Quotation[] = []
let nextQuotationId = 141

export function allocateQuotationId() {
  return nextQuotationId++
}

export const mockPurchaseReturns: PurchaseReturn[] = []
let nextPurchaseReturnId = 61
let nextPurchaseReturnLineId = 121

export function allocatePurchaseReturnId() {
  return nextPurchaseReturnId++
}

export function allocatePurchaseReturnLineId() {
  return nextPurchaseReturnLineId++
}
