// Package pricing is the authoritative price resolver for POS, sales orders,
// and B2B checkout (business-rules.md §11.2, §12). Callers submit intent -
// product, optional configured unit, quantity - and receive the resolved unit
// price, minimum purchase, conversion factor, and base-unit quantity to move in
// stock. A client-supplied price is never an input here.
package pricing

import (
	"context"

	"github.com/shopspring/decimal"

	"github.com/TaruLab/keluargamart-backend/internal/db"
)

// Request is one line of transaction intent. ProductUnitID is optional: when
// absent the product's configured base unit is used, and when the product has
// no configured units the product selling price applies at factor 1.
type Request struct {
	ProductID     int64
	ProductUnitID *int64
	Quantity      decimal.Decimal
	// CustomerID opt-in: when set and a MembershipResolver is wired, the
	// resolved line receives the active membership's tier benefit (§13.1).
	// Nil means no membership lookup — existing behavior is preserved.
	CustomerID *int64
}

// Resolved is the authoritative outcome for one line. Quantity stays in the
// selected unit; BaseQuantity is what inventory must move.
type Resolved struct {
	ProductID        int64
	ProductCode      string
	ProductName      string
	ProductUnitID    *int64
	UnitID           *int64
	UnitName         string
	UnitSymbol       string
	ConversionFactor decimal.Decimal
	UnitPrice        decimal.Decimal
	MinPurchase      decimal.Decimal
	Quantity         decimal.Decimal
	BaseQuantity     decimal.Decimal
	LineSubtotal     decimal.Decimal
	// Membership benefit snapshot (Phase 6 item 3, §13.1). Populated only when
	// an active membership benefit applies; empty/zero otherwise. These travel
	// into the immutable sales-line snapshot so returns replay the discount.
	MembershipTier            string          // "" when not applied
	MembershipDiscountPercent decimal.Decimal // 0 when not applied
	MembershipDiscountAmount  decimal.Decimal // money off line subtotal
	FinalSubtotal             decimal.Decimal // LineSubtotal - MembershipDiscountAmount
}

// Store is the pricing persistence seam (sqlc-backed in production).
//
// Every method takes a db.DBTX so a caller that already holds a transaction
// resolves prices on that same connection. Passing a separate pool connection
// here would deadlock: the caller holds one connection for the transaction while
// waiting for a second one that concurrent callers have already taken. A nil
// DBTX falls back to the pool for read-only callers outside a transaction.
type Store interface {
	PricingProduct(ctx context.Context, q db.DBTX, id int64) (db.GetPricingProductRow, error)
	PricingProductUnit(ctx context.Context, q db.DBTX, id int64) (db.GetPricingProductUnitRow, error)
	PricingBaseUnit(ctx context.Context, q db.DBTX, productID int64) (db.GetPricingBaseUnitRow, error)
}
