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 { getAgent, loadAgentRegistry } from "../../../../../lib/agent-registry.js";
import { hasRequiredFeatures } from "../../../../../lib/auth.js";
import {
  isKnownMutationPolicy,
  isMutationPolicyEscalation
} from "../../../../../lib/agent-policy.js";
import { AiAgentMutationPolicyOverrideRepository } from "../../../../../data/repositories/AiAgentMutationPolicyOverrideRepository.js";
const agentIdPattern = /^[a-z0-9_]+\.[a-z0-9_]+$/;
const agentIdParamSchema = z.object({
  agentId: z.string().regex(agentIdPattern, 'agentId must match "<module>.<agent>" (lowercase, digits, underscores only)')
});
const mutationPolicySchema = z.enum([
  "read-only",
  "confirm-required",
  "destructive-confirm-required"
]);
const mutationPolicyRequestSchema = z.object({
  mutationPolicy: mutationPolicySchema,
  notes: z.string().max(2e3).optional()
});
const VIEW_FEATURE = "ai_assistant.view";
const MANAGE_FEATURE = "ai_assistant.settings.manage";
const openApi = {
  tag: "AI Assistant",
  summary: "Tenant-scoped mutationPolicy override for an AI agent",
  methods: {
    GET: {
      operationId: "aiAssistantGetMutationPolicyOverride",
      summary: "Read the effective mutationPolicy for an agent \u2014 code-declared value plus any tenant override.",
      description: "Returns `{ agentId, codeDeclared, override }` where `codeDeclared` is the agent's compiled-in `mutationPolicy` and `override` is the persisted tenant-scoped override (or `null`). Requires `ai_assistant.view`.",
      responses: [
        {
          status: 200,
          description: "Effective mutationPolicy payload.",
          mediaType: "application/json"
        }
      ],
      errors: [
        { status: 400, description: "Invalid agent id." },
        { status: 401, description: "Unauthenticated caller." },
        { status: 403, description: "Caller lacks `ai_assistant.view`." },
        { status: 404, description: "Unknown agent id." }
      ]
    },
    POST: {
      operationId: "aiAssistantSaveMutationPolicyOverride",
      summary: "Set (or replace) the tenant-scoped mutationPolicy override for this agent.",
      description: 'Body: `{ mutationPolicy: "read-only" | "confirm-required" | "destructive-confirm-required", notes? }`. The override MUST NOT escalate beyond the agent\'s code-declared policy. Escalation attempts are rejected with 400 + `code: "escalation_not_allowed"`. Requires `ai_assistant.settings.manage`.',
      requestBody: {
        contentType: "application/json",
        description: "Body: `{ mutationPolicy, notes? }`.",
        schema: mutationPolicyRequestSchema
      },
      responses: [
        {
          status: 200,
          description: "Override persisted.",
          mediaType: "application/json"
        }
      ],
      errors: [
        { status: 400, description: "Invalid agent id, malformed body, or escalation attempt." },
        { status: 401, description: "Unauthenticated caller." },
        { status: 403, description: "Caller lacks `ai_assistant.settings.manage`." },
        { status: 404, description: "Unknown agent id." }
      ]
    },
    DELETE: {
      operationId: "aiAssistantClearMutationPolicyOverride",
      summary: "Remove the tenant-scoped mutationPolicy override for this agent.",
      description: "Deletes the override row if it exists; subsequent calls fall back to the agent's code-declared policy. Idempotent \u2014 returns 200 even when no override exists. Requires `ai_assistant.settings.manage`.",
      responses: [
        {
          status: 200,
          description: "Override cleared (or already absent).",
          mediaType: "application/json"
        }
      ],
      errors: [
        { status: 400, description: "Invalid agent id." },
        { status: 401, description: "Unauthenticated caller." },
        { status: 403, description: "Caller lacks `ai_assistant.settings.manage`." },
        { status: 404, description: "Unknown agent id." }
      ]
    }
  }
};
const metadata = {
  GET: { requireAuth: true, requireFeatures: [VIEW_FEATURE] },
  POST: { requireAuth: true, requireFeatures: [MANAGE_FEATURE] },
  DELETE: { requireAuth: true, requireFeatures: [MANAGE_FEATURE] }
};
function jsonError(status, message, code, extra) {
  return NextResponse.json({ error: message, code, ...extra ?? {} }, { status });
}
async function resolveAuthOrRespond(req, requiredFeature) {
  const auth = await getAuthFromRequest(req);
  if (!auth) {
    return jsonError(401, "Unauthorized", "unauthenticated");
  }
  const container = await createRequestContainer();
  const rbacService = container.resolve("rbacService");
  const acl = await rbacService.loadAcl(auth.sub, {
    tenantId: auth.tenantId,
    organizationId: auth.orgId
  });
  if (!hasRequiredFeatures([requiredFeature], acl.features, acl.isSuperAdmin, rbacService)) {
    return jsonError(403, `Caller lacks required feature "${requiredFeature}".`, "forbidden");
  }
  return {
    tenantId: auth.tenantId ?? null,
    organizationId: auth.orgId ?? null,
    userId: auth.sub,
    isSuperAdmin: acl.isSuperAdmin,
    features: acl.features,
    container,
    rbacService
  };
}
function serializeOverride(row) {
  return {
    id: row.id,
    agentId: row.agentId,
    mutationPolicy: row.mutationPolicy,
    notes: row.notes ?? null,
    createdByUserId: row.createdByUserId ?? null,
    createdAt: row.createdAt?.toISOString?.() ?? (/* @__PURE__ */ new Date()).toISOString(),
    updatedAt: row.updatedAt?.toISOString?.() ?? (/* @__PURE__ */ new Date()).toISOString()
  };
}
function codeDeclaredPolicy(agent) {
  const declared = agent.mutationPolicy;
  return declared && isKnownMutationPolicy(declared) ? declared : "read-only";
}
async function GET(req, context) {
  const authResult = await resolveAuthOrRespond(req, VIEW_FEATURE);
  if (authResult instanceof NextResponse) return authResult;
  const rawParams = await context.params;
  const paramResult = agentIdParamSchema.safeParse(rawParams);
  if (!paramResult.success) {
    return jsonError(400, "Invalid agent id.", "validation_error", {
      issues: paramResult.error.issues
    });
  }
  try {
    await loadAgentRegistry();
    const agent = getAgent(paramResult.data.agentId);
    if (!agent) {
      return jsonError(404, `Unknown agent "${paramResult.data.agentId}".`, "agent_unknown");
    }
    const declared = codeDeclaredPolicy(agent);
    if (!authResult.tenantId) {
      return NextResponse.json({
        agentId: agent.id,
        codeDeclared: declared,
        override: null
      });
    }
    const em = authResult.container.resolve("em");
    const repo = new AiAgentMutationPolicyOverrideRepository(em);
    const current = await repo.get(agent.id, {
      tenantId: authResult.tenantId,
      organizationId: authResult.organizationId
    });
    return NextResponse.json({
      agentId: agent.id,
      codeDeclared: declared,
      override: current ? serializeOverride(current) : null
    });
  } catch (error) {
    console.error("[AI Mutation Policy GET] Failure:", error);
    return jsonError(
      500,
      error instanceof Error ? error.message : "Failed to load mutationPolicy override.",
      "internal_error"
    );
  }
}
async function POST(req, context) {
  const authResult = await resolveAuthOrRespond(req, MANAGE_FEATURE);
  if (authResult instanceof NextResponse) return authResult;
  const rawParams = await context.params;
  const paramResult = agentIdParamSchema.safeParse(rawParams);
  if (!paramResult.success) {
    return jsonError(400, "Invalid agent id.", "validation_error", {
      issues: paramResult.error.issues
    });
  }
  let parsedBody;
  try {
    parsedBody = await req.json();
  } catch {
    return jsonError(400, "Request body must be valid JSON.", "validation_error");
  }
  const bodyResult = mutationPolicyRequestSchema.safeParse(parsedBody);
  if (!bodyResult.success) {
    return jsonError(400, "Invalid request body.", "validation_error", {
      issues: bodyResult.error.issues
    });
  }
  try {
    await loadAgentRegistry();
    const agent = getAgent(paramResult.data.agentId);
    if (!agent) {
      return jsonError(404, `Unknown agent "${paramResult.data.agentId}".`, "agent_unknown");
    }
    const declared = codeDeclaredPolicy(agent);
    if (isMutationPolicyEscalation(declared, bodyResult.data.mutationPolicy)) {
      return jsonError(
        400,
        `Cannot set mutationPolicy="${bodyResult.data.mutationPolicy}" for agent "${agent.id}": the agent's code-declared policy is "${declared}". Upgrading beyond the declared policy is a code-level change, not a configuration change.`,
        "escalation_not_allowed",
        { codeDeclared: declared, requested: bodyResult.data.mutationPolicy }
      );
    }
    if (!authResult.tenantId) {
      return jsonError(
        400,
        "Caller has no tenant context; cannot persist tenant-scoped mutationPolicy override.",
        "tenant_required"
      );
    }
    const em = authResult.container.resolve("em");
    const repo = new AiAgentMutationPolicyOverrideRepository(em);
    const saved = await repo.set(
      {
        agentId: agent.id,
        mutationPolicy: bodyResult.data.mutationPolicy,
        notes: bodyResult.data.notes ?? null
      },
      {
        tenantId: authResult.tenantId,
        organizationId: authResult.organizationId,
        userId: authResult.userId
      }
    );
    return NextResponse.json({
      ok: true,
      agentId: agent.id,
      codeDeclared: declared,
      override: serializeOverride(saved)
    });
  } catch (error) {
    console.error("[AI Mutation Policy POST] Failure:", error);
    return jsonError(
      500,
      error instanceof Error ? error.message : "Failed to save mutationPolicy override.",
      "internal_error"
    );
  }
}
async function DELETE(req, context) {
  const authResult = await resolveAuthOrRespond(req, MANAGE_FEATURE);
  if (authResult instanceof NextResponse) return authResult;
  const rawParams = await context.params;
  const paramResult = agentIdParamSchema.safeParse(rawParams);
  if (!paramResult.success) {
    return jsonError(400, "Invalid agent id.", "validation_error", {
      issues: paramResult.error.issues
    });
  }
  try {
    await loadAgentRegistry();
    const agent = getAgent(paramResult.data.agentId);
    if (!agent) {
      return jsonError(404, `Unknown agent "${paramResult.data.agentId}".`, "agent_unknown");
    }
    const declared = codeDeclaredPolicy(agent);
    if (!authResult.tenantId) {
      return NextResponse.json({
        ok: true,
        agentId: agent.id,
        codeDeclared: declared,
        override: null,
        cleared: false
      });
    }
    const em = authResult.container.resolve("em");
    const repo = new AiAgentMutationPolicyOverrideRepository(em);
    const cleared = await repo.clear(agent.id, {
      tenantId: authResult.tenantId,
      organizationId: authResult.organizationId
    });
    return NextResponse.json({
      ok: true,
      agentId: agent.id,
      codeDeclared: declared,
      override: null,
      cleared
    });
  } catch (error) {
    console.error("[AI Mutation Policy DELETE] Failure:", error);
    return jsonError(
      500,
      error instanceof Error ? error.message : "Failed to clear mutationPolicy override.",
      "internal_error"
    );
  }
}
export {
  DELETE,
  GET,
  POST,
  metadata,
  openApi
};
//# sourceMappingURL=route.js.map
