import { Router, type Request, type Response } from "express";
import { RunDemoQueryParams } from "@workspace/api-zod";
import { agentService } from "../lib/agent.js";
import { makeLogger } from "../lib/logger.js";

const router = Router();
const logger = makeLogger("demo");

const RATE_LIMIT_MAX = 5;
const RATE_LIMIT_WINDOW_MS = 60 * 60 * 1000;

const ipHits = new Map<string, { count: number; resetAt: number }>();

function checkRateLimit(ip: string): { allowed: boolean; resetAt: number; remaining: number } {
  const now = Date.now();
  const entry = ipHits.get(ip);

  if (!entry || now >= entry.resetAt) {
    ipHits.set(ip, { count: 1, resetAt: now + RATE_LIMIT_WINDOW_MS });
    return { allowed: true, resetAt: now + RATE_LIMIT_WINDOW_MS, remaining: RATE_LIMIT_MAX - 1 };
  }

  if (entry.count >= RATE_LIMIT_MAX) {
    return { allowed: false, resetAt: entry.resetAt, remaining: 0 };
  }

  entry.count += 1;
  return { allowed: true, resetAt: entry.resetAt, remaining: RATE_LIMIT_MAX - entry.count };
}

router.get("/demo", async (req: Request, res: Response) => {
  const ip =
    (req.headers["x-forwarded-for"] as string | undefined)?.split(",")[0]?.trim() ??
    req.socket.remoteAddress ??
    "unknown";

  const { allowed, resetAt, remaining } = checkRateLimit(ip);

  res.setHeader("X-RateLimit-Limit", String(RATE_LIMIT_MAX));
  res.setHeader("X-RateLimit-Remaining", String(remaining));
  res.setHeader("X-RateLimit-Reset", String(Math.floor(resetAt / 1000)));

  if (!allowed) {
    const secsUntilReset = Math.ceil((resetAt - Date.now()) / 1000);
    logger.warn("demo rate limited", { ip, retry_after_s: secsUntilReset });
    res.status(429).json({
      error: `Rate limit exceeded. Try again in ${secsUntilReset}s (5 requests per hour per IP).`,
    });
    return;
  }

  const parseResult = RunDemoQueryParams.safeParse(req.query);
  if (!parseResult.success) {
    const issue = parseResult.error.issues[0];
    const error = issue?.code === "too_big"
      ? "Invalid query param: 'request' must be 500 characters or fewer"
      : "Missing required query param: request";
    res.status(400).json({ error });
    return;
  }
  const { request } = parseResult.data;

  logger.info("demo request received", { ip });

  try {
    const { result } = await agentService.executeWork(request);
    res.json({ result });
  } catch (err) {
    const message = err instanceof Error ? err.message : "Agent error";
    logger.error("demo agent error", { ip, error: message });
    res.status(500).json({ error: message });
  }
});

export default router;
