// One typed client method per Purchase Return endpoint (docs/11-BACKEND-PHASE1.md §3.4, FR-PROC-08).
// In-memory sample data (lib/api/mock-data.ts) — no backend API calls.
import { PagedResponse } from "@/types/common"
import { CreatePurchaseReturnRequest, PurchaseReturn, PurchaseReturnSummary } from "@/types/procurement"
import {
  allocatePurchaseReturnId,
  allocatePurchaseReturnLineId,
  consumeLayerByGrnLine,
  mockDelay,
  mockPurchaseReturns,
  postLedgerEntry,
} from "@/lib/api/mock-data"

function toSummary(r: PurchaseReturn): PurchaseReturnSummary {
  return {
    returnId: r.returnId,
    docNo: r.docNo,
    vendorId: r.vendorId,
    warehouseId: r.warehouseId,
    reasonCodeId: r.reasonCodeId,
    status: r.status,
    createdAt: r.createdAt,
  }
}

export const purchaseReturnsApi = {
  list(): Promise<PagedResponse<PurchaseReturnSummary>> {
    const items = [...mockPurchaseReturns].sort((a, b) => b.returnId - a.returnId).map(toSummary)
    return mockDelay({
      items,
      pagination: { page: 1, pageSize: 20, totalItems: items.length, totalPages: 1 },
    })
  },

  get(returnId: number): Promise<PurchaseReturn> {
    const r = mockPurchaseReturns.find((x) => x.returnId === returnId)
    if (!r) return Promise.reject(new Error(`Mock purchase return ${returnId} not found`))
    return mockDelay(r)
  },

  create(request: CreatePurchaseReturnRequest): Promise<PurchaseReturn> {
    if (!request.reasonCodeId) {
      return Promise.reject(Object.assign(new Error("A reason code is required for returns."), { code: "REASON_CODE_REQUIRED" }))
    }
    if (request.lines.length === 0) return Promise.reject(new Error("Add at least one line."))

    const returnId = allocatePurchaseReturnId()
    const ledgerRefs: number[] = []
    const lines: PurchaseReturn["lines"] = []

    try {
      for (const line of request.lines) {
        // FR-PROC-08: consumes the exact layer the GRN line created; throws
        // StockNegativeError (409 STOCK_NEGATIVE_BLOCKED) if qty exceeds it.
        const chunk = consumeLayerByGrnLine(line.grnLineId, line.qty)
        const ledger = postLedgerEntry({
          itemId: line.itemId,
          warehouseId: chunk.warehouseId,
          userId: 17,
          direction: "Out",
          qtyBase: chunk.qtyConsumed,
          unitCost: chunk.unitCost,
          sourceDocType: "PurchaseReturn",
          sourceDocId: returnId,
        })
        ledgerRefs.push(ledger.ledgerId)
        lines.push({
          returnLineId: allocatePurchaseReturnLineId(),
          grnLineId: line.grnLineId,
          itemId: line.itemId,
          qty: line.qty,
        })
      }
    } catch (err) {
      return Promise.reject(err)
    }

    const purchaseReturn: PurchaseReturn = {
      returnId,
      docNo: `PRET-2026-${String(returnId).padStart(5, "0")}`,
      vendorId: request.vendorId,
      warehouseId: request.warehouseId,
      reasonCodeId: request.reasonCodeId,
      status: "Posted",
      createdBy: 17,
      createdAt: new Date().toISOString(),
      lines,
      ledgerRefs,
    }
    mockPurchaseReturns.push(purchaseReturn)
    return mockDelay(purchaseReturn)
  },
}
