/**
 * middleware/planGate.js
 * Enforces plan limits server-side.
 *
 *   planGate('scan')    →  scans_used_this_month     < plan.scans_limit     + extra_scans
 *   planGate('takedown')→  takedowns_used_this_month < plan.takedowns_limit + extra_takedowns
 *   planGate('case')    →  active_cases_count        < plan.cases_limit
 *
 *   402 with upgrade prompt if over limit.
 *   200 OK and increments usage on pass.
 *
 * Credit packs (one-time purchases) grant extra_scans / extra_takedowns
 * that are ADDITIVE to the monthly plan quota. Credits never expire and
 * are consumed BEFORE the monthly quota — so a Free user with 5 extra
 * scans gets 5 scans from credits + 10 from the monthly plan = 15 total.
 */

'use strict';

const { getPlan } = require('../config/plans');
const usageLog = require('../models/usageLog');
const User     = require('../models/user');
const Case     = require('../models/case');

// Direct factory rather than closure capture: we need `req` at request time.
function planGate(resource) {
  return (req, res, next) => {
    if (!req.user) return res.status(401).json({ error: 'UNAUTHENTICATED' });
    const plan = getPlan(req.user.plan, req.user.plan_override);
    // The user record may be stale on extra_* if credits were just
    // granted in this same request — re-read fresh.
    const fresh = User.getById(req.user.id) || req.user;
    const extraScans     = fresh.extra_scans     || 0;
    const extraTakedowns = fresh.extra_takedowns || 0;

    let used, limit, effectiveExtra;
    if (resource === 'scan') {
      used  = usageLog.current(req.user.id, 'scan');
      limit = plan.scans_limit + extraScans;
      effectiveExtra = extraScans;
    } else if (resource === 'takedown') {
      used  = usageLog.current(req.user.id, 'takedown');
      limit = plan.takedowns_limit + extraTakedowns;
      effectiveExtra = extraTakedowns;
    } else if (resource === 'case') {
      used  = Case.activeCountForUser(req.user.id);
      limit = plan.cases_limit;
      effectiveExtra = 0;
    } else {
      return res.status(500).json({ error: 'INVALID_RESOURCE' });
    }

    if (used >= limit) {
      return res.status(402).json({
        error: 'PLAN_LIMIT',
        resource,
        used,
        limit,
        plan: req.user.plan,
        upgrade_url: '/billing',
        message: `You've reached your ${plan.name} plan's ${resource} limit (${used}/${limit}). Upgrade for more.`,
      });
    }

    // Increment — credits first, then monthly quota.
    if (resource === 'scan' || resource === 'takedown') {
      if (effectiveExtra > 0) {
        // Prefer burning a credit. If the credit burn fails for any
        // reason, fall through to the monthly counter.
        const burned = User.consumeCredit(req.user.id, resource);
        if (!burned) usageLog.increment(req.user.id, resource);
      } else {
        usageLog.increment(req.user.id, resource);
      }
    }

    next();
  };
}

module.exports = planGate;
