import { EntityStatus } from "@/types/common"

export type SalesInvoiceType = "B2B" | "B2C" | "Cash" | "Credit"
export type SalesInvoiceStatus = "Draft" | "Posted" | "Cancelled"
export type SalesSlipStatus = "Draft" | "Posted" | "Cancelled"
export type SalesDiscountMode = "Percentage" | "Amount"

export interface SalesInvoiceLine {
  salesInvoiceLineId: number
  itemId: number
  description: string
  qty: number
  freeQty: number
  warehouseId: number
  unitPrice: number
  baseCost: number
  priceSource: string
  discountPct: number
  discountAmount: number
  discountMode: SalesDiscountMode
  netUnitPrice: number
  lineTotal: number
  taxPct: number
  taxAmount: number
  isFreeIssue: boolean
  parentLineId: number | null
}

export interface SalesInvoiceTotals {
  subtotal: number
  discountTotal: number
  freeQtyTotal: number
  taxTotal: number
  grandTotal: number
  roundOff: number
  netPayable: number
  paidAmount: number
  balanceAmount: number
}

export interface SalesInvoiceSummary {
  salesInvoiceId: number
  invoiceNo: string
  invoiceDate: string
  customerId: number
  customerSnapshotName: string
  warehouseId: number
  invoiceType: SalesInvoiceType
  status: SalesInvoiceStatus
  totals: SalesInvoiceTotals
  createdAt: string
  glJournalNo: string | null
}

export interface SalesInvoicePostingIssue {
  salesInvoiceLineId: number
  itemId: number
  itemSku: string
  itemName: string
  warehouseId: number
  requestedQty: number
  availableQty: number
  shortQty: number
  isFreeIssue: boolean
}

export interface SalesInvoicePostingCheck {
  salesInvoiceId: number
  invoiceNo: string
  status: SalesInvoiceStatus
  canPost: boolean
  issues: SalesInvoicePostingIssue[]
}

export interface SalesSlipPostingIssue {
  salesSlipLineId: number
  itemId: number
  itemSku: string
  itemName: string
  warehouseId: number
  requestedQty: number
  availableQty: number
  shortQty: number
  isFreeIssue: boolean
}

export interface SalesSlipPostingCheck {
  salesSlipId: number
  slipNo: string
  status: SalesSlipStatus
  canPost: boolean
  issues: SalesSlipPostingIssue[]
}

export interface SalesInvoice extends SalesInvoiceSummary {
  customerSnapshotTaxNo: string | null
  createdBy: number
  updatedAt: string | null
  glPostedAt: string | null
  lines: SalesInvoiceLine[]
}

export interface SalesInvoicePayment {
  salesInvoicePaymentId: number
  salesInvoiceId: number
  amount: number
  paymentDate: string
  glBankAccountId: number
  bankAccountName: string
  reference: string | null
  glJournalNo: string | null
  createdAt: string
}

export interface CreateSalesInvoicePaymentRequest {
  amount: number
  glBankAccountId: number
  reference?: string | null
}

export interface CreateSalesInvoiceLineRequest {
  itemId: number
  warehouseId: number
  qty: number
  freeQty: number
  unitPrice?: number | null
  allowManualPriceOverride: boolean
  discountMode: SalesDiscountMode
  discountPct: number
  discountAmount: number
  discountValue: number
  taxPct: number
  isFreeIssue: boolean
  parentLineId?: number | null
}

export interface CreateSalesInvoiceRequest {
  customerId: number
  warehouseId: number
  invoiceType: SalesInvoiceType
  lines: CreateSalesInvoiceLineRequest[]
}

export type UpdateSalesInvoiceRequest = CreateSalesInvoiceRequest

export interface SalesSlipLine {
  salesSlipLineId: number
  itemId: number
  description: string
  qty: number
  freeQty: number
  warehouseId: number
  unitPrice: number
  baseCost: number
  priceSource: string
  discountPct: number
  discountAmount: number
  discountMode: SalesDiscountMode
  netUnitPrice: number
  lineTotal: number
  taxPct: number
  taxAmount: number
  isFreeIssue: boolean
  parentLineId: number | null
}

export interface SalesSlipTotals {
  subtotal: number
  discountTotal: number
  freeQtyTotal: number
  taxTotal: number
  grandTotal: number
  paidAmount: number
  balanceAmount: number
}

export interface SalesSlipSummary {
  salesSlipId: number
  slipNo: string
  slipDate: string
  customerId: number
  customerSnapshotName: string
  warehouseId: number
  status: SalesSlipStatus
  totals: SalesSlipTotals
  createdAt: string
}

export interface SalesSlip {
  salesSlipId: number
  slipNo: string
  slipDate: string
  customerId: number
  customerSnapshotName: string
  warehouseId: number
  cashierUserId: number
  status: SalesSlipStatus
  createdAt: string
  updatedAt: string | null
  totals: SalesSlipTotals
  lines: SalesSlipLine[]
}

export interface CreateSalesSlipLineRequest {
  itemId: number
  warehouseId: number
  qty: number
  freeQty: number
  unitPrice?: number | null
  allowManualPriceOverride: boolean
  discountMode: SalesDiscountMode
  discountPct: number
  discountAmount: number
  discountValue: number
  taxPct: number
  isFreeIssue: boolean
  parentLineId?: number | null
}

export interface CreateSalesSlipRequest {
  customerId: number
  warehouseId: number
  cashierUserId: number
  lines: CreateSalesSlipLineRequest[]
}

