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

package db

import (
	"context"

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

const closeCashierShift = `-- name: CloseCashierShift :execrows
UPDATE cashier_shifts
SET status='closed', closed_at=now(), actual_cash=$2, variance=$3, updated_at=now()
WHERE id=$1
`

type CloseCashierShiftParams struct {
	ID         int64               `json:"id"`
	ActualCash decimal.NullDecimal `json:"actual_cash"`
	Variance   decimal.NullDecimal `json:"variance"`
}

func (q *Queries) CloseCashierShift(ctx context.Context, arg CloseCashierShiftParams) (int64, error) {
	result, err := q.db.Exec(ctx, closeCashierShift, arg.ID, arg.ActualCash, arg.Variance)
	if err != nil {
		return 0, err
	}
	return result.RowsAffected(), nil
}

const countCashierShifts = `-- name: CountCashierShifts :one
SELECT count(*) FROM cashier_shifts
WHERE ($1::bigint IS NULL OR $1::bigint <= 0 OR cashier_id = $1)
  AND ($2::text IS NULL OR status = $2)
  AND ($3::bigint[] IS NULL OR (store_id IS NOT NULL AND store_id = ANY($3)))
`

type CountCashierShiftsParams struct {
	CashierID       pgtype.Int8 `json:"cashier_id"`
	Status          pgtype.Text `json:"status"`
	AllowedStoreIds []int64     `json:"allowed_store_ids"`
}

func (q *Queries) CountCashierShifts(ctx context.Context, arg CountCashierShiftsParams) (int64, error) {
	row := q.db.QueryRow(ctx, countCashierShifts, arg.CashierID, arg.Status, arg.AllowedStoreIds)
	var count int64
	err := row.Scan(&count)
	return count, err
}

const countOrdersByShift = `-- name: CountOrdersByShift :one
SELECT COUNT(*)::bigint AS total
FROM sales_orders WHERE shift_id=$1 AND status <> 'cancelled'
`

func (q *Queries) CountOrdersByShift(ctx context.Context, shiftID pgtype.Int8) (int64, error) {
	row := q.db.QueryRow(ctx, countOrdersByShift, shiftID)
	var total int64
	err := row.Scan(&total)
	return total, err
}

const createCashierShift = `-- name: CreateCashierShift :one
INSERT INTO cashier_shifts (shift_number, cashier_id, status, opening_cash, notes, store_id)
VALUES ($1,$2,'open',$3,$4,$5)
RETURNING id, shift_number, cashier_id, status, opened_at, opening_cash, closed_at, actual_cash, variance, notes, register_id, store_id, created_at, updated_at
`

type CreateCashierShiftParams struct {
	ShiftNumber string          `json:"shift_number"`
	CashierID   int64           `json:"cashier_id"`
	OpeningCash decimal.Decimal `json:"opening_cash"`
	Notes       pgtype.Text     `json:"notes"`
	StoreID     pgtype.Int8     `json:"store_id"`
}

func (q *Queries) CreateCashierShift(ctx context.Context, arg CreateCashierShiftParams) (CashierShift, error) {
	row := q.db.QueryRow(ctx, createCashierShift,
		arg.ShiftNumber,
		arg.CashierID,
		arg.OpeningCash,
		arg.Notes,
		arg.StoreID,
	)
	var i CashierShift
	err := row.Scan(
		&i.ID,
		&i.ShiftNumber,
		&i.CashierID,
		&i.Status,
		&i.OpenedAt,
		&i.OpeningCash,
		&i.ClosedAt,
		&i.ActualCash,
		&i.Variance,
		&i.Notes,
		&i.RegisterID,
		&i.StoreID,
		&i.CreatedAt,
		&i.UpdatedAt,
	)
	return i, err
}

const createDrawerEntry = `-- name: CreateDrawerEntry :one
INSERT INTO cashier_drawer_entries (shift_id, type, amount, notes, created_by)
VALUES ($1,$2,$3,$4,$5)
RETURNING id, shift_id, type, amount, notes, created_by, created_at
`

type CreateDrawerEntryParams struct {
	ShiftID   int64           `json:"shift_id"`
	Type      string          `json:"type"`
	Amount    decimal.Decimal `json:"amount"`
	Notes     pgtype.Text     `json:"notes"`
	CreatedBy pgtype.Int8     `json:"created_by"`
}

func (q *Queries) CreateDrawerEntry(ctx context.Context, arg CreateDrawerEntryParams) (CashierDrawerEntry, error) {
	row := q.db.QueryRow(ctx, createDrawerEntry,
		arg.ShiftID,
		arg.Type,
		arg.Amount,
		arg.Notes,
		arg.CreatedBy,
	)
	var i CashierDrawerEntry
	err := row.Scan(
		&i.ID,
		&i.ShiftID,
		&i.Type,
		&i.Amount,
		&i.Notes,
		&i.CreatedBy,
		&i.CreatedAt,
	)
	return i, err
}

const getCashierShiftByID = `-- name: GetCashierShiftByID :one
SELECT id, shift_number, cashier_id, status, opened_at, opening_cash, closed_at, actual_cash, variance, notes, register_id, store_id, created_at, updated_at
FROM cashier_shifts WHERE id=$1
`

func (q *Queries) GetCashierShiftByID(ctx context.Context, id int64) (CashierShift, error) {
	row := q.db.QueryRow(ctx, getCashierShiftByID, id)
	var i CashierShift
	err := row.Scan(
		&i.ID,
		&i.ShiftNumber,
		&i.CashierID,
		&i.Status,
		&i.OpenedAt,
		&i.OpeningCash,
		&i.ClosedAt,
		&i.ActualCash,
		&i.Variance,
		&i.Notes,
		&i.RegisterID,
		&i.StoreID,
		&i.CreatedAt,
		&i.UpdatedAt,
	)
	return i, err
}

const getCashierShiftByIDForUpdate = `-- name: GetCashierShiftByIDForUpdate :one
SELECT id, shift_number, cashier_id, status, opened_at, opening_cash, closed_at, actual_cash, variance, notes, register_id, store_id, created_at, updated_at
FROM cashier_shifts WHERE id=$1 FOR UPDATE
`

func (q *Queries) GetCashierShiftByIDForUpdate(ctx context.Context, id int64) (CashierShift, error) {
	row := q.db.QueryRow(ctx, getCashierShiftByIDForUpdate, id)
	var i CashierShift
	err := row.Scan(
		&i.ID,
		&i.ShiftNumber,
		&i.CashierID,
		&i.Status,
		&i.OpenedAt,
		&i.OpeningCash,
		&i.ClosedAt,
		&i.ActualCash,
		&i.Variance,
		&i.Notes,
		&i.RegisterID,
		&i.StoreID,
		&i.CreatedAt,
		&i.UpdatedAt,
	)
	return i, err
}

const getOpenShiftByCashier = `-- name: GetOpenShiftByCashier :one
SELECT id, shift_number, cashier_id, status, opened_at, opening_cash, closed_at, actual_cash, variance, notes, register_id, store_id, created_at, updated_at
FROM cashier_shifts WHERE cashier_id=$1 AND status='open' LIMIT 1
`

func (q *Queries) GetOpenShiftByCashier(ctx context.Context, cashierID int64) (CashierShift, error) {
	row := q.db.QueryRow(ctx, getOpenShiftByCashier, cashierID)
	var i CashierShift
	err := row.Scan(
		&i.ID,
		&i.ShiftNumber,
		&i.CashierID,
		&i.Status,
		&i.OpenedAt,
		&i.OpeningCash,
		&i.ClosedAt,
		&i.ActualCash,
		&i.Variance,
		&i.Notes,
		&i.RegisterID,
		&i.StoreID,
		&i.CreatedAt,
		&i.UpdatedAt,
	)
	return i, err
}

const listCashierShifts = `-- name: ListCashierShifts :many
SELECT cs.id, cs.shift_number, cs.cashier_id, cs.status, cs.opened_at, cs.opening_cash, cs.closed_at, cs.actual_cash, cs.variance, cs.notes, cs.register_id, cs.store_id, cs.created_at, cs.updated_at,
       COALESCE(u.name, '') AS cashier_name
FROM cashier_shifts cs
LEFT JOIN users u ON u.id = cs.cashier_id
WHERE ($3::bigint IS NULL OR $3::bigint <= 0 OR cs.cashier_id = $3)
  AND ($4::text IS NULL OR cs.status = $4)
  AND ($5::bigint[] IS NULL OR (cs.store_id IS NOT NULL AND cs.store_id = ANY($5)))
ORDER BY cs.id DESC
LIMIT $1 OFFSET $2
`

type ListCashierShiftsParams struct {
	Limit           int32       `json:"limit"`
	Offset          int32       `json:"offset"`
	CashierID       pgtype.Int8 `json:"cashier_id"`
	Status          pgtype.Text `json:"status"`
	AllowedStoreIds []int64     `json:"allowed_store_ids"`
}

type ListCashierShiftsRow struct {
	ID          int64               `json:"id"`
	ShiftNumber string              `json:"shift_number"`
	CashierID   int64               `json:"cashier_id"`
	Status      string              `json:"status"`
	OpenedAt    pgtype.Timestamptz  `json:"opened_at"`
	OpeningCash decimal.Decimal     `json:"opening_cash"`
	ClosedAt    pgtype.Timestamptz  `json:"closed_at"`
	ActualCash  decimal.NullDecimal `json:"actual_cash"`
	Variance    decimal.NullDecimal `json:"variance"`
	Notes       pgtype.Text         `json:"notes"`
	RegisterID  pgtype.Int8         `json:"register_id"`
	StoreID     pgtype.Int8         `json:"store_id"`
	CreatedAt   pgtype.Timestamptz  `json:"created_at"`
	UpdatedAt   pgtype.Timestamptz  `json:"updated_at"`
	CashierName string              `json:"cashier_name"`
}

func (q *Queries) ListCashierShifts(ctx context.Context, arg ListCashierShiftsParams) ([]ListCashierShiftsRow, error) {
	rows, err := q.db.Query(ctx, listCashierShifts,
		arg.Limit,
		arg.Offset,
		arg.CashierID,
		arg.Status,
		arg.AllowedStoreIds,
	)
	if err != nil {
		return nil, err
	}
	defer rows.Close()
	var items []ListCashierShiftsRow
	for rows.Next() {
		var i ListCashierShiftsRow
		if err := rows.Scan(
			&i.ID,
			&i.ShiftNumber,
			&i.CashierID,
			&i.Status,
			&i.OpenedAt,
			&i.OpeningCash,
			&i.ClosedAt,
			&i.ActualCash,
			&i.Variance,
			&i.Notes,
			&i.RegisterID,
			&i.StoreID,
			&i.CreatedAt,
			&i.UpdatedAt,
			&i.CashierName,
		); err != nil {
			return nil, err
		}
		items = append(items, i)
	}
	if err := rows.Err(); err != nil {
		return nil, err
	}
	return items, nil
}

const listDrawerEntries = `-- name: ListDrawerEntries :many
SELECT id, shift_id, type, amount, notes, created_by, created_at
FROM cashier_drawer_entries WHERE shift_id=$1 ORDER BY id
`

func (q *Queries) ListDrawerEntries(ctx context.Context, shiftID int64) ([]CashierDrawerEntry, error) {
	rows, err := q.db.Query(ctx, listDrawerEntries, shiftID)
	if err != nil {
		return nil, err
	}
	defer rows.Close()
	var items []CashierDrawerEntry
	for rows.Next() {
		var i CashierDrawerEntry
		if err := rows.Scan(
			&i.ID,
			&i.ShiftID,
			&i.Type,
			&i.Amount,
			&i.Notes,
			&i.CreatedBy,
			&i.CreatedAt,
		); err != nil {
			return nil, err
		}
		items = append(items, i)
	}
	if err := rows.Err(); err != nil {
		return nil, err
	}
	return items, nil
}

const setSalesOrderShift = `-- name: SetSalesOrderShift :execrows
UPDATE sales_orders SET shift_id=$2, updated_at=now() WHERE id=$1
`

type SetSalesOrderShiftParams struct {
	ID      int64       `json:"id"`
	ShiftID pgtype.Int8 `json:"shift_id"`
}

func (q *Queries) SetSalesOrderShift(ctx context.Context, arg SetSalesOrderShiftParams) (int64, error) {
	result, err := q.db.Exec(ctx, setSalesOrderShift, arg.ID, arg.ShiftID)
	if err != nil {
		return 0, err
	}
	return result.RowsAffected(), nil
}

const setShiftBinding = `-- name: SetShiftBinding :one
UPDATE cashier_shifts
SET register_id=$2, store_id=$3, updated_at=now()
WHERE id=$1
RETURNING id, shift_number, cashier_id, status, opened_at, opening_cash, closed_at, actual_cash, variance, notes, register_id, store_id, created_at, updated_at
`

type SetShiftBindingParams struct {
	ID         int64       `json:"id"`
	RegisterID pgtype.Int8 `json:"register_id"`
	StoreID    pgtype.Int8 `json:"store_id"`
}

func (q *Queries) SetShiftBinding(ctx context.Context, arg SetShiftBindingParams) (CashierShift, error) {
	row := q.db.QueryRow(ctx, setShiftBinding, arg.ID, arg.RegisterID, arg.StoreID)
	var i CashierShift
	err := row.Scan(
		&i.ID,
		&i.ShiftNumber,
		&i.CashierID,
		&i.Status,
		&i.OpenedAt,
		&i.OpeningCash,
		&i.ClosedAt,
		&i.ActualCash,
		&i.Variance,
		&i.Notes,
		&i.RegisterID,
		&i.StoreID,
		&i.CreatedAt,
		&i.UpdatedAt,
	)
	return i, err
}

const sumCashSalesByShift = `-- name: SumCashSalesByShift :one
SELECT COALESCE(SUM(p.amount),0)::numeric AS total
FROM payments p
JOIN invoices inv ON inv.id = p.payable_id AND (p.payable_type = 'App\Models\Invoice' OR p.payable_type = 'invoice')
JOIN sales_orders so ON so.id = inv.sales_order_id
WHERE so.shift_id = $1 AND p.payment_method IN ('cash', 'tunai') AND so.status <> 'cancelled'
`

func (q *Queries) SumCashSalesByShift(ctx context.Context, shiftID pgtype.Int8) (decimal.Decimal, error) {
	row := q.db.QueryRow(ctx, sumCashSalesByShift, shiftID)
	var total decimal.Decimal
	err := row.Scan(&total)
	return total, err
}

const sumDrawerByShift = `-- name: SumDrawerByShift :many
SELECT type, COALESCE(SUM(amount),0)::numeric AS total
FROM cashier_drawer_entries WHERE shift_id=$1 GROUP BY type
`

type SumDrawerByShiftRow struct {
	Type  string          `json:"type"`
	Total decimal.Decimal `json:"total"`
}

func (q *Queries) SumDrawerByShift(ctx context.Context, shiftID int64) ([]SumDrawerByShiftRow, error) {
	rows, err := q.db.Query(ctx, sumDrawerByShift, shiftID)
	if err != nil {
		return nil, err
	}
	defer rows.Close()
	var items []SumDrawerByShiftRow
	for rows.Next() {
		var i SumDrawerByShiftRow
		if err := rows.Scan(&i.Type, &i.Total); err != nil {
			return nil, err
		}
		items = append(items, i)
	}
	if err := rows.Err(); err != nil {
		return nil, err
	}
	return items, nil
}

const sumDrawerByShifts = `-- name: SumDrawerByShifts :many
SELECT shift_id, type, COALESCE(SUM(amount),0)::numeric AS total
FROM cashier_drawer_entries WHERE shift_id = ANY($1::bigint[]) GROUP BY shift_id, type
`

type SumDrawerByShiftsRow struct {
	ShiftID int64           `json:"shift_id"`
	Type    string          `json:"type"`
	Total   decimal.Decimal `json:"total"`
}

func (q *Queries) SumDrawerByShifts(ctx context.Context, dollar_1 []int64) ([]SumDrawerByShiftsRow, error) {
	rows, err := q.db.Query(ctx, sumDrawerByShifts, dollar_1)
	if err != nil {
		return nil, err
	}
	defer rows.Close()
	var items []SumDrawerByShiftsRow
	for rows.Next() {
		var i SumDrawerByShiftsRow
		if err := rows.Scan(&i.ShiftID, &i.Type, &i.Total); err != nil {
			return nil, err
		}
		items = append(items, i)
	}
	if err := rows.Err(); err != nil {
		return nil, err
	}
	return items, nil
}

const sumNonCashSalesByShift = `-- name: SumNonCashSalesByShift :one
SELECT COALESCE(SUM(p.amount),0)::numeric AS total
FROM payments p
JOIN invoices inv ON inv.id = p.payable_id AND (p.payable_type = 'App\Models\Invoice' OR p.payable_type = 'invoice')
JOIN sales_orders so ON so.id = inv.sales_order_id
WHERE so.shift_id = $1 AND p.payment_method NOT IN ('cash', 'tunai') AND so.status <> 'cancelled'
`

func (q *Queries) SumNonCashSalesByShift(ctx context.Context, shiftID pgtype.Int8) (decimal.Decimal, error) {
	row := q.db.QueryRow(ctx, sumNonCashSalesByShift, shiftID)
	var total decimal.Decimal
	err := row.Scan(&total)
	return total, err
}
