import type { PrismaClient } from "@prisma/client";
import type { FastifyInstance } from "fastify";
import { getSessionDetail, listProjectSessions } from "../../org/sessions.js";
import { getOrgUsage, getProjectUsage } from "../../org/usage.js";
import { requireOrgRole, type GuardDeps } from "../auth/guards.js";
import { handleRouteError } from "../errors.js";

export async function registerSessionsAndUsageRoutes(
  app: FastifyInstance,
  config: { readonly prisma: PrismaClient; readonly sessionSecret: string },
): Promise<void> {
  const guardDeps: GuardDeps = { prisma: config.prisma, sessionSecret: config.sessionSecret };

  app.get("/api/org/:orgSlug/projects/:projectId/sessions", async (request, reply) => {
    try {
      const { orgSlug, projectId } = request.params as { orgSlug: string; projectId: string };
      const auth = await requireOrgRole(request, reply, guardDeps, { orgSlug });
      if (auth === null) return;
      const q = request.query as { limit?: string };
      const limit = q.limit !== undefined ? Number(q.limit) : undefined;
      return {
        sessions: await listProjectSessions(config.prisma, {
          organizationId: auth.organization.id,
          projectId,
          ...(limit !== undefined && Number.isFinite(limit) ? { limit } : {}),
        }),
      };
    } catch (err) {
      return handleRouteError(reply, err);
    }
  });

  app.get("/api/org/:orgSlug/sessions/:sessionId", async (request, reply) => {
    try {
      const { orgSlug, sessionId } = request.params as { orgSlug: string; sessionId: string };
      const auth = await requireOrgRole(request, reply, guardDeps, { orgSlug });
      if (auth === null) return;
      return await getSessionDetail(config.prisma, {
        organizationId: auth.organization.id,
        sessionId,
      });
    } catch (err) {
      return handleRouteError(reply, err);
    }
  });

  app.get("/api/org/:orgSlug/usage", async (request, reply) => {
    try {
      const { orgSlug } = request.params as { orgSlug: string };
      const auth = await requireOrgRole(request, reply, guardDeps, { orgSlug });
      if (auth === null) return;
      const q = request.query as { from?: string; to?: string; folderId?: string };
      return await getOrgUsage(config.prisma, {
        organizationId: auth.organization.id,
        ...(q.from !== undefined && q.from !== "" ? { from: new Date(q.from) } : {}),
        ...(q.to !== undefined && q.to !== "" ? { to: new Date(q.to) } : {}),
        ...(q.folderId !== undefined && q.folderId !== "" ? { folderId: q.folderId } : {}),
      });
    } catch (err) {
      return handleRouteError(reply, err);
    }
  });

  app.get("/api/org/:orgSlug/projects/:projectId/usage", async (request, reply) => {
    try {
      const { orgSlug, projectId } = request.params as { orgSlug: string; projectId: string };
      const auth = await requireOrgRole(request, reply, guardDeps, { orgSlug });
      if (auth === null) return;
      const q = request.query as { from?: string; to?: string };
      return await getProjectUsage(config.prisma, {
        organizationId: auth.organization.id,
        projectId,
        ...(q.from !== undefined && q.from !== "" ? { from: new Date(q.from) } : {}),
        ...(q.to !== undefined && q.to !== "" ? { to: new Date(q.to) } : {}),
      });
    } catch (err) {
      return handleRouteError(reply, err);
    }
  });
}
