// One typed client method per GRN endpoint (docs/11-BACKEND-PHASE1.md §4).
//
// `confirm` is the transactional one: the SERVER creates the FIFO layers, posts the
// inbound ledger and accrues PO receipts (FR-GRN-06). This client only triggers it and
// renders the returned side effects — the browser no longer does inventory maths.
//
// There is deliberately no update()/remove(): the API has no PUT or DELETE for a GRN.
// A confirmed receipt is corrected with a reversing document, never edited (FR-X-05).
import { apiRequest, buildQuery } from "@/lib/api-client"
import { PagedResponse } from "@/types/common"
import {
  ConfirmGrnResponse,
  CreateGrnPaymentRequest,
  CreateGrnRequest,
  Grn,
  GrnPayment,
  GrnStatus,
  GrnSummary,
  ReleaseAction,
  ReleaseGrnLineResponse,
} from "@/types/grn"

export interface ListGrnsParams {
  page?: number
  pageSize?: number
  q?: string
  status?: GrnStatus
  poId?: number
  vendorId?: number
  warehouseId?: number
  sort?: string
}

export const grnsApi = {
  list(params: ListGrnsParams = {}): Promise<PagedResponse<GrnSummary>> {
    return apiRequest<PagedResponse<GrnSummary>>(`/grns${buildQuery(params)}`)
  },

  get(grnId: number): Promise<Grn> {
    return apiRequest<Grn>(`/grns/${grnId}`)
  },

  /** 422 OVER_RECEIPT_TOLERANCE if qty exceeds the PO's open qty beyond tolerance. */
  create(request: CreateGrnRequest): Promise<Grn> {
    return apiRequest<Grn>("/grns", { method: "POST", body: request })
  },

  /**
   * Posts the receipt. Pass a stable idempotencyKey per detail-page session so a retry
   * cannot double-post stock — unlike the old mock, the server genuinely dedupes on it.
   */
  confirm(grnId: number, idempotencyKey?: string): Promise<ConfirmGrnResponse> {
    return apiRequest<ConfirmGrnResponse>(`/grns/${grnId}/confirm`, { method: "POST", idempotencyKey })
  },

  /** "Release" makes an on-hold line issuable; "Reject" routes it to a purchase return. */
  releaseLine(grnId: number, grnLineId: number, action: ReleaseAction): Promise<ReleaseGrnLineResponse> {
    return apiRequest<ReleaseGrnLineResponse>(`/grns/${grnId}/lines/${grnLineId}/release`, {
      method: "POST",
      body: { action },
    })
  },

  /** Pay the vendor against the GRN's balance, in full or in installments. Posts a real GL journal entry. */
  pay(grnId: number, request: CreateGrnPaymentRequest): Promise<GrnPayment> {
    return apiRequest<GrnPayment>(`/grns/${grnId}/payments`, { method: "POST", body: request })
  },

  /** Payment history for a GRN, newest first. */
  listPayments(grnId: number): Promise<GrnPayment[]> {
    return apiRequest<GrnPayment[]>(`/grns/${grnId}/payments`)
  },
}
