/**
 * Mount point for `/api/org/:orgSlug/*` org-admin APIs.
 */
import type { PrismaClient } from "@prisma/client";
import type { FastifyInstance } from "fastify";
import { requireOrgRole, type GuardDeps } from "../auth/guards.js";
import { handleRouteError } from "../errors.js";
import {
  ensureOrganizationProjectSettings,
  setMembersCanCreateProjects,
} from "../../projectOnboarding.js";
import { registerAccessRoutes } from "./accessRoutes.js";
import { registerExplorerRoutes } from "./explorerRoutes.js";
import { registerMembersRoutes } from "./membersRoutes.js";
import { registerSessionsAndUsageRoutes } from "./sessionsRoutes.js";
import { registerTeamsRoutes } from "./teamsRoutes.js";
import { registerProviderConnectionRoutes } from "./providerConnectionRoutes.js";
import { registerCapacityRoutes } from "./capacityRoutes.js";
import { readSkillStoreRoot } from "../../agent/skillStore.js";
import { registerAgentConfigRoutes } from "./agentConfigRoutes.js";
import type { LocalSecretEnvelope } from "../../security/secretEnvelope.js";
import type { ProviderReadinessProbe } from "../../connections/providerReadiness.js";
import type { FeishuReadinessProbe } from "../../connections/feishuReadiness.js";
import { registerFeishuApplicationConnectionRoutes } from "./feishuApplicationConnectionRoutes.js";
import { registerCapabilityConnectionRoutes } from "./capabilityConnectionRoutes.js";
import type { CapabilityReadinessProbe } from "../../capability/capabilityReadiness.js";

export interface OrgRouteConfig {
  readonly prisma: PrismaClient;
  readonly sessionSecret: string;
  readonly projectWorkspaceRoot: string;
  readonly secretEnvelope: LocalSecretEnvelope;
  readonly providerReadinessProbe?: ProviderReadinessProbe;
  readonly feishuConnectionReadinessProbe?: FeishuReadinessProbe;
  readonly capabilityReadinessProbe?: CapabilityReadinessProbe;
}

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

  app.get("/api/org/:orgSlug", async (request, reply) => {
    try {
      const { orgSlug } = request.params as { orgSlug: string };
      const auth = await requireOrgRole(request, reply, guardDeps, { orgSlug });
      if (auth === null) return;
      return {
        organization: {
          id: auth.organization.id,
          slug: auth.organization.slug,
          name: auth.organization.name,
          status: auth.organization.status,
        },
        actorRole: auth.membershipRole,
      };
    } catch (err) {
      return handleRouteError(reply, err);
    }
  });

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

  app.patch("/api/org/:orgSlug/settings", async (request, reply) => {
    try {
      const { orgSlug } = request.params as { orgSlug: string };
      const auth = await requireOrgRole(request, reply, guardDeps, { orgSlug });
      if (auth === null) return;
      const body = request.body as { membersCanCreateProjects?: unknown };
      if (typeof body.membersCanCreateProjects !== "boolean") {
        return reply.status(400).send({
          error: { code: "bad_request", message: "membersCanCreateProjects must be a boolean" },
        });
      }
      const settings = await setMembersCanCreateProjects(config.prisma, {
        organizationId: auth.organization.id,
        enabled: body.membersCanCreateProjects,
      });
      return {
        membersCanCreateProjects: settings.membersCanCreateProjects,
      };
    } catch (err) {
      return handleRouteError(reply, err);
    }
  });

  await registerExplorerRoutes(app, {
    prisma: config.prisma,
    sessionSecret: config.sessionSecret,
    projectWorkspaceRoot: config.projectWorkspaceRoot,
  });
  await registerMembersRoutes(app, {
    prisma: config.prisma,
    sessionSecret: config.sessionSecret,
  });
  await registerTeamsRoutes(app, {
    prisma: config.prisma,
    sessionSecret: config.sessionSecret,
  });
  await registerAccessRoutes(app, {
    prisma: config.prisma,
    sessionSecret: config.sessionSecret,
  });
  await registerCapacityRoutes(app, {
    prisma: config.prisma,
    sessionSecret: config.sessionSecret,
  });
  await registerAgentConfigRoutes(app, {
    prisma: config.prisma,
    sessionSecret: config.sessionSecret,
    skillStoreRoot: readSkillStoreRoot(),
    secretEnvelope: config.secretEnvelope,
  });
  await registerSessionsAndUsageRoutes(app, {
    prisma: config.prisma,
    sessionSecret: config.sessionSecret,
  });
  await registerProviderConnectionRoutes(app, {
    prisma: config.prisma,
    sessionSecret: config.sessionSecret,
    secretEnvelope: config.secretEnvelope,
    ...(config.providerReadinessProbe !== undefined
      ? { providerReadinessProbe: config.providerReadinessProbe }
      : {}),
  });
  await registerFeishuApplicationConnectionRoutes(app, {
    prisma: config.prisma,
    sessionSecret: config.sessionSecret,
    secretEnvelope: config.secretEnvelope,
    ...(config.feishuConnectionReadinessProbe !== undefined
      ? { readinessProbe: config.feishuConnectionReadinessProbe }
      : {}),
  });
  await registerCapabilityConnectionRoutes(app, {
    prisma: config.prisma,
    sessionSecret: config.sessionSecret,
    secretEnvelope: config.secretEnvelope,
    ...(config.capabilityReadinessProbe !== undefined
      ? { readinessProbe: config.capabilityReadinessProbe }
      : {}),
  });
}
