import { consumeAccountRateLimitResetCredit, readAccountRateLimits, readAccountTokenUsage } from "./usage-status.js";

export async function resolveUsageRoute(req, url, context) {
  const historyMatch = url.pathname.match(/^\/accounts\/([^/]+)\/usage\/history$/);
  const tokensMatch = url.pathname.match(/^\/accounts\/([^/]+)\/usage\/tokens$/);
  const usageMatch = url.pathname.match(/^\/accounts\/([^/]+)\/usage$/);
  const resetMatch = url.pathname.match(/^\/accounts\/([^/]+)\/usage\/reset$/);
  if (!historyMatch && !tokensMatch && !usageMatch && !resetMatch) return null;

  const accountId = decodeURIComponent((historyMatch ?? tokensMatch ?? usageMatch ?? resetMatch)[1]);
  requireAccount(context.config, accountId);

  if (req.method === "GET" && historyMatch) {
    const days = Number(url.searchParams.get("days") || 1);
    if (![1, 3, 7, 30].includes(days)) {
      const error = new Error("invalid_usage_history_range");
      error.status = 400;
      throw error;
    }
    const now = (context.now ?? (() => new Date()))();
    const since = new Date(now.getTime() - days * 24 * 60 * 60 * 1000);
    return { status: 200, body: { points: await context.historyStore.history(accountId, since) } };
  }

  if (req.method === "GET" && tokensMatch) {
    try {
      const usage = await (context.readTokenUsage ?? readAccountTokenUsage)(context.config, accountId);
      const body = context.tokenUsageStore ? await context.tokenUsageStore.record(accountId, usage) : usage;
      return { status: 200, body };
    } catch (cause) {
      const cached = await context.tokenUsageStore?.read(accountId);
      if (cached) return { status: 200, body: cached };
      throw cause;
    }
  }

  if (req.method === "GET" && usageMatch) {
    const usage = await (context.readUsage ?? readAccountRateLimits)(context.config, accountId);
    try {
      await context.historyStore.record(accountId, usage);
    } catch {
      (context.logger ?? console).warn("usage history unavailable");
    }
    return { status: 200, body: usage };
  }

  if (req.method === "POST" && resetMatch) {
    return { status: 200, body: await (context.consumeReset ?? consumeAccountRateLimitResetCredit)(context.config, accountId) };
  }

  return null;
}

function requireAccount(config, accountId) {
  if (config.accounts.some((account) => account.id === accountId)) return;
  const error = new Error("account_not_found");
  error.status = 404;
  throw error;
}
