/**
 * routes/download-lead.js — self-hosted download email capture.
 *
 * Owns: POST /api/download/lead (email capture before the release zip download),
 *       GET /api/download/admin/leads (admin list).
 * Does NOT own: the /download page itself (server.js), analytics events
 *       (routes/analytics.js), license issuing (routes/license.js).
 *
 * Soft gate: the download ALWAYS proceeds client-side even if this fails —
 * a storage error is logged and swallowed, never surfaced as an error status.
 * No auth required.
 *
 * Mounted at: /api/download (see server.js)
 */

'use strict';

const express = require('express');
const crypto  = require('crypto');
const { z }   = require('zod');
const router  = express.Router();

const { insertDownloadLead, listDownloadLeads } = require('../db/download-leads');
const { validateBody, authLimiter }            = require('../middleware/security');
const { requireAdmin }                         = require('../middleware/auth');

// Same shape as magicLinkSchema, plus .trim() — zod's .email() does not trim, and a
// pasted/autofilled address with a stray space must not cost someone their download.
const downloadLeadSchema = z.object({
  email        : z.string().trim().email('Valid email required').max(254),
  version      : z.string().max(32).optional(),
  utm_source   : z.string().max(128).optional(),
  utm_medium   : z.string().max(128).optional(),
  utm_campaign : z.string().max(128).optional(),
});

// ---------------------------------------------------------------------------
// POST /api/download/lead — email capture before the self-hosted zip download.
// Public, no auth. authLimiter = 10 req/min per IP (reused from the magic-link
// path — the tightest existing limiter, and the same email-form shape).
// Returns { ok: true } even when the insert fails: the client starts the
// download off this response and must never be trapped by our storage errors.
// ---------------------------------------------------------------------------
router.post('/lead', authLimiter, validateBody(downloadLeadSchema), async (req, res) => {
  const { email, version, utm_source, utm_medium, utm_campaign } = req.body;

  try {
    const rawIp    = req.ip || (req.headers['x-forwarded-for'] || '').split(',')[0].trim() || '';
    const ipHash   = rawIp ? crypto.createHash('sha256').update(rawIp).digest('hex') : null;
    const referrer = req.headers['referer'] || req.headers['referrer'] || null;

    await insertDownloadLead({
      email,
      downloadedVersion : version || null,
      ipHash,
      referrer,
      utmSource         : utm_source   || null,
      utmMedium         : utm_medium   || null,
      utmCampaign       : utm_campaign || null,
    });
  } catch (err) {
    // Never block the download — lead capture is always best-effort.
    console.error('[download-lead] lead insert error:', err.message);
  }

  res.json({ ok: true });
});

// ---------------------------------------------------------------------------
// GET /api/download/admin/leads — admin list of captured download leads.
// ---------------------------------------------------------------------------
router.get('/admin/leads', requireAdmin, async (req, res) => {
  try {
    const limit  = Math.min(parseInt(req.query.limit, 10)  || 100, 500);
    const offset = parseInt(req.query.offset, 10) || 0;
    res.json({ leads: await listDownloadLeads({ limit, offset }) });
  } catch (err) {
    console.error('[download-lead] admin list error:', err.message);
    res.status(500).json({ error: 'Failed to load download leads' });
  }
});

module.exports = router;
