// Code generated by sqlc. DO NOT EDIT.
// versions:
//   sqlc v1.29.0
// source: tenant_limits.sql

package sqlcv1

import (
	"context"

	"github.com/google/uuid"
	"github.com/jackc/pgx/v5/pgtype"
)

const countTenantWorkers = `-- name: CountTenantWorkers :one
SELECT COUNT(distinct id) AS "count"
FROM "Worker"
WHERE "tenantId" = $1::uuid
AND "lastHeartbeatAt" >= NOW() - '30 seconds'::INTERVAL
AND "isActive" = true
`

func (q *Queries) CountTenantWorkers(ctx context.Context, db DBTX, tenantid uuid.UUID) (int64, error) {
	row := db.QueryRow(ctx, countTenantWorkers, tenantid)
	var count int64
	err := row.Scan(&count)
	return count, err
}

const getTenantResourceLimit = `-- name: GetTenantResourceLimit :one
WITH updated AS (
    UPDATE "TenantResourceLimit"
    SET
        "value" = 0, -- Reset to 0 if the window has passed
        "lastRefill" = CURRENT_TIMESTAMP -- Update lastRefill if the window has passed
    WHERE "tenantId" = $1::uuid
      AND (("window" IS NOT NULL AND "window" != '' AND NOW() - "lastRefill" >= "window"::INTERVAL))
      AND "resource" = $2::"LimitResource"
      AND "customValueMeter" = false
    RETURNING id, "createdAt", "updatedAt", resource, "tenantId", "limitValue", "alarmValue", value, "window", "lastRefill", "customValueMeter"
)
SELECT id, "createdAt", "updatedAt", resource, "tenantId", "limitValue", "alarmValue", value, "window", "lastRefill", "customValueMeter" FROM updated
UNION ALL
SELECT id, "createdAt", "updatedAt", resource, "tenantId", "limitValue", "alarmValue", value, "window", "lastRefill", "customValueMeter" FROM "TenantResourceLimit"
WHERE "tenantId" = $1::uuid
    AND "resource" = $2::"LimitResource"
    AND NOT EXISTS (SELECT 1 FROM updated)
`

type GetTenantResourceLimitParams struct {
	Tenantid uuid.UUID         `json:"tenantid"`
	Resource NullLimitResource `json:"resource"`
}

type GetTenantResourceLimitRow struct {
	ID               uuid.UUID        `json:"id"`
	CreatedAt        pgtype.Timestamp `json:"createdAt"`
	UpdatedAt        pgtype.Timestamp `json:"updatedAt"`
	Resource         LimitResource    `json:"resource"`
	TenantId         uuid.UUID        `json:"tenantId"`
	LimitValue       int32            `json:"limitValue"`
	AlarmValue       pgtype.Int4      `json:"alarmValue"`
	Value            int32            `json:"value"`
	Window           pgtype.Text      `json:"window"`
	LastRefill       pgtype.Timestamp `json:"lastRefill"`
	CustomValueMeter bool             `json:"customValueMeter"`
}

func (q *Queries) GetTenantResourceLimit(ctx context.Context, db DBTX, arg GetTenantResourceLimitParams) (*GetTenantResourceLimitRow, error) {
	row := db.QueryRow(ctx, getTenantResourceLimit, arg.Tenantid, arg.Resource)
	var i GetTenantResourceLimitRow
	err := row.Scan(
		&i.ID,
		&i.CreatedAt,
		&i.UpdatedAt,
		&i.Resource,
		&i.TenantId,
		&i.LimitValue,
		&i.AlarmValue,
		&i.Value,
		&i.Window,
		&i.LastRefill,
		&i.CustomValueMeter,
	)
	return &i, err
}

const listTenantResourceLimits = `-- name: ListTenantResourceLimits :many
SELECT id, "createdAt", "updatedAt", resource, "tenantId", "limitValue", "alarmValue", value, "window", "lastRefill", "customValueMeter" FROM "TenantResourceLimit"
WHERE "tenantId" = $1::uuid
`

func (q *Queries) ListTenantResourceLimits(ctx context.Context, db DBTX, tenantid uuid.UUID) ([]*TenantResourceLimit, error) {
	rows, err := db.Query(ctx, listTenantResourceLimits, tenantid)
	if err != nil {
		return nil, err
	}
	defer rows.Close()
	var items []*TenantResourceLimit
	for rows.Next() {
		var i TenantResourceLimit
		if err := rows.Scan(
			&i.ID,
			&i.CreatedAt,
			&i.UpdatedAt,
			&i.Resource,
			&i.TenantId,
			&i.LimitValue,
			&i.AlarmValue,
			&i.Value,
			&i.Window,
			&i.LastRefill,
			&i.CustomValueMeter,
		); err != nil {
			return nil, err
		}
		items = append(items, &i)
	}
	if err := rows.Err(); err != nil {
		return nil, err
	}
	return items, nil
}

const meterTenantResource = `-- name: MeterTenantResource :one
UPDATE "TenantResourceLimit"
SET
    "value" = CASE
        WHEN ("customValueMeter" = true OR ("window" IS NOT NULL AND "window" != '' AND NOW() - "lastRefill" >= "window"::INTERVAL)) THEN
            0 -- Refill to 0 since the window has passed
        ELSE
            "value" + $1::int -- Increment the current value within the window by the number of resources
    END,
    "lastRefill" = CASE
        WHEN ("window" IS NOT NULL AND "window" != '' AND NOW() - "lastRefill" >= "window"::INTERVAL) THEN
            CURRENT_TIMESTAMP -- Update lastRefill if the window has passed
        ELSE
            "lastRefill" -- Keep the lastRefill unchanged if within the window
    END
WHERE "tenantId" = $2::uuid
    AND "resource" = $3::"LimitResource"
RETURNING id, "createdAt", "updatedAt", resource, "tenantId", "limitValue", "alarmValue", value, "window", "lastRefill", "customValueMeter"
`

