// Code generated by sqlc. DO NOT EDIT.
// versions:
//   sqlc v1.27.0
// source: cart.sql

package db

import (
	"context"

	"github.com/jackc/pgx/v5/pgtype"
	"github.com/shopspring/decimal"
)

const addOrUpdateCartItem = `-- name: AddOrUpdateCartItem :one
INSERT INTO cart_items (cart_id, product_id, quantity, created_at, updated_at)
VALUES ($1, $2, $3, now(), now())
ON CONFLICT (cart_id, product_id) DO UPDATE
SET quantity = cart_items.quantity + EXCLUDED.quantity, updated_at = now()
RETURNING id, cart_id, product_id, quantity, created_at, updated_at
`

type AddOrUpdateCartItemParams struct {
	CartID    int64           `json:"cart_id"`
	ProductID int64           `json:"product_id"`
	Quantity  decimal.Decimal `json:"quantity"`
}

func (q *Queries) AddOrUpdateCartItem(ctx context.Context, arg AddOrUpdateCartItemParams) (CartItem, error) {
	row := q.db.QueryRow(ctx, addOrUpdateCartItem, arg.CartID, arg.ProductID, arg.Quantity)
	var i CartItem
	err := row.Scan(
		&i.ID,
		&i.CartID,
		&i.ProductID,
		&i.Quantity,
		&i.CreatedAt,
		&i.UpdatedAt,
	)
	return i, err
}

const clearCartItems = `-- name: ClearCartItems :exec
DELETE FROM cart_items WHERE cart_id = $1
`

func (q *Queries) ClearCartItems(ctx context.Context, cartID int64) error {
	_, err := q.db.Exec(ctx, clearCartItems, cartID)
	return err
}

const deleteCartItem = `-- name: DeleteCartItem :execrows
DELETE FROM cart_items WHERE cart_id = $1 AND product_id = $2
`

type DeleteCartItemParams struct {
	CartID    int64 `json:"cart_id"`
	ProductID int64 `json:"product_id"`
}

func (q *Queries) DeleteCartItem(ctx context.Context, arg DeleteCartItemParams) (int64, error) {
	result, err := q.db.Exec(ctx, deleteCartItem, arg.CartID, arg.ProductID)
	if err != nil {
		return 0, err
	}
	return result.RowsAffected(), nil
}

const getCartByUserID = `-- name: GetCartByUserID :one
SELECT id, user_id, created_at, updated_at FROM carts WHERE user_id = $1
`

func (q *Queries) GetCartByUserID(ctx context.Context, userID int64) (Cart, error) {
	row := q.db.QueryRow(ctx, getCartByUserID, userID)
	var i Cart
	err := row.Scan(
		&i.ID,
		&i.UserID,
		&i.CreatedAt,
		&i.UpdatedAt,
	)
	return i, err
}

const getOrCreateCart = `-- name: GetOrCreateCart :one
INSERT INTO carts (user_id, created_at, updated_at)
VALUES ($1, now(), now())
ON CONFLICT (user_id) DO UPDATE SET updated_at = now()
RETURNING id, user_id, created_at, updated_at
`

func (q *Queries) GetOrCreateCart(ctx context.Context, userID int64) (Cart, error) {
	row := q.db.QueryRow(ctx, getOrCreateCart, userID)
	var i Cart
	err := row.Scan(
		&i.ID,
		&i.UserID,
		&i.CreatedAt,
		&i.UpdatedAt,
	)
	return i, err
}

const listCartItemsByCartID = `-- name: ListCartItemsByCartID :many
SELECT ci.id, ci.cart_id, ci.product_id, ci.quantity, ci.created_at, ci.updated_at,
       p.id, p.code, p.name, p.selling_price, p.image
FROM cart_items ci
JOIN products p ON ci.product_id = p.id
WHERE ci.cart_id = $1
ORDER BY ci.created_at ASC
`

type ListCartItemsByCartIDRow struct {
	ID           int64              `json:"id"`
	CartID       int64              `json:"cart_id"`
	ProductID    int64              `json:"product_id"`
	Quantity     decimal.Decimal    `json:"quantity"`
	CreatedAt    pgtype.Timestamptz `json:"created_at"`
	UpdatedAt    pgtype.Timestamptz `json:"updated_at"`
	ID_2         int64              `json:"id_2"`
	Code         string             `json:"code"`
	Name         string             `json:"name"`
	SellingPrice decimal.Decimal    `json:"selling_price"`
	Image        pgtype.Text        `json:"image"`
}

func (q *Queries) ListCartItemsByCartID(ctx context.Context, cartID int64) ([]ListCartItemsByCartIDRow, error) {
	rows, err := q.db.Query(ctx, listCartItemsByCartID, cartID)
	if err != nil {
		return nil, err
	}
	defer rows.Close()
	var items []ListCartItemsByCartIDRow
	for rows.Next() {
		var i ListCartItemsByCartIDRow
		if err := rows.Scan(
			&i.ID,
			&i.CartID,
			&i.ProductID,
			&i.Quantity,
			&i.CreatedAt,
			&i.UpdatedAt,
			&i.ID_2,
			&i.Code,
			&i.Name,
			&i.SellingPrice,
			&i.Image,
		); err != nil {
			return nil, err
		}
		items = append(items, i)
	}
	if err := rows.Err(); err != nil {
		return nil, err
	}
	return items, nil
}

const productExistsByID = `-- name: ProductExistsByID :one
SELECT EXISTS(SELECT 1 FROM products WHERE id = $1 AND deleted_at IS NULL)
`

func (q *Queries) ProductExistsByID(ctx context.Context, id int64) (bool, error) {
	row := q.db.QueryRow(ctx, productExistsByID, id)
	var exists bool
	err := row.Scan(&exists)
	return exists, err
}

const productIDBySKU = `-- name: ProductIDBySKU :one
SELECT id FROM products WHERE code = $1 AND deleted_at IS NULL
`

func (q *Queries) ProductIDBySKU(ctx context.Context, code string) (int64, error) {
	row := q.db.QueryRow(ctx, productIDBySKU, code)
	var id int64
	err := row.Scan(&id)
	return id, err
}

const updateCartItemQuantity = `-- name: UpdateCartItemQuantity :execrows
UPDATE cart_items
SET quantity = $3, updated_at = now()
WHERE cart_id = $1 AND product_id = $2
`

type UpdateCartItemQuantityParams struct {
	CartID    int64           `json:"cart_id"`
	ProductID int64           `json:"product_id"`
	Quantity  decimal.Decimal `json:"quantity"`
}

func (q *Queries) UpdateCartItemQuantity(ctx context.Context, arg UpdateCartItemQuantityParams) (int64, error) {
	result, err := q.db.Exec(ctx, updateCartItemQuantity, arg.CartID, arg.ProductID, arg.Quantity)
	if err != nil {
		return 0, err
	}
	return result.RowsAffected(), nil
}
