import { NextResponse } from "next/server";
import { z } from "zod";
import { getAuthFromRequest } from "@open-mercato/shared/lib/auth/server";
import { createRequestContainer } from "@open-mercato/shared/lib/di/container";
import { hasRequiredFeatures } from "../../../lib/auth.js";
import { toInteger, toIsoString } from "../../../lib/usage-serialization.js";
const REQUIRED_FEATURE = "ai_assistant.settings.manage";
const MAX_PAGE_SIZE = 100;
const querySchema = z.object({
  from: z.string().regex(/^\d{4}-\d{2}-\d{2}$/, "from must be a date in YYYY-MM-DD format"),
  to: z.string().regex(/^\d{4}-\d{2}-\d{2}$/, "to must be a date in YYYY-MM-DD format"),
  agentId: z.string().min(1).max(256).optional(),
  limit: z.string().optional().transform((val) => val !== void 0 ? parseInt(val, 10) : MAX_PAGE_SIZE).refine((val) => !isNaN(val) && val > 0 && val <= MAX_PAGE_SIZE, {
    message: `limit must be between 1 and ${MAX_PAGE_SIZE}`
  }),
  offset: z.string().optional().transform((val) => val !== void 0 ? parseInt(val, 10) : 0).refine((val) => !isNaN(val) && val >= 0, { message: "offset must be a non-negative integer" })
});
const openApi = {
  tag: "AI Assistant",
  summary: "Per-session token usage totals",
  methods: {
    GET: {
      operationId: "aiAssistantUsageSessions",
      summary: "List per-session token usage totals for a date window.",
      description: "Returns aggregated token-usage data grouped by `session_id` from `ai_token_usage_events` for the given date window. Tenant-scoped. Optionally filtered by `agentId`. Paginated via `limit` / `offset`. Requires `ai_assistant.settings.manage`.",
      query: querySchema,
      responses: [
        {
          status: 200,
          description: "Array of session-level usage summaries plus pagination metadata.",
          mediaType: "application/json"
        }
      ],
      errors: [
        { status: 400, description: "Invalid query parameters." },
        { status: 401, description: "Unauthenticated caller." },
        { status: 403, description: "Caller lacks `ai_assistant.settings.manage`." },
        { status: 500, description: "Internal failure." }
      ]
    }
  }
};
const metadata = {
  path: "/ai_assistant/usage/sessions",
  GET: { requireAuth: true, requireFeatures: [REQUIRED_FEATURE] }
};
function jsonError(status, message, code, extra) {
  return NextResponse.json({ error: message, code, ...extra ?? {} }, { status });
}
async function GET(req) {
  const auth = await getAuthFromRequest(req);
  if (!auth) {
    return jsonError(401, "Unauthorized", "unauthenticated");
  }
  const { searchParams } = new URL(req.url);
  const rawQuery = {
    from: searchParams.get("from") ?? void 0,
    to: searchParams.get("to") ?? void 0,
    agentId: searchParams.get("agentId") ?? void 0,
    limit: searchParams.get("limit") ?? void 0,
    offset: searchParams.get("offset") ?? void 0
  };
  const queryResult = querySchema.safeParse(rawQuery);
  if (!queryResult.success) {
    return jsonError(400, "Invalid query parameters.", "validation_error", {
      issues: queryResult.error.issues
    });
  }
  const { from, to, agentId, limit, offset } = queryResult.data;
  try {
    const container = await createRequestContainer();
    const rbacService = container.resolve("rbacService");
    const acl = await rbacService.loadAcl(auth.sub, {
      tenantId: auth.tenantId,
      organizationId: auth.orgId
    });
    if (!hasRequiredFeatures([REQUIRED_FEATURE], acl.features, acl.isSuperAdmin, rbacService)) {
      return jsonError(403, `Caller lacks required feature "${REQUIRED_FEATURE}".`, "forbidden");
    }
    if (!auth.tenantId) {
      return NextResponse.json({ sessions: [], total: 0, limit, offset });
    }
    const em = container.resolve("em");
    const connection = em.getConnection();
    const params = [auth.tenantId, from, to];
    let agentFilter = "";
    if (agentId) {
      agentFilter = "and agent_id = ?";
      params.push(agentId);
    }
    const countParams = [...params];
    const countSql = `
      select count(distinct session_id)::bigint as total
      from ai_token_usage_events
      where tenant_id = ?
        and created_at >= ?::date
        and created_at < (?::date + interval '1 day')
        ${agentFilter}
    `;
    const countRows = await connection.execute(countSql, countParams, "all");
    const totalRaw = Array.isArray(countRows) && countRows.length > 0 ? countRows[0].total : "0";
    const total = toInteger(totalRaw);
    params.push(limit, offset);
    const dataSql = `
      select
        session_id,
        agent_id,
        module_id,
        user_id,
        min(created_at) as started_at,
        max(created_at) as last_event_at,
        count(*)::bigint as step_count,
        count(distinct turn_id)::bigint as turn_count,
        sum(input_tokens)::bigint as input_tokens,
        sum(output_tokens)::bigint as output_tokens,
        sum(coalesce(cached_input_tokens, 0))::bigint as cached_input_tokens,
        sum(coalesce(reasoning_tokens, 0))::bigint as reasoning_tokens
      from ai_token_usage_events
      where tenant_id = ?
        and created_at >= ?::date
        and created_at < (?::date + interval '1 day')
        ${agentFilter}
      group by session_id, agent_id, module_id, user_id
      order by started_at desc
      limit ? offset ?
    `;
    const dataRows = await connection.execute(dataSql, params, "all");
    const sessions = Array.isArray(dataRows) ? dataRows.map((row) => ({
      sessionId: row.session_id,
      agentId: row.agent_id,
      moduleId: row.module_id,
      userId: row.user_id,
      startedAt: toIsoString(row.started_at),
      lastEventAt: toIsoString(row.last_event_at),
      stepCount: toInteger(row.step_count),
      turnCount: toInteger(row.turn_count),
      inputTokens: toInteger(row.input_tokens),
      outputTokens: toInteger(row.output_tokens),
      cachedInputTokens: toInteger(row.cached_input_tokens),
      reasoningTokens: toInteger(row.reasoning_tokens)
    })) : [];
    return NextResponse.json({ sessions, total, limit, offset });
  } catch (error) {
    console.error("[AI Usage Sessions] GET error:", error);
    return jsonError(500, "Failed to fetch session usage data.", "internal_error");
  }
}
export {
  GET,
  metadata,
  openApi
};
//# sourceMappingURL=route.js.map
