import { Router, Request, Response } from "express";
import rateLimit from "express-rate-limit";
import { createFreeKey } from "../services/keys.js";
import { createVerification, createPendingVerification, verifyCode, isEmailVerified, getVerifiedApiKey } from "../services/verification.js";
import { sendVerificationEmail } from "../services/email.js";
import logger from "../services/logger.js";

const router = Router();

const signupLimiter = rateLimit({
  windowMs: 60 * 60 * 1000,
  max: 5,
  message: { error: "Too many signup attempts. Please try again in 1 hour." },
  standardHeaders: true,
  legacyHeaders: false,
});

const verifyLimiter = rateLimit({
  windowMs: 15 * 60 * 1000,
  max: 15,
  message: { error: "Too many verification attempts. Please try again later." },
  standardHeaders: true,
  legacyHeaders: false,
});

async function rejectDuplicateEmail(req: Request, res: Response, next: Function) {
  const { email } = req.body || {};
  if (email && typeof email === "string") {
    const cleanEmail = email.trim().toLowerCase();
    if (await isEmailVerified(cleanEmail)) {
      res.status(409).json({ error: "Email already registered" });
      return;
    }
  }
  next();
}

// Step 1: Request signup — generates 6-digit code, sends via email
router.post("/free", rejectDuplicateEmail, signupLimiter, async (req: Request, res: Response) => {
  const { email } = req.body || {};

  if (!email || typeof email !== "string" || !/^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(email)) {
    res.status(400).json({ error: "A valid email address is required." });
    return;
  }

  const cleanEmail = email.trim().toLowerCase();

  if (await isEmailVerified(cleanEmail)) {
    res.status(409).json({ error: "This email is already registered. Contact support if you need help." });
    return;
  }

  const pending = await createPendingVerification(cleanEmail);

  sendVerificationEmail(cleanEmail, pending.code).catch(err => {
    logger.error({ err, email: cleanEmail }, "Failed to send verification email");
  });

  res.json({
    status: "verification_required",
    message: "Check your email for the verification code.",
  });
});

// Step 2: Verify code — creates API key
router.post("/verify", verifyLimiter, async (req: Request, res: Response) => {
  const { email, code } = req.body || {};

  if (!email || !code) {
    res.status(400).json({ error: "Email and code are required." });
    return;
  }

  const cleanEmail = email.trim().toLowerCase();
  const cleanCode = String(code).trim();

  if (await isEmailVerified(cleanEmail)) {
    res.status(409).json({ error: "This email is already verified." });
    return;
  }

  const result = await verifyCode(cleanEmail, cleanCode);

  switch (result.status) {
    case "ok": {
      const keyInfo = await createFreeKey(cleanEmail);
      const verification = await createVerification(cleanEmail, keyInfo.key);
      verification.verifiedAt = new Date().toISOString();

      res.json({
        status: "verified",
        message: "Email verified! Here's your API key.",
        apiKey: keyInfo.key,
        tier: keyInfo.tier,
      });
      break;
    }
    case "expired":
      res.status(410).json({ error: "Verification code has expired. Please sign up again." });
      break;
    case "max_attempts":
      res.status(429).json({ error: "Too many failed attempts. Please sign up again to get a new code." });
      break;
    case "invalid":
      res.status(400).json({ error: "Invalid verification code." });
      break;
  }
});

export { router as signupRouter };
