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

package dbgen

import (
	"context"

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

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

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

const CreatePayment = `-- name: CreatePayment :one

INSERT INTO payments (
    user_id, plan_id, subscription_id, session_id, transaction_id, nonce,
    amount, currency, payment_method, status, payment_url, expires_at
)
VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, COALESCE($10, 'PENDING'), $11, $12)
RETURNING id, user_id, plan_id, subscription_id, session_id, transaction_id, nonce, amount, currency, payment_method, status, payment_url, paid_at, expires_at, created_at, updated_at
`

type CreatePaymentParams struct {
	UserID         int64              `json:"user_id"`
	PlanID         pgtype.Int8        `json:"plan_id"`
	SubscriptionID pgtype.Int8        `json:"subscription_id"`
	SessionID      pgtype.Text        `json:"session_id"`
	TransactionID  pgtype.Text        `json:"transaction_id"`
	Nonce          string             `json:"nonce"`
	Amount         pgtype.Numeric     `json:"amount"`
	Currency       string             `json:"currency"`
	PaymentMethod  pgtype.Text        `json:"payment_method"`
	Column10       interface{}        `json:"column_10"`
	PaymentUrl     pgtype.Text        `json:"payment_url"`
	ExpiresAt      pgtype.Timestamptz `json:"expires_at"`
}

// =====================
// Payments
// =====================
func (q *Queries) CreatePayment(ctx context.Context, arg CreatePaymentParams) (Payment, error) {
	row := q.db.QueryRow(ctx, CreatePayment,
		arg.UserID,
		arg.PlanID,
		arg.SubscriptionID,
		arg.SessionID,
		arg.TransactionID,
		arg.Nonce,
		arg.Amount,
		arg.Currency,
		arg.PaymentMethod,
		arg.Column10,
		arg.PaymentUrl,
		arg.ExpiresAt,
	)
	var i Payment
	err := row.Scan(
		&i.ID,
		&i.UserID,
		&i.PlanID,
		&i.SubscriptionID,
		&i.SessionID,
		&i.TransactionID,
		&i.Nonce,
		&i.Amount,
		&i.Currency,
		&i.PaymentMethod,
		&i.Status,
		&i.PaymentUrl,
		&i.PaidAt,
		&i.ExpiresAt,
		&i.CreatedAt,
		&i.UpdatedAt,
	)
	return i, err
}

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

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

const GetExpiredPendingPayments = `-- name: GetExpiredPendingPayments :many
SELECT id, user_id, plan_id, subscription_id, session_id, transaction_id, nonce, amount, currency, payment_method, status, payment_url, paid_at, expires_at, created_at, updated_at FROM payments
WHERE status = 'PENDING'
  AND expires_at IS NOT NULL
  AND expires_at <= CURRENT_TIMESTAMP
`

func (q *Queries) GetExpiredPendingPayments(ctx context.Context) ([]Payment, error) {
	rows, err := q.db.Query(ctx, GetExpiredPendingPayments)
	if err != nil {
		return nil, err
	}
	defer rows.Close()
	var items []Payment
	for rows.Next() {
		var i Payment
		if err := rows.Scan(
			&i.ID,
			&i.UserID,
			&i.PlanID,
			&i.SubscriptionID,
			&i.SessionID,
			&i.TransactionID,
			&i.Nonce,
			&i.Amount,
			&i.Currency,
			&i.PaymentMethod,
			&i.Status,
			&i.PaymentUrl,
			&i.PaidAt,
			&i.ExpiresAt,
			&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 GetPaymentByID = `-- name: GetPaymentByID :one
SELECT id, user_id, plan_id, subscription_id, session_id, transaction_id, nonce, amount, currency, payment_method, status, payment_url, paid_at, expires_at, created_at, updated_at FROM payments WHERE id = $1
`

func (q *Queries) GetPaymentByID(ctx context.Context, id int64) (Payment, error) {
	row := q.db.QueryRow(ctx, GetPaymentByID, id)
	var i Payment
	err := row.Scan(
		&i.ID,
		&i.UserID,
		&i.PlanID,
		&i.SubscriptionID,
		&i.SessionID,
		&i.TransactionID,
		&i.Nonce,
		&i.Amount,
		&i.Currency,
		&i.PaymentMethod,
		&i.Status,
		&i.PaymentUrl,
		&i.PaidAt,
		&i.ExpiresAt,
		&i.CreatedAt,
		&i.UpdatedAt,
	)
	return i, err
}

const GetPaymentByNonce = `-- name: GetPaymentByNonce :one
SELECT id, user_id, plan_id, subscription_id, session_id, transaction_id, nonce, amount, currency, payment_method, status, payment_url, paid_at, expires_at, created_at, updated_at FROM payments WHERE nonce = $1
`

func (q *Queries) GetPaymentByNonce(ctx context.Context, nonce string) (Payment, error) {
	row := q.db.QueryRow(ctx, GetPaymentByNonce, nonce)
	var i Payment
	err := row.Scan(
		&i.ID,
		&i.UserID,
		&i.PlanID,
		&i.SubscriptionID,
		&i.SessionID,
		&i.TransactionID,
		&i.Nonce,
		&i.Amount,
		&i.Currency,
		&i.PaymentMethod,
		&i.Status,
		&i.PaymentUrl,
		&i.PaidAt,
		&i.ExpiresAt,
		&i.CreatedAt,
		&i.UpdatedAt,
	)
	return i, err
}

const GetPaymentBySessionID = `-- name: GetPaymentBySessionID :one
SELECT id, user_id, plan_id, subscription_id, session_id, transaction_id, nonce, amount, currency, payment_method, status, payment_url, paid_at, expires_at, created_at, updated_at FROM payments WHERE session_id = $1
`

func (q *Queries) GetPaymentBySessionID(ctx context.Context, sessionID pgtype.Text) (Payment, error) {
	row := q.db.QueryRow(ctx, GetPaymentBySessionID, sessionID)
	var i Payment
	err := row.Scan(
		&i.ID,
		&i.UserID,
		&i.PlanID,
		&i.SubscriptionID,
		&i.SessionID,
		&i.TransactionID,
		&i.Nonce,
		&i.Amount,
		&i.Currency,
		&i.PaymentMethod,
		&i.Status,
		&i.PaymentUrl,
		&i.PaidAt,
		&i.ExpiresAt,
		&i.CreatedAt,
		&i.UpdatedAt,
	)
	return i, err
}

const GetPaymentByTransactionID = `-- name: GetPaymentByTransactionID :one
SELECT id, user_id, plan_id, subscription_id, session_id, transaction_id, nonce, amount, currency, payment_method, status, payment_url, paid_at, expires_at, created_at, updated_at FROM payments WHERE transaction_id = $1
`

func (q *Queries) GetPaymentByTransactionID(ctx context.Context, transactionID pgtype.Text) (Payment, error) {
	row := q.db.QueryRow(ctx, GetPaymentByTransactionID, transactionID)
	var i Payment
	err := row.Scan(
		&i.ID,
		&i.UserID,
		&i.PlanID,
		&i.SubscriptionID,
		&i.SessionID,
		&i.TransactionID,
		&i.Nonce,
		&i.Amount,
		&i.Currency,
		&i.PaymentMethod,
		&i.Status,
		&i.PaymentUrl,
		&i.PaidAt,
		&i.ExpiresAt,
		&i.CreatedAt,
		&i.UpdatedAt,
	)
	return i, err
}

const GetPaymentsByUserID = `-- name: GetPaymentsByUserID :many
SELECT p.id, p.user_id, p.plan_id, p.subscription_id, p.session_id, p.transaction_id, p.nonce, p.amount, p.currency, p.payment_method, p.status, p.payment_url, p.paid_at, p.expires_at, p.created_at, p.updated_at, sp.name AS plan_name
FROM payments p
LEFT JOIN subscription_plans sp ON sp.id = p.plan_id
WHERE p.user_id = $1
ORDER BY p.created_at DESC
LIMIT $3::INT
OFFSET $2::INT
`

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

type GetPaymentsByUserIDRow struct {
	ID             int64              `json:"id"`
	UserID         int64              `json:"user_id"`
	PlanID         pgtype.Int8        `json:"plan_id"`
	SubscriptionID pgtype.Int8        `json:"subscription_id"`
	SessionID      pgtype.Text        `json:"session_id"`
	TransactionID  pgtype.Text        `json:"transaction_id"`
	Nonce          string             `json:"nonce"`
	Amount         pgtype.Numeric     `json:"amount"`
	Currency       string             `json:"currency"`
	PaymentMethod  pgtype.Text        `json:"payment_method"`
	Status         string             `json:"status"`
	PaymentUrl     pgtype.Text        `json:"payment_url"`
	PaidAt         pgtype.Timestamptz `json:"paid_at"`
	ExpiresAt      pgtype.Timestamptz `json:"expires_at"`
	CreatedAt      pgtype.Timestamptz `json:"created_at"`
	UpdatedAt      pgtype.Timestamptz `json:"updated_at"`
	PlanName       pgtype.Text        `json:"plan_name"`
}

func (q *Queries) GetPaymentsByUserID(ctx context.Context, arg GetPaymentsByUserIDParams) ([]GetPaymentsByUserIDRow, error) {
	rows, err := q.db.Query(ctx, GetPaymentsByUserID, arg.UserID, arg.Offset, arg.Limit)
	if err != nil {
		return nil, err
	}
	defer rows.Close()
	var items []GetPaymentsByUserIDRow
	for rows.Next() {
		var i GetPaymentsByUserIDRow
		if err := rows.Scan(
			&i.ID,
			&i.UserID,
			&i.PlanID,
			&i.SubscriptionID,
			&i.SessionID,
			&i.TransactionID,
			&i.Nonce,
			&i.Amount,
			&i.Currency,
			&i.PaymentMethod,
			&i.Status,
			&i.PaymentUrl,
			&i.PaidAt,
			&i.ExpiresAt,
			&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 GetPendingPaymentsByUserID = `-- name: GetPendingPaymentsByUserID :many
SELECT id, user_id, plan_id, subscription_id, session_id, transaction_id, nonce, amount, currency, payment_method, status, payment_url, paid_at, expires_at, created_at, updated_at FROM payments
WHERE user_id = $1 AND status = 'PENDING'
ORDER BY created_at DESC
`

func (q *Queries) GetPendingPaymentsByUserID(ctx context.Context, userID int64) ([]Payment, error) {
	rows, err := q.db.Query(ctx, GetPendingPaymentsByUserID, userID)
	if err != nil {
		return nil, err
	}
	defer rows.Close()
	var items []Payment
	for rows.Next() {
		var i Payment
		if err := rows.Scan(
			&i.ID,
			&i.UserID,
			&i.PlanID,
			&i.SubscriptionID,
			&i.SessionID,
			&i.TransactionID,
			&i.Nonce,
			&i.Amount,
			&i.Currency,
			&i.PaymentMethod,
			&i.Status,
			&i.PaymentUrl,
			&i.PaidAt,
			&i.ExpiresAt,
			&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 LinkPaymentToSubscription = `-- name: LinkPaymentToSubscription :exec
UPDATE payments
SET 
    subscription_id = $1,
    updated_at = CURRENT_TIMESTAMP
WHERE id = $2
`

type LinkPaymentToSubscriptionParams struct {
	SubscriptionID pgtype.Int8 `json:"subscription_id"`
	ID             int64       `json:"id"`
}

func (q *Queries) LinkPaymentToSubscription(ctx context.Context, arg LinkPaymentToSubscriptionParams) error {
	_, err := q.db.Exec(ctx, LinkPaymentToSubscription, arg.SubscriptionID, arg.ID)
	return err
}

const UpdatePaymentSessionID = `-- name: UpdatePaymentSessionID :exec
UPDATE payments
SET 
    session_id = $1,
    payment_url = $2,
    updated_at = CURRENT_TIMESTAMP
WHERE id = $3
`

type UpdatePaymentSessionIDParams struct {
	SessionID  pgtype.Text `json:"session_id"`
	PaymentUrl pgtype.Text `json:"payment_url"`
	ID         int64       `json:"id"`
}

func (q *Queries) UpdatePaymentSessionID(ctx context.Context, arg UpdatePaymentSessionIDParams) error {
	_, err := q.db.Exec(ctx, UpdatePaymentSessionID, arg.SessionID, arg.PaymentUrl, arg.ID)
	return err
}

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

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

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

const UpdatePaymentStatusByNonce = `-- name: UpdatePaymentStatusByNonce :exec
UPDATE payments
SET 
    status = $1,
    transaction_id = COALESCE($2, transaction_id),
    payment_method = COALESCE($3, payment_method),
    paid_at = CASE WHEN $1 = 'SUCCESS' THEN CURRENT_TIMESTAMP ELSE paid_at END,
    updated_at = CURRENT_TIMESTAMP
WHERE nonce = $4
`

type UpdatePaymentStatusByNonceParams struct {
	Status        string      `json:"status"`
	TransactionID pgtype.Text `json:"transaction_id"`
	PaymentMethod pgtype.Text `json:"payment_method"`
	Nonce         string      `json:"nonce"`
}

func (q *Queries) UpdatePaymentStatusByNonce(ctx context.Context, arg UpdatePaymentStatusByNonceParams) error {
	_, err := q.db.Exec(ctx, UpdatePaymentStatusByNonce,
		arg.Status,
		arg.TransactionID,
		arg.PaymentMethod,
		arg.Nonce,
	)
	return err
}

const UpdatePaymentStatusBySessionID = `-- name: UpdatePaymentStatusBySessionID :exec
UPDATE payments
SET 
    status = $1,
    transaction_id = COALESCE($2, transaction_id),
    payment_method = COALESCE($3, payment_method),
    paid_at = CASE WHEN $1 = 'SUCCESS' THEN CURRENT_TIMESTAMP ELSE paid_at END,
    updated_at = CURRENT_TIMESTAMP
WHERE session_id = $4
`

type UpdatePaymentStatusBySessionIDParams struct {
	Status        string      `json:"status"`
	TransactionID pgtype.Text `json:"transaction_id"`
	PaymentMethod pgtype.Text `json:"payment_method"`
	SessionID     pgtype.Text `json:"session_id"`
}

func (q *Queries) UpdatePaymentStatusBySessionID(ctx context.Context, arg UpdatePaymentStatusBySessionIDParams) error {
	_, err := q.db.Exec(ctx, UpdatePaymentStatusBySessionID,
		arg.Status,
		arg.TransactionID,
		arg.PaymentMethod,
		arg.SessionID,
	)
	return err
}
