package cart

import (
	"context"

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

// Store is the cart persistence seam (sqlc-backed).
type Store interface {
	Begin(ctx context.Context) (Tx, error)
	GetOrCreateCart(ctx context.Context, userID int64) (db.Cart, error)
	GetCartByUserID(ctx context.Context, userID int64) (db.Cart, error)
	LockCartTx(ctx context.Context, q db.DBTX, userID int64) (db.Cart, error)
	CheckoutReceiptTx(ctx context.Context, q db.DBTX, userID int64, key, fingerprint string) (*PlacedOrder, error)
	SaveCheckoutReceiptTx(ctx context.Context, q db.DBTX, userID int64, key, fingerprint string, order *PlacedOrder) error
	ListCartItems(ctx context.Context, cartID int64) ([]db.ListCartItemsByCartIDRow, error)
	ListCartItemsTx(ctx context.Context, q db.DBTX, cartID int64) ([]db.ListCartItemsByCartIDRow, error)
	AddOrUpdateItem(ctx context.Context, cartID, productID int64, quantity decimal.Decimal) (db.CartItem, error)
	UpdateItemQuantity(ctx context.Context, cartID, productID int64, quantity decimal.Decimal) error
	RemoveItem(ctx context.Context, cartID, productID int64) error
	ClearCart(ctx context.Context, cartID int64) error
	ClearCartTx(ctx context.Context, q db.DBTX, cartID int64) error
	GetProductBySKU(ctx context.Context, sku string) (int64, error)
}

// Tx is a physical transaction; pgx.Tx satisfies it. It doubles as the
// db.DBTX handed to tx-scoped store writes.
type Tx interface {
	db.DBTX
	Commit(ctx context.Context) error
	Rollback(ctx context.Context) error
}

// AddItemInput for POST /cart/items.
type AddItemInput struct {
	SKU      string          `json:"sku"`
	Quantity decimal.Decimal `json:"quantity"`
}

// UpdateQuantityInput for PATCH /cart/items/{key}.
type UpdateQuantityInput struct {
	Quantity decimal.Decimal `json:"quantity"`
}

// CartView is the API response shape (persistence uses db.Cart / db rows).
type CartView struct {
	ID        int64        `json:"id"`
	UserID    int64        `json:"user_id"`
	Items     []ItemView   `json:"items"`
	Summary   *CartSummary `json:"summary,omitempty"`
	CreatedAt string       `json:"created_at"`
	UpdatedAt string       `json:"updated_at"`
}

// CartSummary carries the authoritative, membership-adjusted totals so the
// storefront shows exactly what checkout will charge instead of recomputing
// B2B pricing from the list price. Populated only when a line pricer is wired.
type CartSummary struct {
	Subtotal           decimal.Decimal `json:"subtotal"`            // Σ list price × qty (gross)
	MembershipDiscount decimal.Decimal `json:"membership_discount"` // total member benefit
	Total              decimal.Decimal `json:"total"`               // subtotal − membership_discount
}

// ItemView is a cart line with its product snapshot for display.
type ItemView struct {
	ID        int64           `json:"id"`
	CartID    int64           `json:"cart_id"`
	ProductID int64           `json:"product_id"`
	Quantity  decimal.Decimal `json:"quantity"`
	Product   *ProductInfo    `json:"product,omitempty"`
	// Membership-adjusted pricing for this line (populated when a line pricer
	// is wired). MembershipDiscount is the money taken off; Subtotal is the net
	// line total (list price × qty − MembershipDiscount).
	MembershipDiscount *decimal.Decimal `json:"membership_discount,omitempty"`
	Subtotal           *decimal.Decimal `json:"subtotal,omitempty"`
}

// ProductInfo is a minimal product snapshot for cart display.
type ProductInfo struct {
	ID           int64           `json:"id"`
	Code         string          `json:"code"`
	Name         string          `json:"name"`
	SellingPrice decimal.Decimal `json:"selling_price"`
	Image        *string         `json:"image,omitempty"`
}
