/**
 * Grace-period downgrade middleware (Session 9).
 *
 * Fires at request time on tier-gated routes. The Stripe webhook
 * (`customer.subscription.deleted` and `invoice.payment_failed`) sets
 * `users.grace_period_until` to now + 48h on cancellation / payment
 * failure. Until Session 9, nothing actively checked whether the
 * grace had expired — so cancelled users could keep paid access
 * indefinitely. This middleware closes that gap.
 *
 * Behavior:
 *   - No `grace_period_until` on req.user           → pass through
 *   - Grace still in the future                     → pass through
 *   - Grace expired                                 → atomically
 *     downgrade `users.tier` AND `user_profiles.tier` to 'free',
 *     clear the grace timestamp, set subscription_status='expired'
 *     on the profile mirror, and rewrite req.user so the downstream
 *     route immediately sees the downgraded tier.
 *
 * Mount AFTER `requireAuth` on tier-gated routes. Routes that don't
 * gate by tier (e.g. /api/bets read-only views) don't need it.
 *
 * Failure semantics: if either DB write fails, we still call next()
 * — the user might briefly retain paid access until the next request,
 * but at least the route keeps serving. The webhook's grace pointer
 * stays set, so we'll try again on the next request.
 */

const { getSupabaseServiceClient } = require('../utils/supabase');

async function checkGracePeriod(req, res, next) {
  const user = req.user;
  // No user (unauth route slipping through?) — bail to next.
  if (!user || !user.grace_period_until) return next();

  const grace = new Date(user.grace_period_until);
  // Invalid date → treat as no grace.
  if (!Number.isFinite(grace.getTime())) return next();
  // Still in grace window — let them keep paid access.
  if (grace.getTime() > Date.now()) return next();

  // Expired. Downgrade in both tables. We log on failure but DO NOT
  // throw — the route still serves; we re-try on the next request.
  try {
    const supabase = getSupabaseServiceClient();
    const { error: usersErr } = await supabase
      .from('users')
      .update({ tier: 'free', grace_period_until: null })
      .eq('id', user.id);
    if (usersErr) {
      console.warn('[gracePeriod] users update failed:', usersErr.message);
    }

    const { error: profileErr } = await supabase
      .from('user_profiles')
      .update({
        tier: 'free',
        subscription_status: 'expired',
        grace_period_until: null,
      })
      .eq('id', user.id);
    if (profileErr) {
      console.warn('[gracePeriod] user_profiles update failed:', profileErr.message);
    }

    // Reflect on req.user so the downstream route sees the downgrade
    // immediately (no race against a stale closure).
    req.user.tier = 'free';
    req.user.grace_period_until = null;
  } catch (err) {
    console.warn('[gracePeriod] downgrade error (continuing):', err.message);
  }

  return next();
}

module.exports = { checkGracePeriod };
