/**
 * Customer API Key Management — /api/api-keys
 *
 * Manages externally-issued API keys for customer access to the TIP public API.
 * Keys are stored as SHA-256 hashes. The actual key is shown ONCE at creation.
 *
 * Routes:
 *   POST   /api/api-keys           — Issue a new key (admin-only in prod)
 *   GET    /api/api-keys           — List keys (filter by email)
 *   DELETE /api/api-keys/:id       — Revoke a key
 *   GET    /api/api-keys/stats     — Usage stats per key
 *   POST   /api/api-keys/validate  — Validate a key (internal use by middleware)
 */
import { Router, Request, Response } from "express";
import { createHash, randomBytes } from "crypto";
import { pool } from "../db/client";

export const apiKeysRouter = Router();

function hashKey(key: string): string {
  return createHash("sha256").update(key).digest("hex");
}

function generateKey(): { key: string; prefix: string; hash: string } {
  const raw = randomBytes(24).toString("base64url");
  const key = `tip_${raw}`;
  const prefix = key.slice(0, 12);
  const hash = hashKey(key);
  return { key, prefix, hash };
}

// ── POST /api/api-keys — Issue new key ──────────────────────────────────────
apiKeysRouter.post("/", async (req: Request, res: Response) => {
  const { email, label, tier = "free", rate_limit, expires_in_days } = req.body as Record<string, any>;

  if (!email || !email.includes("@")) {
    return res.status(400).json({ success: false, error: "Valid email required" });
  }
  if (!label || typeof label !== "string") {
    return res.status(400).json({ success: false, error: "label required" });
  }

  const RATE_LIMITS: Record<string, number> = { free: 100, pro: 1000, enterprise: 10000 };
  const resolvedRateLimit = rate_limit ? parseInt(rate_limit) : RATE_LIMITS[tier] || 100;
  const expiresAt = expires_in_days
    ? new Date(Date.now() + parseInt(expires_in_days) * 86400000).toISOString()
    : null;

  try {
    const { key, prefix, hash } = generateKey();
    const result = await pool.query(
      `INSERT INTO api_keys (key_hash, key_prefix, label, email, tier, rate_limit, expires_at)
       VALUES ($1,$2,$3,$4,$5,$6,$7)
       RETURNING id, key_prefix, label, email, tier, rate_limit, active, created_at, expires_at`,
      [hash, prefix, label, email.toLowerCase().trim(), tier, resolvedRateLimit, expiresAt]
    );

    return res.status(201).json({
      success: true,
      api_key: key,          // shown ONCE — client must store it
      warning: "Store this key now — it will not be shown again.",
      meta: result.rows[0],
    });
  } catch (err) {
    return res.status(500).json({ success: false, error: String(err) });
  }
});

// ── GET /api/api-keys?email= — List keys ────────────────────────────────────
apiKeysRouter.get("/", async (req: Request, res: Response) => {
  const email = String(Array.isArray(req.query.email) ? req.query.email[0] ?? "" : req.query.email ?? "").trim().toLowerCase();

  try {
    const result = await pool.query(
      `SELECT id, key_prefix, label, email, tier, rate_limit, active,
              last_used_at, usage_count, created_at, expires_at
       FROM api_keys
       WHERE ($1 = '' OR email = $1)
       ORDER BY created_at DESC
       LIMIT 100`,
      [email]
    );
    return res.json({ success: true, keys: result.rows });
  } catch (err) {
    return res.status(500).json({ success: false, error: String(err) });
  }
});

// ── DELETE /api/api-keys/:id — Revoke key ───────────────────────────────────
apiKeysRouter.delete("/:id", async (req: Request, res: Response) => {
  try {
    const result = await pool.query(
      `UPDATE api_keys SET active = false WHERE id = $1 RETURNING id, key_prefix`,
      [parseInt(String(req.params.id))]
    );
    if (result.rowCount === 0) return res.status(404).json({ success: false, error: "Key not found" });
    return res.json({ success: true, revoked: result.rows[0] });
  } catch (err) {
    return res.status(500).json({ success: false, error: String(err) });
  }
});

// ── GET /api/api-keys/stats — Usage dashboard ───────────────────────────────
apiKeysRouter.get("/stats", async (_req: Request, res: Response) => {
  try {
    const result = await pool.query(`
      SELECT
        tier,
        COUNT(*)                          AS total_keys,
        COUNT(*) FILTER (WHERE active)    AS active_keys,
        SUM(usage_count)                  AS total_requests,
        MAX(last_used_at)                 AS last_activity
      FROM api_keys
      GROUP BY tier
      ORDER BY total_requests DESC
    `);
    return res.json({ success: true, stats: result.rows });
  } catch (err) {
    return res.status(500).json({ success: false, error: String(err) });
  }
});

// ── POST /api/api-keys/validate — Validate key (used by auth middleware) ────
apiKeysRouter.post("/validate", async (req: Request, res: Response) => {
  const { key } = req.body as { key?: string };
  if (!key) return res.status(400).json({ valid: false });

  try {
    const hash = hashKey(key);
    const result = await pool.query(
      `UPDATE api_keys
       SET last_used_at = NOW(), usage_count = usage_count + 1
       WHERE key_hash = $1
         AND active = true
         AND (expires_at IS NULL OR expires_at > NOW())
       RETURNING id, key_prefix, email, tier, rate_limit`,
      [hash]
    );
    if (result.rowCount === 0) return res.json({ valid: false });
    return res.json({ valid: true, ...result.rows[0] });
  } catch (err) {
    return res.status(500).json({ valid: false, error: String(err) });
  }
});
