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

package db

import (
	"context"

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

const countStoresByWarehouse = `-- name: CountStoresByWarehouse :one
SELECT count(*) FROM stores WHERE warehouse_id = $1
`

// Stores own their outlet warehouse: deleting the last store bound to a
// warehouse must retire the warehouse too, or it lingers in checkout pickers
// (B2B + POS read active-only options) with no store behind it.
func (q *Queries) CountStoresByWarehouse(ctx context.Context, warehouseID int64) (int64, error) {
	row := q.db.QueryRow(ctx, countStoresByWarehouse, warehouseID)
	var count int64
	err := row.Scan(&count)
	return count, err
}

const countWarehouses = `-- name: CountWarehouses :one
SELECT count(*) FROM warehouses
WHERE $1 = '' OR (name ILIKE '%' || $1 || '%' OR code ILIKE '%' || $1 || '%')
`

func (q *Queries) CountWarehouses(ctx context.Context, dollar_1 interface{}) (int64, error) {
	row := q.db.QueryRow(ctx, countWarehouses, dollar_1)
	var count int64
	err := row.Scan(&count)
	return count, err
}

const createWarehouse = `-- name: CreateWarehouse :one
INSERT INTO warehouses (code, name, address, is_active, latitude, longitude) VALUES ($1, $2, $3, $4, $5, $6) RETURNING id
`

type CreateWarehouseParams struct {
	Code      string              `json:"code"`
	Name      string              `json:"name"`
	Address   pgtype.Text         `json:"address"`
	IsActive  bool                `json:"is_active"`
	Latitude  decimal.NullDecimal `json:"latitude"`
	Longitude decimal.NullDecimal `json:"longitude"`
}

func (q *Queries) CreateWarehouse(ctx context.Context, arg CreateWarehouseParams) (int64, error) {
	row := q.db.QueryRow(ctx, createWarehouse,
		arg.Code,
		arg.Name,
		arg.Address,
		arg.IsActive,
		arg.Latitude,
		arg.Longitude,
	)
	var id int64
	err := row.Scan(&id)
	return id, err
}

const deactivateWarehouse = `-- name: DeactivateWarehouse :execrows
UPDATE warehouses SET is_active = false, updated_at = now() WHERE id = $1
`

func (q *Queries) DeactivateWarehouse(ctx context.Context, id int64) (int64, error) {
	result, err := q.db.Exec(ctx, deactivateWarehouse, id)
	if err != nil {
		return 0, err
	}
	return result.RowsAffected(), nil
}

const deleteWarehouse = `-- name: DeleteWarehouse :execrows
DELETE FROM warehouses WHERE id = $1
`

func (q *Queries) DeleteWarehouse(ctx context.Context, id int64) (int64, error) {
	result, err := q.db.Exec(ctx, deleteWarehouse, id)
	if err != nil {
		return 0, err
	}
	return result.RowsAffected(), nil
}

const getWarehouseByID = `-- name: GetWarehouseByID :one
SELECT id, code, name, address, is_active, latitude, longitude FROM warehouses WHERE id = $1
`

type GetWarehouseByIDRow struct {
	ID        int64               `json:"id"`
	Code      string              `json:"code"`
	Name      string              `json:"name"`
	Address   pgtype.Text         `json:"address"`
	IsActive  bool                `json:"is_active"`
	Latitude  decimal.NullDecimal `json:"latitude"`
	Longitude decimal.NullDecimal `json:"longitude"`
}

func (q *Queries) GetWarehouseByID(ctx context.Context, id int64) (GetWarehouseByIDRow, error) {
	row := q.db.QueryRow(ctx, getWarehouseByID, id)
	var i GetWarehouseByIDRow
	err := row.Scan(
		&i.ID,
		&i.Code,
		&i.Name,
		&i.Address,
		&i.IsActive,
		&i.Latitude,
		&i.Longitude,
	)
	return i, err
}

const listWarehouseLocations = `-- name: ListWarehouseLocations :many
SELECT id, code, name, address, city, is_active, latitude, longitude, coordinate_precision FROM warehouses ORDER BY id
`

type ListWarehouseLocationsRow struct {
	ID                  int64               `json:"id"`
	Code                string              `json:"code"`
	Name                string              `json:"name"`
	Address             pgtype.Text         `json:"address"`
	City                pgtype.Text         `json:"city"`
	IsActive            bool                `json:"is_active"`
	Latitude            decimal.NullDecimal `json:"latitude"`
	Longitude           decimal.NullDecimal `json:"longitude"`
	CoordinatePrecision pgtype.Text         `json:"coordinate_precision"`
}

func (q *Queries) ListWarehouseLocations(ctx context.Context) ([]ListWarehouseLocationsRow, error) {
	rows, err := q.db.Query(ctx, listWarehouseLocations)
	if err != nil {
		return nil, err
	}
	defer rows.Close()
	var items []ListWarehouseLocationsRow
	for rows.Next() {
		var i ListWarehouseLocationsRow
		if err := rows.Scan(
			&i.ID,
			&i.Code,
			&i.Name,
			&i.Address,
			&i.City,
			&i.IsActive,
			&i.Latitude,
			&i.Longitude,
			&i.CoordinatePrecision,
		); err != nil {
			return nil, err
		}
		items = append(items, i)
	}
	if err := rows.Err(); err != nil {
		return nil, err
	}
	return items, nil
}

const listWarehouseOptions = `-- name: ListWarehouseOptions :many
SELECT w.id, w.code, w.name, w.latitude, w.longitude
FROM warehouses w
WHERE w.is_active = true
  AND EXISTS (SELECT 1 FROM stores s WHERE s.warehouse_id = w.id AND s.is_active = true)
ORDER BY w.code
`

type ListWarehouseOptionsRow struct {
	ID        int64               `json:"id"`
	Code      string              `json:"code"`
	Name      string              `json:"name"`
	Latitude  decimal.NullDecimal `json:"latitude"`
	Longitude decimal.NullDecimal `json:"longitude"`
}

func (q *Queries) ListWarehouseOptions(ctx context.Context) ([]ListWarehouseOptionsRow, error) {
	rows, err := q.db.Query(ctx, listWarehouseOptions)
	if err != nil {
		return nil, err
	}
	defer rows.Close()
	var items []ListWarehouseOptionsRow
	for rows.Next() {
		var i ListWarehouseOptionsRow
		if err := rows.Scan(
			&i.ID,
			&i.Code,
			&i.Name,
			&i.Latitude,
			&i.Longitude,
		); err != nil {
			return nil, err
		}
		items = append(items, i)
	}
	if err := rows.Err(); err != nil {
		return nil, err
	}
	return items, nil
}

const listWarehouses = `-- name: ListWarehouses :many
SELECT id, code, name, address, is_active
FROM warehouses
WHERE $1 = '' OR (name ILIKE '%' || $1 || '%' OR code ILIKE '%' || $1 || '%')
ORDER BY code
LIMIT $2 OFFSET $3
`

type ListWarehousesParams struct {
	Column1 interface{} `json:"column_1"`
	Limit   int32       `json:"limit"`
	Offset  int32       `json:"offset"`
}

type ListWarehousesRow struct {
	ID       int64       `json:"id"`
	Code     string      `json:"code"`
	Name     string      `json:"name"`
	Address  pgtype.Text `json:"address"`
	IsActive bool        `json:"is_active"`
}

func (q *Queries) ListWarehouses(ctx context.Context, arg ListWarehousesParams) ([]ListWarehousesRow, error) {
	rows, err := q.db.Query(ctx, listWarehouses, arg.Column1, arg.Limit, arg.Offset)
	if err != nil {
		return nil, err
	}
	defer rows.Close()
	var items []ListWarehousesRow
	for rows.Next() {
		var i ListWarehousesRow
		if err := rows.Scan(
			&i.ID,
			&i.Code,
			&i.Name,
			&i.Address,
			&i.IsActive,
		); err != nil {
			return nil, err
		}
		items = append(items, i)
	}
	if err := rows.Err(); err != nil {
		return nil, err
	}
	return items, nil
}

const updateWarehouse = `-- name: UpdateWarehouse :execrows
UPDATE warehouses SET name = $2, address = $3, is_active = $4, latitude = $5, longitude = $6 WHERE id = $1
`

type UpdateWarehouseParams struct {
	ID        int64               `json:"id"`
	Name      string              `json:"name"`
	Address   pgtype.Text         `json:"address"`
	IsActive  bool                `json:"is_active"`
	Latitude  decimal.NullDecimal `json:"latitude"`
	Longitude decimal.NullDecimal `json:"longitude"`
}

func (q *Queries) UpdateWarehouse(ctx context.Context, arg UpdateWarehouseParams) (int64, error) {
	result, err := q.db.Exec(ctx, updateWarehouse,
		arg.ID,
		arg.Name,
		arg.Address,
		arg.IsActive,
		arg.Latitude,
		arg.Longitude,
	)
	if err != nil {
		return 0, err
	}
	return result.RowsAffected(), nil
}

const warehouseHasInventory = `-- name: WarehouseHasInventory :one
SELECT EXISTS(
  SELECT 1 FROM stocks WHERE stocks.warehouse_id = $1 AND stocks.quantity <> 0
  UNION ALL SELECT 1 FROM stock_movements WHERE stock_movements.warehouse_id = $1
  UNION ALL SELECT 1 FROM stock_opnames WHERE stock_opnames.warehouse_id = $1
  UNION ALL SELECT 1 FROM stock_transfers WHERE stock_transfers.from_warehouse_id = $1 OR stock_transfers.to_warehouse_id = $1
  UNION ALL SELECT 1 FROM sales_orders WHERE sales_orders.warehouse_id = $1
  UNION ALL SELECT 1 FROM purchase_orders WHERE purchase_orders.warehouse_id = $1
  UNION ALL SELECT 1 FROM delivery_orders WHERE delivery_orders.warehouse_id = $1
  UNION ALL SELECT 1 FROM goods_receipts WHERE goods_receipts.warehouse_id = $1
  UNION ALL SELECT 1 FROM sales_returns WHERE sales_returns.warehouse_id = $1
)
`

// True when the warehouse cannot simply be deleted: stock on hand or any
// transactional footprint. Callers deactivate instead, which hides it from
// pickers while keeping history intact.
func (q *Queries) WarehouseHasInventory(ctx context.Context, warehouseID int64) (bool, error) {
	row := q.db.QueryRow(ctx, warehouseHasInventory, warehouseID)
	var exists bool
	err := row.Scan(&exists)
	return exists, err
}
