-- =====================
-- Subscription Plans
-- =====================

-- name: CreateSubscriptionPlan :one
INSERT INTO subscription_plans (
    name, description, category, duration_value, duration_unit, price, currency, is_active
)
VALUES ($1, $2, $3, $4, $5, $6, $7, COALESCE($8, true))
RETURNING *;

-- name: GetSubscriptionPlanByID :one
SELECT * FROM subscription_plans WHERE id = $1;

-- name: ListSubscriptionPlans :many
SELECT * FROM subscription_plans
WHERE ($1::BOOLEAN IS NULL OR $1 = true AND is_active = true OR $1 = false)
ORDER BY price ASC;

-- name: ListActiveSubscriptionPlans :many
SELECT * FROM subscription_plans
WHERE is_active = true
ORDER BY price ASC;

-- name: UpdateSubscriptionPlan :exec
UPDATE subscription_plans
SET
    name = COALESCE(sqlc.narg('name')::varchar, name),
    description = COALESCE(sqlc.narg('description')::text, description),
    category = COALESCE(sqlc.narg('category')::varchar, category),
    duration_value = COALESCE(sqlc.narg('duration_value')::int, duration_value),
    duration_unit = COALESCE(sqlc.narg('duration_unit')::varchar, duration_unit),
    price = COALESCE(sqlc.narg('price')::numeric, price),
    currency = COALESCE(sqlc.narg('currency')::varchar, currency),
    is_active = COALESCE(sqlc.narg('is_active')::boolean, is_active),
    updated_at = CURRENT_TIMESTAMP
WHERE id = sqlc.arg('id');

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

-- =====================
-- User Subscriptions
-- =====================

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

-- name: GetUserSubscriptionByID :one
SELECT 
    us.*,
    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;

-- Display status for admin user lists: ACTIVE (non-expired), else latest PENDING, else Unsubscribed.
-- name: ListSubscriptionDisplayStatusesByUserIDs :many
WITH input AS (
    SELECT unnest($1::bigint[])::bigint AS user_id
)
SELECT
    input.user_id,
    COALESCE(
        (SELECT us.status::text FROM user_subscriptions us
         WHERE us.user_id = input.user_id
           AND us.status = 'ACTIVE' AND us.expires_at > CURRENT_TIMESTAMP
         ORDER BY us.expires_at DESC LIMIT 1),
        (SELECT us.status::text FROM user_subscriptions us
         WHERE us.user_id = input.user_id
           AND us.status = 'PENDING'
         ORDER BY us.created_at DESC LIMIT 1),
        'Unsubscribed'
    )::text AS subscription_status
FROM input;

-- name: GetSubscriptionDisplayStatusByUserID :one
SELECT COALESCE(
    (SELECT us.status::text FROM user_subscriptions us
     WHERE us.user_id = $1
       AND us.status = 'ACTIVE' AND us.expires_at > CURRENT_TIMESTAMP
     ORDER BY us.expires_at DESC LIMIT 1),
    (SELECT us.status::text FROM user_subscriptions us
     WHERE us.user_id = $1
       AND us.status = 'PENDING'
       ORDER BY us.created_at DESC LIMIT 1),
    'Unsubscribed'
)::text AS subscription_status;

-- name: GetActiveSubscriptionByUserID :one
SELECT 
    us.*,
    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;

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

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

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

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

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

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

-- name: GetExpiredSubscriptions :many
SELECT us.*, 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;

-- name: ListLearnEnglishSubscriptionsExpiringInSevenDays :many
SELECT
    us.id,
    us.user_id,
    us.plan_id,
    us.expires_at,
    sp.name AS plan_name,
    sp.category AS plan_category
FROM user_subscriptions us
JOIN subscription_plans sp ON sp.id = us.plan_id
WHERE us.status = 'ACTIVE'
  AND us.expires_at > CURRENT_TIMESTAMP
  AND sp.category = 'LEARN_ENGLISH'
  AND us.expires_at::date = (CURRENT_DATE + INTERVAL '7 days')::date;

-- name: GetExpiringSubscriptions :many
SELECT 
    us.*,
    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';

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

-- name: HasActiveSubscriptionByCategory :one
SELECT EXISTS(
    SELECT 1
    FROM user_subscriptions us
    JOIN subscription_plans sp ON sp.id = us.plan_id
    WHERE us.user_id = $1
      AND sp.category = $2
      AND us.status = 'ACTIVE'
      AND us.expires_at > CURRENT_TIMESTAMP
) AS has_subscription;

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