type MeterTenantResourceParams struct {
	Numresources int32             `json:"numresources"`
	Tenantid     uuid.UUID         `json:"tenantid"`
	Resource     NullLimitResource `json:"resource"`
}

func (q *Queries) MeterTenantResource(ctx context.Context, db DBTX, arg MeterTenantResourceParams) (*TenantResourceLimit, error) {
	row := db.QueryRow(ctx, meterTenantResource, arg.Numresources, arg.Tenantid, arg.Resource)
	var i TenantResourceLimit
	err := row.Scan(
		&i.ID,
		&i.CreatedAt,
		&i.UpdatedAt,
		&i.Resource,
		&i.TenantId,
		&i.LimitValue,
		&i.AlarmValue,
		&i.Value,
		&i.Window,
		&i.LastRefill,
		&i.CustomValueMeter,
	)
	return &i, err
}

const resolveAllLimitsIfWindowPassed = `-- name: ResolveAllLimitsIfWindowPassed :many
WITH resolved_limits AS (
    UPDATE "TenantResourceLimit"
    SET
        "value" = 0, -- Reset value to 0
        "lastRefill" = CURRENT_TIMESTAMP -- Update lastRefill timestamp
    WHERE
        ("window" IS NOT NULL AND "window" != '' AND NOW() - "lastRefill" >= "window"::INTERVAL)
    RETURNING id, "createdAt", "updatedAt", resource, "tenantId", "limitValue", "alarmValue", value, "window", "lastRefill", "customValueMeter"
)
SELECT id, "createdAt", "updatedAt", resource, "tenantId", "limitValue", "alarmValue", value, "window", "lastRefill", "customValueMeter"
FROM resolved_limits
`

type ResolveAllLimitsIfWindowPassedRow struct {
	ID               uuid.UUID        `json:"id"`
	CreatedAt        pgtype.Timestamp `json:"createdAt"`
	UpdatedAt        pgtype.Timestamp `json:"updatedAt"`
	Resource         LimitResource    `json:"resource"`
	TenantId         uuid.UUID        `json:"tenantId"`
	LimitValue       int32            `json:"limitValue"`
	AlarmValue       pgtype.Int4      `json:"alarmValue"`
	Value            int32            `json:"value"`
	Window           pgtype.Text      `json:"window"`
	LastRefill       pgtype.Timestamp `json:"lastRefill"`
	CustomValueMeter bool             `json:"customValueMeter"`
}

func (q *Queries) ResolveAllLimitsIfWindowPassed(ctx context.Context, db DBTX) ([]*ResolveAllLimitsIfWindowPassedRow, error) {
	rows, err := db.Query(ctx, resolveAllLimitsIfWindowPassed)
	if err != nil {
		return nil, err
	}
	defer rows.Close()
	var items []*ResolveAllLimitsIfWindowPassedRow
	for rows.Next() {
		var i ResolveAllLimitsIfWindowPassedRow
		if err := rows.Scan(
			&i.ID,
			&i.CreatedAt,
			&i.UpdatedAt,
			&i.Resource,
			&i.TenantId,
			&i.LimitValue,
			&i.AlarmValue,
			&i.Value,
			&i.Window,
			&i.LastRefill,
			&i.CustomValueMeter,
		); err != nil {
			return nil, err
		}
		items = append(items, &i)
	}
	if err := rows.Err(); err != nil {
		return nil, err
	}
	return items, nil
}

const upsertTenantResourceLimits = `-- name: UpsertTenantResourceLimits :exec
WITH input_values AS (
    SELECT
        "resource",
        "limitValue",
        "alarmValue",
        "window",
        "customValueMeter"
    FROM (
        SELECT
            unnest(cast($2::text[] AS "LimitResource"[])) AS "resource",
            unnest($3::int[]) AS "limitValue",
            unnest($4::int[]) AS "alarmValue",
            unnest($5::text[]) AS "window",
            unnest($6::boolean[]) AS "customValueMeter"
    ) AS subquery
)
INSERT INTO "TenantResourceLimit" ("id", "tenantId", "resource", "value", "limitValue", "alarmValue", "window", "customValueMeter", "lastRefill")
SELECT
    gen_random_uuid(),
    $1::uuid,
    iv."resource",
    0,
    iv."limitValue",
    NULLIF(iv."alarmValue", 0),
    NULLIF(iv."window", ''),
    iv."customValueMeter",
    CURRENT_TIMESTAMP
FROM input_values iv
ON CONFLICT ("tenantId", "resource") DO UPDATE SET
    "limitValue" = EXCLUDED."limitValue",
    "alarmValue" = EXCLUDED."alarmValue",
    "updatedAt" = CURRENT_TIMESTAMP
`

type UpsertTenantResourceLimitsParams struct {
	Tenantid          uuid.UUID `json:"tenantid"`
	Resources         []string  `json:"resources"`
	Limitvalues       []int32   `json:"limitvalues"`
	Alarmvalues       []int32   `json:"alarmvalues"`
	Windows           []string  `json:"windows"`
	Customvaluemeters []bool    `json:"customvaluemeters"`
}

func (q *Queries) UpsertTenantResourceLimits(ctx context.Context, db DBTX, arg UpsertTenantResourceLimitsParams) error {
	_, err := db.Exec(ctx, upsertTenantResourceLimits,
		arg.Tenantid,
		arg.Resources,
		arg.Limitvalues,
		arg.Alarmvalues,
		arg.Windows,
		arg.Customvaluemeters,
	)
	return err
}
