import { apiRequest, apiRequestWithETag, buildQuery } from "@/lib/api-client"
import { ApiResult, PagedResponse } from "@/types/common"
import {
  CreateSalesInvoicePaymentRequest,
  CreateSalesInvoiceRequest,
  CreateSalesSlipRequest,
  SalesInvoice,
  SalesInvoiceStatus,
  SalesInvoicePayment,
  SalesInvoicePostingCheck,
  SalesInvoiceSummary,
  SalesListFilterParams,
  SalesReportDefinition,
  SalesReportQueryRequest,
  SalesReportQueryResponse,
  SalesFreeIssueSuggestion,
  FreeIssueDetail,
  FreeIssueSummary,
  SalesSlip,
  SalesSlipStatus,
  SalesSlipPostingCheck,
  SalesSlipSummary,
  UpdateSalesInvoiceRequest,
  UpdateSalesSlipRequest,
} from "@/types/sales"

type SalesReportId = string

export interface ListSalesInvoicesParams extends SalesListFilterParams {
  status?: SalesInvoiceStatus
}

export interface ListSalesSlipsParams extends SalesListFilterParams {
  status?: SalesSlipStatus
}

export interface ListFreeIssuesParams extends SalesListFilterParams {
  status?: SalesSlipStatus
}

export const salesApi = {
  listInvoices(params: ListSalesInvoicesParams = {}): Promise<PagedResponse<SalesInvoiceSummary>> {
    return apiRequest<PagedResponse<SalesInvoiceSummary>>(`/sales-invoices${buildQuery(params)}`)
  },

  getInvoice(salesInvoiceId: number): Promise<ApiResult<SalesInvoice>> {
    return apiRequestWithETag<SalesInvoice>(`/sales-invoices/${salesInvoiceId}`)
  },

  createInvoice(request: CreateSalesInvoiceRequest): Promise<ApiResult<SalesInvoice>> {
    return apiRequestWithETag<SalesInvoice>("/sales-invoices", { method: "POST", body: request })
  },

  updateInvoice(salesInvoiceId: number, request: UpdateSalesInvoiceRequest, ifMatch: string): Promise<ApiResult<SalesInvoice>> {
    return apiRequestWithETag<SalesInvoice>(`/sales-invoices/${salesInvoiceId}`, { method: "PUT", body: request, ifMatch })
  },

  postInvoice(salesInvoiceId: number): Promise<SalesInvoice> {
    return apiRequest<SalesInvoice>(`/sales-invoices/${salesInvoiceId}/post`, { method: "POST" })
  },

  checkInvoicePosting(salesInvoiceId: number): Promise<SalesInvoicePostingCheck> {
    return apiRequest<SalesInvoicePostingCheck>(`/sales-invoices/${salesInvoiceId}/posting-check`)
  },

  cancelInvoice(salesInvoiceId: number): Promise<SalesInvoice> {
    return apiRequest<SalesInvoice>(`/sales-invoices/${salesInvoiceId}/cancel`, { method: "POST" })
  },

  /** Pay the customer's balance against a posted invoice, in full or in installments. Posts a real GL journal entry. */
  payInvoice(salesInvoiceId: number, request: CreateSalesInvoicePaymentRequest): Promise<SalesInvoicePayment> {
    return apiRequest<SalesInvoicePayment>(`/sales-invoices/${salesInvoiceId}/payments`, { method: "POST", body: request })
  },

  /** Payment history for an invoice, newest first. */
  listInvoicePayments(salesInvoiceId: number): Promise<SalesInvoicePayment[]> {
    return apiRequest<SalesInvoicePayment[]>(`/sales-invoices/${salesInvoiceId}/payments`)
  },

  listSlips(params: ListSalesSlipsParams = {}): Promise<PagedResponse<SalesSlipSummary>> {
    return apiRequest<PagedResponse<SalesSlipSummary>>(`/sales-slips${buildQuery(params)}`)
  },

  getSlip(salesSlipId: number): Promise<ApiResult<SalesSlip>> {
    return apiRequestWithETag<SalesSlip>(`/sales-slips/${salesSlipId}`)
  },

  createSlip(request: CreateSalesSlipRequest): Promise<ApiResult<SalesSlip>> {
    return apiRequestWithETag<SalesSlip>("/sales-slips", { method: "POST", body: request })
  },

  updateSlip(salesSlipId: number, request: UpdateSalesSlipRequest, ifMatch: string): Promise<ApiResult<SalesSlip>> {
    return apiRequestWithETag<SalesSlip>(`/sales-slips/${salesSlipId}`, { method: "PUT", body: request, ifMatch })
  },

  postSlip(salesSlipId: number): Promise<SalesSlip> {
    return apiRequest<SalesSlip>(`/sales-slips/${salesSlipId}/post`, { method: "POST" })
  },

  checkSlipPosting(salesSlipId: number): Promise<SalesSlipPostingCheck> {
    return apiRequest<SalesSlipPostingCheck>(`/sales-slips/${salesSlipId}/posting-check`)
  },

  cancelSlip(salesSlipId: number): Promise<SalesSlip> {
    return apiRequest<SalesSlip>(`/sales-slips/${salesSlipId}/cancel`, { method: "POST" })
  },

  listFreeIssues(params: ListFreeIssuesParams = {}): Promise<PagedResponse<FreeIssueSummary>> {
    return apiRequest<PagedResponse<FreeIssueSummary>>(`/free-issues${buildQuery(params)}`)
  },

  getFreeIssue(freeIssueId: number): Promise<ApiResult<FreeIssueDetail>> {
    return apiRequestWithETag<FreeIssueDetail>(`/free-issues/${freeIssueId}`)
  },

  createFreeIssue(request: CreateSalesSlipRequest): Promise<ApiResult<FreeIssueDetail>> {
    return apiRequestWithETag<FreeIssueDetail>("/free-issues", { method: "POST", body: request })
  },

  updateFreeIssue(freeIssueId: number, request: UpdateSalesSlipRequest, ifMatch: string): Promise<ApiResult<FreeIssueDetail>> {
    return apiRequestWithETag<FreeIssueDetail>(`/free-issues/${freeIssueId}`, { method: "PUT", body: request, ifMatch })
  },

  postFreeIssue(freeIssueId: number): Promise<FreeIssueDetail> {
    return apiRequest<FreeIssueDetail>(`/free-issues/${freeIssueId}/post`, { method: "POST" })
  },

  checkFreeIssuePosting(freeIssueId: number): Promise<SalesSlipPostingCheck> {
    return apiRequest<SalesSlipPostingCheck>(`/free-issues/${freeIssueId}/posting-check`)
  },

  cancelFreeIssue(freeIssueId: number): Promise<FreeIssueDetail> {
    return apiRequest<FreeIssueDetail>(`/free-issues/${freeIssueId}/cancel`, { method: "POST" })
  },

  getFreeIssueSuggestions(salesSlipId: number): Promise<SalesFreeIssueSuggestion> {
    return apiRequest<SalesFreeIssueSuggestion>(`/sales-slips/${salesSlipId}/free-issue-suggestions`)
  },

  listReports(): Promise<SalesReportDefinition[]> {
    return apiRequest<SalesReportDefinition[]>("/reports/sales")
  },

  getReport(reportId: SalesReportId): Promise<SalesReportDefinition> {
    return apiRequest<SalesReportDefinition>(`/reports/sales/${reportId}`)
  },

  queryReport(request: SalesReportQueryRequest): Promise<SalesReportQueryResponse> {
    return apiRequest<SalesReportQueryResponse>("/reports/sales/query", { method: "POST", body: request })
  },
}
