-- =====================
-- Payments
-- =====================

-- 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 *;

-- name: GetPaymentByID :one
SELECT * FROM payments WHERE id = $1;

-- name: GetPaymentBySessionID :one
SELECT * FROM payments WHERE session_id = $1;

-- name: GetPaymentByNonce :one
SELECT * FROM payments WHERE nonce = $1;

-- name: GetPaymentByTransactionID :one
SELECT * FROM payments WHERE transaction_id = $1;

-- name: GetPaymentsByUserID :many
SELECT p.*, 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 sqlc.narg('limit')::INT
OFFSET sqlc.narg('offset')::INT;

-- name: GetPendingPaymentsByUserID :many
SELECT * FROM payments
WHERE user_id = $1 AND status = 'PENDING'
ORDER BY created_at DESC;

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

-- name: UpdatePaymentStatusBySessionID :exec
UPDATE payments
SET 
    status = sqlc.arg(status)::varchar,
    transaction_id = COALESCE(sqlc.arg(transaction_id)::text, transaction_id),
    payment_method = COALESCE(sqlc.arg(payment_method)::text, payment_method),
    paid_at = CASE WHEN sqlc.arg(status)::varchar = 'SUCCESS' THEN CURRENT_TIMESTAMP ELSE paid_at END,
    updated_at = CURRENT_TIMESTAMP
WHERE session_id = sqlc.arg(session_id)::text;

-- name: UpdatePaymentStatusByNonce :exec
UPDATE payments
SET 
    status = sqlc.arg(status)::varchar,
    transaction_id = COALESCE(sqlc.arg(transaction_id)::text, transaction_id),
    payment_method = COALESCE(sqlc.arg(payment_method)::text, payment_method),
    paid_at = CASE WHEN sqlc.arg(status)::varchar = 'SUCCESS' THEN CURRENT_TIMESTAMP ELSE paid_at END,
    updated_at = CURRENT_TIMESTAMP
WHERE nonce = sqlc.arg(nonce)::text;

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

-- name: LinkPaymentToSubscription :exec
UPDATE payments
SET 
    subscription_id = $1,
    updated_at = CURRENT_TIMESTAMP
WHERE id = $2;

-- name: GetExpiredPendingPayments :many
SELECT * FROM payments
WHERE status = 'PENDING'
  AND expires_at IS NOT NULL
  AND expires_at <= CURRENT_TIMESTAMP;

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

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

-- name: ListPaymentsAdmin :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,
    sp.category AS plan_category,
    u.email AS user_email,
    u.first_name AS user_first_name,
    u.last_name AS user_last_name
FROM payments p
LEFT JOIN subscription_plans sp ON sp.id = p.plan_id
LEFT JOIN users u ON u.id = p.user_id
WHERE (sqlc.narg('payment_id')::bigint IS NULL OR p.id = sqlc.narg('payment_id')::bigint)
  AND (sqlc.narg('user_id')::bigint IS NULL OR p.user_id = sqlc.narg('user_id')::bigint)
  AND (sqlc.narg('plan_id')::bigint IS NULL OR p.plan_id = sqlc.narg('plan_id')::bigint)
  AND (sqlc.narg('subscription_id')::bigint IS NULL OR p.subscription_id = sqlc.narg('subscription_id')::bigint)
  AND (sqlc.narg('status')::varchar IS NULL OR p.status = sqlc.narg('status')::varchar)
  AND (sqlc.narg('payment_method')::varchar IS NULL OR UPPER(COALESCE(p.payment_method, '')) = UPPER(sqlc.narg('payment_method')::varchar))
  AND (sqlc.narg('currency')::varchar IS NULL OR UPPER(p.currency) = UPPER(sqlc.narg('currency')::varchar))
  AND (sqlc.narg('plan_category')::varchar IS NULL OR sp.category = sqlc.narg('plan_category')::varchar)
  AND (sqlc.narg('created_from')::timestamptz IS NULL OR p.created_at >= sqlc.narg('created_from')::timestamptz)
  AND (sqlc.narg('created_to')::timestamptz IS NULL OR p.created_at < sqlc.narg('created_to')::timestamptz)
  AND (sqlc.narg('paid_from')::timestamptz IS NULL OR p.paid_at >= sqlc.narg('paid_from')::timestamptz)
  AND (sqlc.narg('paid_to')::timestamptz IS NULL OR p.paid_at < sqlc.narg('paid_to')::timestamptz)
  AND (sqlc.narg('min_amount')::numeric IS NULL OR p.amount >= sqlc.narg('min_amount')::numeric)
  AND (sqlc.narg('max_amount')::numeric IS NULL OR p.amount <= sqlc.narg('max_amount')::numeric)
  AND (
    sqlc.narg('reference')::text IS NULL
    OR p.session_id ILIKE '%' || sqlc.narg('reference')::text || '%'
    OR p.nonce ILIKE '%' || sqlc.narg('reference')::text || '%'
    OR p.transaction_id ILIKE '%' || sqlc.narg('reference')::text || '%'
  )
ORDER BY p.created_at DESC
LIMIT sqlc.arg('limit') OFFSET sqlc.arg('offset');

-- name: CountPaymentsAdmin :one
SELECT COUNT(*)::bigint AS total
FROM payments p
LEFT JOIN subscription_plans sp ON sp.id = p.plan_id
WHERE (sqlc.narg('payment_id')::bigint IS NULL OR p.id = sqlc.narg('payment_id')::bigint)
  AND (sqlc.narg('user_id')::bigint IS NULL OR p.user_id = sqlc.narg('user_id')::bigint)
  AND (sqlc.narg('plan_id')::bigint IS NULL OR p.plan_id = sqlc.narg('plan_id')::bigint)
  AND (sqlc.narg('subscription_id')::bigint IS NULL OR p.subscription_id = sqlc.narg('subscription_id')::bigint)
  AND (sqlc.narg('status')::varchar IS NULL OR p.status = sqlc.narg('status')::varchar)
  AND (sqlc.narg('payment_method')::varchar IS NULL OR UPPER(COALESCE(p.payment_method, '')) = UPPER(sqlc.narg('payment_method')::varchar))
  AND (sqlc.narg('currency')::varchar IS NULL OR UPPER(p.currency) = UPPER(sqlc.narg('currency')::varchar))
  AND (sqlc.narg('plan_category')::varchar IS NULL OR sp.category = sqlc.narg('plan_category')::varchar)
  AND (sqlc.narg('created_from')::timestamptz IS NULL OR p.created_at >= sqlc.narg('created_from')::timestamptz)
  AND (sqlc.narg('created_to')::timestamptz IS NULL OR p.created_at < sqlc.narg('created_to')::timestamptz)
  AND (sqlc.narg('paid_from')::timestamptz IS NULL OR p.paid_at >= sqlc.narg('paid_from')::timestamptz)
  AND (sqlc.narg('paid_to')::timestamptz IS NULL OR p.paid_at < sqlc.narg('paid_to')::timestamptz)
  AND (sqlc.narg('min_amount')::numeric IS NULL OR p.amount >= sqlc.narg('min_amount')::numeric)
  AND (sqlc.narg('max_amount')::numeric IS NULL OR p.amount <= sqlc.narg('max_amount')::numeric)
  AND (
    sqlc.narg('reference')::text IS NULL
    OR p.session_id ILIKE '%' || sqlc.narg('reference')::text || '%'
    OR p.nonce ILIKE '%' || sqlc.narg('reference')::text || '%'
    OR p.transaction_id ILIKE '%' || sqlc.narg('reference')::text || '%'
  );