export type UpdateSalesSlipRequest = CreateSalesSlipRequest

export interface SalesReportDefinition {
  id: string
  name: string
  description: string
  supportedFilters: string[]
}

export interface SalesReportQueryRequest {
  reportType: string
  from: string
  to: string
  itemId?: number | null
  customerId?: number | null
  warehouseId?: number | null
}

export interface SalesReportQueryResponse {
  reportType: string
  from: string
  to: string
  rows: unknown[]
}

export interface SalesListFilterParams {
  page?: number
  pageSize?: number
  status?: SalesInvoiceStatus | SalesSlipStatus
  customerId?: number
  warehouseId?: number
}

export interface FreeIssueSummaryItem extends SalesSlipSummary {
  // Alias for the free issue route. Kept as a slip-shaped payload because the backend
  // stores free issues as sales slips with free-issue line flags.
  isFreeIssue?: boolean
}

export interface FreeIssueSummary {
  salesSlipId: number
  slipNo: string
  status: SalesSlipStatus
  createdAt: string
  warehouseId: number
  warehouseName: string
  itemId: number
  itemSku: string
  itemName: string
  uomName: string
  qty: number
  freeQty: number
  schemeLabel: string
}

export interface FreeIssueDetail {
  salesSlipId: number
  slipNo: string
  slipDate: string
  status: SalesSlipStatus
  customerId: number
  customerSnapshotName: string
  warehouseId: number
  warehouseName: string
  cashierUserId: number
  createdAt: string
  updatedAt: string | null
  summary: FreeIssueSummary
  lines: SalesSlipLine[]
}

export interface SalesFreeIssueRewardOption {
  itemId: number
  sku: string
  name: string
  salePrice: number | null
}

export interface SalesFreeIssueSuggestionLine {
  salesSlipLineId: number
  itemId: number
  itemSku: string
  itemName: string
  qty: number
  suggestedFreeQty: number
  triggerQty: number
  rewardOptions: SalesFreeIssueRewardOption[]
}

export interface SalesFreeIssueSuggestion {
  salesSlipId: number
  slipNo: string
  slipDate: string
  lines: SalesFreeIssueSuggestionLine[]
}

export interface SalesCustomer {
  customerId: number
  code: string
  name: string
  taxNo: string | null
  status: EntityStatus
}

// --- Sales Returns -----------------------------------------------------------------

export type SalesReturnStatus = "Draft" | "Posted"

export interface SalesReturnLine {
  returnLineId: number
  /** Optional: a return may reference the originating sales invoice line for traceability. */
  salesInvoiceLineId: number | null
  itemId: number
  qty: number
}

export interface SalesReturn {
  returnId: number
  docNo: string
  customerId: number
  warehouseId: number
  reasonCodeId: number
  status: SalesReturnStatus
  createdBy: number
  createdAt: string
  glJournalNo: string | null
  glPostedAt: string | null
  lines: SalesReturnLine[]
  ledgerRefs: number[]
}

export interface SalesReturnSummary {
  returnId: number
  docNo: string
  customerId: number
  warehouseId: number
  reasonCodeId: number
  status: SalesReturnStatus
  createdBy: number
  createdAt: string
  lineCount: number
  totalQty: number
  glJournalNo: string | null
}

/** Remaining returnable qty for one sales invoice line (invoiced qty minus already-returned). */
export interface SalesInvoiceLineRemaining {
  salesInvoiceLineId: number
  remainingQty: number
}

export interface CreateSalesReturnLineInput {
  salesInvoiceLineId?: number | null
  itemId: number
  qty: number
}

export interface CreateSalesReturnRequest {
  customerId: number
  warehouseId: number
  /** Mandatory; omitting it returns 400 REASON_CODE_REQUIRED. */
  reasonCodeId: number
  lines: CreateSalesReturnLineInput[]
}

// Sales Day End -------------------------------------------------------------------

export interface SalesDayEndItemLine {
  itemId: number
  sku: string
  name: string
  qty: number
  revenue: number
}

export interface SalesDayEnd {
  salesDayEndId: number
  docNo: string
  cashierUserId: number
  businessDate: string
  slipCount: number
  bundleCount: number
  subtotal: number
  discountTotal: number
  taxTotal: number
  grandTotal: number
  costOfGoodsSold: number
  glJournalNo: string | null
  glPostedAt: string | null
  closedBy: number
  closedAt: string
  slipNumbers: string[]
  bundleNumbers: string[]
  itemBreakdown: SalesDayEndItemLine[]
}

export interface SalesDayEndSummary {
  salesDayEndId: number
  docNo: string
  cashierUserId: number
  businessDate: string
  slipCount: number
  bundleCount: number
  grandTotal: number
  glJournalNo: string | null
  closedAt: string
}

export interface DraftSlipBlockingClose {
  salesSlipId: number
  slipNo: string
  grandTotal: number
}

export interface DraftBundleBlockingClose {
  bundleSaleId: number
  bundleNo: string
  grandTotal: number
}

export interface SalesDayEndPreview {
  cashierUserId: number
  businessDate: string
  alreadyClosed: boolean
  slipCount: number
  bundleCount: number
  subtotal: number
  discountTotal: number
  taxTotal: number
  grandTotal: number
  slipNumbers: string[]
  bundleNumbers: string[]
  draftSlipsBlockingClose: DraftSlipBlockingClose[]
  draftBundleSalesBlockingClose: DraftBundleBlockingClose[]
}

export interface CreateSalesDayEndRequest {
  cashierUserId: number
  businessDate?: string | null
}
