// Code generated by sqlc. DO NOT EDIT.
// versions:
//   sqlc v1.30.0
// source: subscriptions.sql

package dbgen

import (
	"context"

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

const CancelUserSubscription = `-- name: CancelUserSubscription :exec
UPDATE user_subscriptions
SET 
    status = 'CANCELLED',
    cancelled_at = CURRENT_TIMESTAMP,
    auto_renew = false,
    updated_at = CURRENT_TIMESTAMP
WHERE id = $1
`

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

const CountUserSubscriptions = `-- name: CountUserSubscriptions :one
SELECT COUNT(*) FROM user_subscriptions WHERE user_id = $1
`

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

const CreateSubscriptionPlan = `-- name: CreateSubscriptionPlan :one

INSERT INTO subscription_plans (
    name, description, duration_value, duration_unit, price, currency, is_active
)
VALUES ($1, $2, $3, $4, $5, $6, COALESCE($7, true))
RETURNING id, name, description, duration_value, duration_unit, price, currency, is_active, created_at, updated_at
`

type CreateSubscriptionPlanParams struct {
	Name          string         `json:"name"`
	Description   pgtype.Text    `json:"description"`
	DurationValue int32          `json:"duration_value"`
	DurationUnit  string         `json:"duration_unit"`
	Price         pgtype.Numeric `json:"price"`
	Currency      string         `json:"currency"`
	Column7       interface{}    `json:"column_7"`
}

// =====================
// Subscription Plans
// =====================
func (q *Queries) CreateSubscriptionPlan(ctx context.Context, arg CreateSubscriptionPlanParams) (SubscriptionPlan, error) {
	row := q.db.QueryRow(ctx, CreateSubscriptionPlan,
		arg.Name,
		arg.Description,
		arg.DurationValue,
		arg.DurationUnit,
		arg.Price,
		arg.Currency,
		arg.Column7,
	)
	var i SubscriptionPlan
	err := row.Scan(
		&i.ID,
		&i.Name,
		&i.Description,
		&i.DurationValue,
		&i.DurationUnit,
		&i.Price,
		&i.Currency,
		&i.IsActive,
		&i.CreatedAt,
		&i.UpdatedAt,
	)
	return i, err
}

const CreateUserSubscription = `-- name: CreateUserSubscription :one

INSERT INTO user_subscriptions (
    user_id, plan_id, starts_at, expires_at, status, payment_reference, payment_method, auto_renew
)
VALUES ($1, $2, COALESCE($3, CURRENT_TIMESTAMP), $4, COALESCE($5, 'ACTIVE'), $6, $7, COALESCE($8, false))
RETURNING id, user_id, plan_id, starts_at, expires_at, status, payment_reference, payment_method, auto_renew, cancelled_at, created_at, updated_at
`

type CreateUserSubscriptionParams struct {
	UserID           int64              `json:"user_id"`
	PlanID           int64              `json:"plan_id"`
	Column3          interface{}        `json:"column_3"`
	ExpiresAt        pgtype.Timestamptz `json:"expires_at"`
	Column5          interface{}        `json:"column_5"`
	PaymentReference pgtype.Text        `json:"payment_reference"`
	PaymentMethod    pgtype.Text        `json:"payment_method"`
	Column8          interface{}        `json:"column_8"`
}

// =====================
// User Subscriptions
// =====================
func (q *Queries) CreateUserSubscription(ctx context.Context, arg CreateUserSubscriptionParams) (UserSubscription, error) {
	row := q.db.QueryRow(ctx, CreateUserSubscription,
		arg.UserID,
		arg.PlanID,
		arg.Column3,
		arg.ExpiresAt,
		arg.Column5,
		arg.PaymentReference,
		arg.PaymentMethod,
		arg.Column8,
	)
	var i UserSubscription
	err := row.Scan(
		&i.ID,
		&i.UserID,
		&i.PlanID,
		&i.StartsAt,
		&i.ExpiresAt,
		&i.Status,
		&i.PaymentReference,
		&i.PaymentMethod,
		&i.AutoRenew,
		&i.CancelledAt,
		&i.CreatedAt,
		&i.UpdatedAt,
	)
	return i, err
}

const DeleteSubscriptionPlan = `-- name: DeleteSubscriptionPlan :exec
DELETE FROM subscription_plans WHERE id = $1
`

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

const ExpireUserSubscription = `-- name: ExpireUserSubscription :exec
UPDATE user_subscriptions
SET 
    status = 'EXPIRED',
    updated_at = CURRENT_TIMESTAMP
WHERE id = $1
`

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

const ExtendSubscription = `-- name: ExtendSubscription :exec
UPDATE user_subscriptions
SET 
    expires_at = $1,
    updated_at = CURRENT_TIMESTAMP
WHERE id = $2
`

type ExtendSubscriptionParams struct {
	ExpiresAt pgtype.Timestamptz `json:"expires_at"`
	ID        int64              `json:"id"`
}

func (q *Queries) ExtendSubscription(ctx context.Context, arg ExtendSubscriptionParams) error {
	_, err := q.db.Exec(ctx, ExtendSubscription, arg.ExpiresAt, arg.ID)
	return err
}

const GetActiveSubscriptionByUserID = `-- name: GetActiveSubscriptionByUserID :one
SELECT 
    us.id, us.user_id, us.plan_id, us.starts_at, us.expires_at, us.status, us.payment_reference, us.payment_method, us.auto_renew, us.cancelled_at, us.created_at, us.updated_at,
    sp.name AS plan_name,
    sp.duration_value,
    sp.duration_unit,
    sp.price,
    sp.currency
FROM user_subscriptions us
JOIN subscription_plans sp ON sp.id = us.plan_id
WHERE us.user_id = $1 
  AND us.status = 'ACTIVE'
  AND us.expires_at > CURRENT_TIMESTAMP
ORDER BY us.expires_at DESC
LIMIT 1
`

type GetActiveSubscriptionByUserIDRow struct {
	ID               int64              `json:"id"`
	UserID           int64              `json:"user_id"`
	PlanID           int64              `json:"plan_id"`
	StartsAt         pgtype.Timestamptz `json:"starts_at"`
	ExpiresAt        pgtype.Timestamptz `json:"expires_at"`
	Status           string             `json:"status"`
	PaymentReference pgtype.Text        `json:"payment_reference"`
	PaymentMethod    pgtype.Text        `json:"payment_method"`
	AutoRenew        bool               `json:"auto_renew"`
	CancelledAt      pgtype.Timestamptz `json:"cancelled_at"`
	CreatedAt        pgtype.Timestamptz `json:"created_at"`
	UpdatedAt        pgtype.Timestamptz `json:"updated_at"`
	PlanName         string             `json:"plan_name"`
	DurationValue    int32              `json:"duration_value"`
	DurationUnit     string             `json:"duration_unit"`
	Price            pgtype.Numeric     `json:"price"`
	Currency         string             `json:"currency"`
}

func (q *Queries) GetActiveSubscriptionByUserID(ctx context.Context, userID int64) (GetActiveSubscriptionByUserIDRow, error) {
	row := q.db.QueryRow(ctx, GetActiveSubscriptionByUserID, userID)
	var i GetActiveSubscriptionByUserIDRow
	err := row.Scan(
		&i.ID,
		&i.UserID,
		&i.PlanID,
		&i.StartsAt,
		&i.ExpiresAt,
		&i.Status,
		&i.PaymentReference,
		&i.PaymentMethod,
		&i.AutoRenew,
		&i.CancelledAt,
		&i.CreatedAt,
		&i.UpdatedAt,
		&i.PlanName,
		&i.DurationValue,
		&i.DurationUnit,
		&i.Price,
		&i.Currency,
	)
	return i, err
}

const GetExpiredSubscriptions = `-- name: GetExpiredSubscriptions :many
SELECT us.id, us.user_id, us.plan_id, us.starts_at, us.expires_at, us.status, us.payment_reference, us.payment_method, us.auto_renew, us.cancelled_at, us.created_at, us.updated_at, sp.name AS plan_name
FROM user_subscriptions us
JOIN subscription_plans sp ON sp.id = us.plan_id
WHERE us.status = 'ACTIVE'
  AND us.expires_at <= CURRENT_TIMESTAMP
`

type GetExpiredSubscriptionsRow struct {
	ID               int64              `json:"id"`
	UserID           int64              `json:"user_id"`
	PlanID           int64              `json:"plan_id"`
	StartsAt         pgtype.Timestamptz `json:"starts_at"`
	ExpiresAt        pgtype.Timestamptz `json:"expires_at"`
	Status           string             `json:"status"`
	PaymentReference pgtype.Text        `json:"payment_reference"`
	PaymentMethod    pgtype.Text        `json:"payment_method"`
	AutoRenew        bool               `json:"auto_renew"`
	CancelledAt      pgtype.Timestamptz `json:"cancelled_at"`
	CreatedAt        pgtype.Timestamptz `json:"created_at"`
	UpdatedAt        pgtype.Timestamptz `json:"updated_at"`
	PlanName         string             `json:"plan_name"`
}

func (q *Queries) GetExpiredSubscriptions(ctx context.Context) ([]GetExpiredSubscriptionsRow, error) {
	rows, err := q.db.Query(ctx, GetExpiredSubscriptions)
	if err != nil {
		return nil, err
	}
	defer rows.Close()
	var items []GetExpiredSubscriptionsRow
	for rows.Next() {
		var i GetExpiredSubscriptionsRow
		if err := rows.Scan(
			&i.ID,
			&i.UserID,
			&i.PlanID,
			&i.StartsAt,
			&i.ExpiresAt,
			&i.Status,
			&i.PaymentReference,
			&i.PaymentMethod,
			&i.AutoRenew,
			&i.CancelledAt,
			&i.CreatedAt,
			&i.UpdatedAt,
			&i.PlanName,
		); err != nil {
			return nil, err
		}
		items = append(items, i)
	}
	if err := rows.Err(); err != nil {
		return nil, err
	}
	return items, nil
}

const GetExpiringSubscriptions = `-- name: GetExpiringSubscriptions :many
SELECT 
    us.id, us.user_id, us.plan_id, us.starts_at, us.expires_at, us.status, us.payment_reference, us.payment_method, us.auto_renew, us.cancelled_at, us.created_at, us.updated_at,
    sp.name AS plan_name,
    u.email,
    u.first_name
FROM user_subscriptions us
JOIN subscription_plans sp ON sp.id = us.plan_id
JOIN users u ON u.id = us.user_id
WHERE us.status = 'ACTIVE'
  AND us.expires_at > CURRENT_TIMESTAMP
  AND us.expires_at <= CURRENT_TIMESTAMP + INTERVAL '7 days'
`

type GetExpiringSubscriptionsRow struct {
	ID               int64              `json:"id"`
	UserID           int64              `json:"user_id"`
	PlanID           int64              `json:"plan_id"`
	StartsAt         pgtype.Timestamptz `json:"starts_at"`
	ExpiresAt        pgtype.Timestamptz `json:"expires_at"`
	Status           string             `json:"status"`
	PaymentReference pgtype.Text        `json:"payment_reference"`
	PaymentMethod    pgtype.Text        `json:"payment_method"`
	AutoRenew        bool               `json:"auto_renew"`
	CancelledAt      pgtype.Timestamptz `json:"cancelled_at"`
	CreatedAt        pgtype.Timestamptz `json:"created_at"`
	UpdatedAt        pgtype.Timestamptz `json:"updated_at"`
	PlanName         string             `json:"plan_name"`
	Email            pgtype.Text        `json:"email"`
	FirstName        pgtype.Text        `json:"first_name"`
}

func (q *Queries) GetExpiringSubscriptions(ctx context.Context) ([]GetExpiringSubscriptionsRow, error) {
	rows, err := q.db.Query(ctx, GetExpiringSubscriptions)
	if err != nil {
		return nil, err
	}
	defer rows.Close()
	var items []GetExpiringSubscriptionsRow
	for rows.Next() {
		var i GetExpiringSubscriptionsRow
		if err := rows.Scan(
			&i.ID,
			&i.UserID,
			&i.PlanID,
			&i.StartsAt,
			&i.ExpiresAt,
			&i.Status,
			&i.PaymentReference,
			&i.PaymentMethod,
			&i.AutoRenew,
			&i.CancelledAt,
			&i.CreatedAt,
			&i.UpdatedAt,
			&i.PlanName,
			&i.Email,
			&i.FirstName,
		); err != nil {
			return nil, err
		}
		items = append(items, i)
	}
	if err := rows.Err(); err != nil {
		return nil, err
	}
	return items, nil
}

const GetSubscriptionPlanByID = `-- name: GetSubscriptionPlanByID :one
SELECT id, name, description, duration_value, duration_unit, price, currency, is_active, created_at, updated_at FROM subscription_plans WHERE id = $1
`

func (q *Queries) GetSubscriptionPlanByID(ctx context.Context, id int64) (SubscriptionPlan, error) {
	row := q.db.QueryRow(ctx, GetSubscriptionPlanByID, id)
	var i SubscriptionPlan
	err := row.Scan(
		&i.ID,
		&i.Name,
		&i.Description,
		&i.DurationValue,
		&i.DurationUnit,
		&i.Price,
		&i.Currency,
		&i.IsActive,
		&i.CreatedAt,
		&i.UpdatedAt,
	)
	return i, err
}

const GetUserSubscriptionByID = `-- name: GetUserSubscriptionByID :one
SELECT 
    us.id, us.user_id, us.plan_id, us.starts_at, us.expires_at, us.status, us.payment_reference, us.payment_method, us.auto_renew, us.cancelled_at, us.created_at, us.updated_at,
    sp.name AS plan_name,
    sp.duration_value,
    sp.duration_unit,
    sp.price,
    sp.currency
FROM user_subscriptions us
JOIN subscription_plans sp ON sp.id = us.plan_id
WHERE us.id = $1
`

type GetUserSubscriptionByIDRow struct {
	ID               int64              `json:"id"`
	UserID           int64              `json:"user_id"`
	PlanID           int64              `json:"plan_id"`
	StartsAt         pgtype.Timestamptz `json:"starts_at"`
	ExpiresAt        pgtype.Timestamptz `json:"expires_at"`
	Status           string             `json:"status"`
	PaymentReference pgtype.Text        `json:"payment_reference"`
	PaymentMethod    pgtype.Text        `json:"payment_method"`
	AutoRenew        bool               `json:"auto_renew"`
	CancelledAt      pgtype.Timestamptz `json:"cancelled_at"`
	CreatedAt        pgtype.Timestamptz `json:"created_at"`
	UpdatedAt        pgtype.Timestamptz `json:"updated_at"`
	PlanName         string             `json:"plan_name"`
	DurationValue    int32              `json:"duration_value"`
	DurationUnit     string             `json:"duration_unit"`
	Price            pgtype.Numeric     `json:"price"`
	Currency         string             `json:"currency"`
}

func (q *Queries) GetUserSubscriptionByID(ctx context.Context, id int64) (GetUserSubscriptionByIDRow, error) {
	row := q.db.QueryRow(ctx, GetUserSubscriptionByID, id)
	var i GetUserSubscriptionByIDRow
	err := row.Scan(
		&i.ID,
		&i.UserID,
		&i.PlanID,
		&i.StartsAt,
		&i.ExpiresAt,
		&i.Status,
		&i.PaymentReference,
		&i.PaymentMethod,
		&i.AutoRenew,
		&i.CancelledAt,
		&i.CreatedAt,
		&i.UpdatedAt,
		&i.PlanName,
		&i.DurationValue,
		&i.DurationUnit,
		&i.Price,
		&i.Currency,
	)
	return i, err
}

const GetUserSubscriptionHistory = `-- name: GetUserSubscriptionHistory :many
SELECT 
    us.id, us.user_id, us.plan_id, us.starts_at, us.expires_at, us.status, us.payment_reference, us.payment_method, us.auto_renew, us.cancelled_at, us.created_at, us.updated_at,
    sp.name AS plan_name,
    sp.duration_value,
    sp.duration_unit,
    sp.price,
    sp.currency
FROM user_subscriptions us
JOIN subscription_plans sp ON sp.id = us.plan_id
WHERE us.user_id = $1
ORDER BY us.created_at DESC
LIMIT $3::INT
OFFSET $2::INT
`

type GetUserSubscriptionHistoryParams struct {
	UserID int64       `json:"user_id"`
	Offset pgtype.Int4 `json:"offset"`
	Limit  pgtype.Int4 `json:"limit"`
}

type GetUserSubscriptionHistoryRow struct {
	ID               int64              `json:"id"`
	UserID           int64              `json:"user_id"`
	PlanID           int64              `json:"plan_id"`
	StartsAt         pgtype.Timestamptz `json:"starts_at"`
	ExpiresAt        pgtype.Timestamptz `json:"expires_at"`
	Status           string             `json:"status"`
	PaymentReference pgtype.Text        `json:"payment_reference"`
	PaymentMethod    pgtype.Text        `json:"payment_method"`
	AutoRenew        bool               `json:"auto_renew"`
	CancelledAt      pgtype.Timestamptz `json:"cancelled_at"`
	CreatedAt        pgtype.Timestamptz `json:"created_at"`
	UpdatedAt        pgtype.Timestamptz `json:"updated_at"`
	PlanName         string             `json:"plan_name"`
	DurationValue    int32              `json:"duration_value"`
	DurationUnit     string             `json:"duration_unit"`
	Price            pgtype.Numeric     `json:"price"`
	Currency         string             `json:"currency"`
}

func (q *Queries) GetUserSubscriptionHistory(ctx context.Context, arg GetUserSubscriptionHistoryParams) ([]GetUserSubscriptionHistoryRow, error) {
	rows, err := q.db.Query(ctx, GetUserSubscriptionHistory, arg.UserID, arg.Offset, arg.Limit)
	if err != nil {
		return nil, err
	}
	defer rows.Close()
	var items []GetUserSubscriptionHistoryRow
	for rows.Next() {
		var i GetUserSubscriptionHistoryRow
		if err := rows.Scan(
			&i.ID,
			&i.UserID,
			&i.PlanID,
			&i.StartsAt,
			&i.ExpiresAt,
			&i.Status,
			&i.PaymentReference,
			&i.PaymentMethod,
			&i.AutoRenew,
			&i.CancelledAt,
			&i.CreatedAt,
			&i.UpdatedAt,
			&i.PlanName,
			&i.DurationValue,
			&i.DurationUnit,
			&i.Price,
			&i.Currency,
		); err != nil {
			return nil, err
		}
		items = append(items, i)
	}
	if err := rows.Err(); err != nil {
		return nil, err
	}
	return items, nil
}

const HasActiveSubscription = `-- name: HasActiveSubscription :one
SELECT EXISTS(
    SELECT 1 FROM user_subscriptions
    WHERE user_id = $1
      AND status = 'ACTIVE'
      AND expires_at > CURRENT_TIMESTAMP
) AS has_subscription
`

func (q *Queries) HasActiveSubscription(ctx context.Context, userID int64) (bool, error) {
	row := q.db.QueryRow(ctx, HasActiveSubscription, userID)
	var has_subscription bool
	err := row.Scan(&has_subscription)
	return has_subscription, err
}

const ListActiveSubscriptionPlans = `-- name: ListActiveSubscriptionPlans :many
SELECT id, name, description, duration_value, duration_unit, price, currency, is_active, created_at, updated_at FROM subscription_plans
WHERE is_active = true
ORDER BY price ASC
`

func (q *Queries) ListActiveSubscriptionPlans(ctx context.Context) ([]SubscriptionPlan, error) {
	rows, err := q.db.Query(ctx, ListActiveSubscriptionPlans)
	if err != nil {
		return nil, err
	}
	defer rows.Close()
	var items []SubscriptionPlan
	for rows.Next() {
		var i SubscriptionPlan
		if err := rows.Scan(
			&i.ID,
			&i.Name,
			&i.Description,
			&i.DurationValue,
			&i.DurationUnit,
			&i.Price,
			&i.Currency,
			&i.IsActive,
			&i.CreatedAt,
			&i.UpdatedAt,
		); err != nil {
			return nil, err
		}
		items = append(items, i)
	}
	if err := rows.Err(); err != nil {
		return nil, err
	}
	return items, nil
}

const ListSubscriptionPlans = `-- name: ListSubscriptionPlans :many
SELECT id, name, description, duration_value, duration_unit, price, currency, is_active, created_at, updated_at FROM subscription_plans
WHERE ($1::BOOLEAN IS NULL OR $1 = true AND is_active = true OR $1 = false)
ORDER BY price ASC
`

func (q *Queries) ListSubscriptionPlans(ctx context.Context, dollar_1 bool) ([]SubscriptionPlan, error) {
	rows, err := q.db.Query(ctx, ListSubscriptionPlans, dollar_1)
	if err != nil {
		return nil, err
	}
	defer rows.Close()
	var items []SubscriptionPlan
	for rows.Next() {
		var i SubscriptionPlan
		if err := rows.Scan(
			&i.ID,
			&i.Name,
			&i.Description,
			&i.DurationValue,
			&i.DurationUnit,
			&i.Price,
			&i.Currency,
			&i.IsActive,
			&i.CreatedAt,
			&i.UpdatedAt,
		); err != nil {
			return nil, err
		}
		items = append(items, i)
	}
	if err := rows.Err(); err != nil {
		return nil, err
	}
	return items, nil
}

const UpdateAutoRenew = `-- name: UpdateAutoRenew :exec
UPDATE user_subscriptions
SET 
    auto_renew = $1,
    updated_at = CURRENT_TIMESTAMP
WHERE id = $2
`

type UpdateAutoRenewParams struct {
	AutoRenew bool  `json:"auto_renew"`
	ID        int64 `json:"id"`
}

func (q *Queries) UpdateAutoRenew(ctx context.Context, arg UpdateAutoRenewParams) error {
	_, err := q.db.Exec(ctx, UpdateAutoRenew, arg.AutoRenew, arg.ID)
	return err
}

const UpdateSubscriptionPlan = `-- name: UpdateSubscriptionPlan :exec
UPDATE subscription_plans
SET
    name = COALESCE($1, name),
    description = COALESCE($2, description),
    duration_value = COALESCE($3, duration_value),
    duration_unit = COALESCE($4, duration_unit),
    price = COALESCE($5, price),
    currency = COALESCE($6, currency),
    is_active = COALESCE($7, is_active),
    updated_at = CURRENT_TIMESTAMP
WHERE id = $8
`

type UpdateSubscriptionPlanParams struct {
	Name          string         `json:"name"`
	Description   pgtype.Text    `json:"description"`
	DurationValue int32          `json:"duration_value"`
	DurationUnit  string         `json:"duration_unit"`
	Price         pgtype.Numeric `json:"price"`
	Currency      string         `json:"currency"`
	IsActive      bool           `json:"is_active"`
	ID            int64          `json:"id"`
}

func (q *Queries) UpdateSubscriptionPlan(ctx context.Context, arg UpdateSubscriptionPlanParams) error {
	_, err := q.db.Exec(ctx, UpdateSubscriptionPlan,
		arg.Name,
		arg.Description,
		arg.DurationValue,
		arg.DurationUnit,
		arg.Price,
		arg.Currency,
		arg.IsActive,
		arg.ID,
	)
	return err
}

const UpdateUserSubscriptionStatus = `-- name: UpdateUserSubscriptionStatus :exec
UPDATE user_subscriptions
SET 
    status = $1,
    updated_at = CURRENT_TIMESTAMP
WHERE id = $2
`

type UpdateUserSubscriptionStatusParams struct {
	Status string `json:"status"`
	ID     int64  `json:"id"`
}

func (q *Queries) UpdateUserSubscriptionStatus(ctx context.Context, arg UpdateUserSubscriptionStatusParams) error {
	_, err := q.db.Exec(ctx, UpdateUserSubscriptionStatus, arg.Status, arg.ID)
	return err
}
