import { NextResponse } from "next/server";
import { z } from "zod";
import { createRequestContainer } from "@open-mercato/shared/lib/di/container";
import { getAuthFromRequest } from "@open-mercato/shared/lib/auth/server";
import { resolveOrganizationScopeForRequest } from "@open-mercato/core/modules/directory/utils/organizationScope";
import { resolveOrganizationScopeFilter } from "@open-mercato/core/modules/directory/utils/organizationScopeFilter";
import { WorkflowDefinition } from "../../../data/entities.js";
import {
  updateWorkflowDefinitionInputSchema
} from "../../../data/validators.js";
import { serializeWorkflowDefinition, serializeCodeWorkflowDefinition } from "../serialize.js";
import { invalidateTriggerCache } from "../../../lib/event-trigger-service.js";
import { getCodeWorkflow } from "../../../lib/code-registry.js";
import { createGenericOptimisticLockReader } from "@open-mercato/shared/lib/crud/optimistic-lock";
import { registerOptimisticLockReaderIfAbsent } from "@open-mercato/shared/lib/crud/optimistic-lock-store";
import { validateCrudMutationGuard, runCrudMutationGuardAfterSuccess } from "@open-mercato/shared/lib/crud/mutation-guard";
import { enforceCommandOptimisticLockWithGuards } from "@open-mercato/shared/lib/crud/optimistic-lock-command";
import { isCrudHttpError } from "@open-mercato/shared/lib/crud/errors";
import { createLogger } from "@open-mercato/shared/lib/logger";
const logger = createLogger("workflows");
registerOptimisticLockReaderIfAbsent({
  "workflows.definition": createGenericOptimisticLockReader({
    entity: WorkflowDefinition,
    idField: "id",
    tenantField: "tenantId",
    orgField: "organizationId",
    softDeleteField: "deletedAt"
  })
});
const metadata = {
  requireAuth: true,
  requireFeatures: ["workflows.definitions.view"]
};
async function GET(request, context) {
  try {
    const params = await context.params;
    const container = await createRequestContainer();
    const em = container.resolve("em");
    const auth = await getAuthFromRequest(request);
    if (!auth) {
      return NextResponse.json({ error: "Unauthorized" }, { status: 401 });
    }
    const scope = await resolveOrganizationScopeForRequest({ container, auth, request });
    const tenantId = auth.tenantId;
    const orgFilter = resolveOrganizationScopeFilter(scope, auth);
    if (params.id.startsWith("code:")) {
      const workflowId = params.id.slice(5);
      const codeDef = getCodeWorkflow(workflowId);
      if (!codeDef) {
        return NextResponse.json(
          { error: "Workflow definition not found" },
          { status: 404 }
        );
      }
      return NextResponse.json({
        data: serializeCodeWorkflowDefinition(codeDef, params.id)
      });
    }
    const definition = await em.findOne(WorkflowDefinition, {
      id: params.id,
      tenantId,
      ...orgFilter.where,
      deletedAt: null
    });
    if (!definition) {
      return NextResponse.json(
        { error: "Workflow definition not found" },
        { status: 404 }
      );
    }
    return NextResponse.json({ data: serializeWorkflowDefinition(definition) });
  } catch (error) {
    logger.error("Error getting workflow definition", { err: error });
    return NextResponse.json(
      { error: "Failed to get workflow definition" },
      { status: 500 }
    );
  }
}
async function PUT(request, context) {
  try {
    const params = await context.params;
    const container = await createRequestContainer();
    const em = container.resolve("em");
    const auth = await getAuthFromRequest(request);
    if (!auth) {
      return NextResponse.json({ error: "Unauthorized" }, { status: 401 });
    }
    const scope = await resolveOrganizationScopeForRequest({ container, auth, request });
    const tenantId = auth.tenantId;
    const organizationId = scope?.selectedId ?? auth.orgId;
    const rbacService = container.resolve("rbacService");
    const hasPermission = await rbacService.userHasAllFeatures(
      auth.sub,
      ["workflows.definitions.edit"],
      {
        tenantId,
        organizationId
      }
    );
    if (!hasPermission) {
      return NextResponse.json(
        { error: "Insufficient permissions" },
        { status: 403 }
      );
    }
    const body = await request.json();
    const validation = updateWorkflowDefinitionInputSchema.safeParse(body);
    if (!validation.success) {
      return NextResponse.json(
        {
          error: "Validation failed",
          details: validation.error.issues
        },
        { status: 400 }
      );
    }
    const input = validation.data;
    const guardResult = await validateCrudMutationGuard(container, {
      tenantId: tenantId ?? "",
      organizationId: organizationId ?? null,
      userId: auth.sub ?? "",
      resourceKind: "workflows.definition",
      resourceId: params.id,
      operation: "update",
      requestMethod: "PUT",
      requestHeaders: request.headers,
      mutationPayload: input
    });
    if (guardResult && !guardResult.ok) {
      return NextResponse.json(guardResult.body, { status: guardResult.status });
    }
    if (params.id.startsWith("code:")) {
      const workflowId = params.id.slice(5);
      const codeDef = getCodeWorkflow(workflowId);
      if (!codeDef) {
        return NextResponse.json(
          { error: "Workflow definition not found" },
          { status: 404 }
        );
      }
      const existingOverride = await em.findOne(WorkflowDefinition, {
        workflowId: codeDef.workflowId,
        tenantId
      });
      let savedOverride;
      if (existingOverride) {
        try {
          await enforceCommandOptimisticLockWithGuards(container, {
            resourceKind: "workflows.definition",
            resourceId: existingOverride.id,
            current: existingOverride.updatedAt ?? null,
            request
          });
        } catch (lockError) {
          if (isCrudHttpError(lockError)) {
            return NextResponse.json(lockError.body, { status: lockError.status });
          }
          throw lockError;
        }
        existingOverride.deletedAt = null;
        existingOverride.workflowName = codeDef.workflowName;
        existingOverride.description = codeDef.description;
        existingOverride.version = codeDef.version;
        existingOverride.definition = input.definition ?? codeDef.definition;
        existingOverride.metadata = codeDef.metadata ?? null;
        existingOverride.enabled = input.enabled ?? codeDef.enabled;
        existingOverride.codeWorkflowId = codeDef.workflowId;
        existingOverride.updatedBy = auth.sub;
        existingOverride.updatedAt = /* @__PURE__ */ new Date();
        await em.flush();
        savedOverride = existingOverride;
      } else {
        const override = em.create(WorkflowDefinition, {
          workflowId: codeDef.workflowId,
          workflowName: codeDef.workflowName,
          description: codeDef.description,
          version: codeDef.version,
          definition: input.definition ?? codeDef.definition,
          metadata: codeDef.metadata,
          enabled: input.enabled ?? codeDef.enabled,
          codeWorkflowId: codeDef.workflowId,
          tenantId,
          organizationId,
          createdBy: auth.sub,
          updatedBy: auth.sub,
          createdAt: /* @__PURE__ */ new Date(),
          updatedAt: /* @__PURE__ */ new Date()
        });
        em.persist(override);
        await em.flush();
        savedOverride = override;
      }
      try {
        const eventBus = container.resolve("eventBus");
        if (eventBus && typeof eventBus.emitEvent === "function") {
          await eventBus.emitEvent(
            "workflows.definition.customized",
            {
              id: savedOverride.id,
              workflowId: savedOverride.workflowId,
              codeWorkflowId: savedOverride.codeWorkflowId ?? null,
              tenantId: savedOverride.tenantId,
              organizationId: savedOverride.organizationId,
              userId: auth.sub ?? null
            },
            { tenantId: savedOverride.tenantId, organizationId: savedOverride.organizationId, persistent: true }
          );
        }
      } catch (eventError) {
        logger.error("Failed to emit workflows.definition.customized event", { err: eventError });
      }
      if (guardResult?.shouldRunAfterSuccess) {
        await runCrudMutationGuardAfterSuccess(container, {
          tenantId: tenantId ?? "",
          organizationId: organizationId ?? null,
          userId: auth.sub ?? "",
          resourceKind: "workflows.definition",
          resourceId: String(savedOverride.id),
          operation: "update",
          requestMethod: "PUT",
          requestHeaders: request.headers,
          metadata: guardResult.metadata
        });
      }
      return NextResponse.json({
        data: serializeWorkflowDefinition(savedOverride),
        message: "Workflow definition customized successfully"
      });
    }
    const definition = await em.findOne(WorkflowDefinition, {
      id: params.id,
      tenantId,
      organizationId,
      deletedAt: null
    });
    if (!definition) {
      return NextResponse.json(
        { error: "Workflow definition not found" },
        { status: 404 }
      );
    }
    try {
      await enforceCommandOptimisticLockWithGuards(container, {
        resourceKind: "workflows.definition",
        resourceId: definition.id,
        current: definition.updatedAt ?? null,
        request
      });
    } catch (lockError) {
      if (isCrudHttpError(lockError)) {
        return NextResponse.json(lockError.body, { status: lockError.status });
      }
      throw lockError;
    }
    if (input.workflowName !== void 0) {
      definition.workflowName = input.workflowName;
    }
    if (input.description !== void 0) {
      definition.description = input.description;
    }
    if (input.version !== void 0) {
      definition.version = input.version;
    }
    if (input.definition !== void 0) {
      definition.definition = input.definition;
    }
    if (input.metadata !== void 0) {
      definition.metadata = input.metadata;
    }
    if (input.enabled !== void 0) {
      definition.enabled = input.enabled;
    }
    if (input.effectiveFrom !== void 0) {
      definition.effectiveFrom = input.effectiveFrom;
    }
    if (input.effectiveTo !== void 0) {
      definition.effectiveTo = input.effectiveTo;
    }
    definition.updatedAt = /* @__PURE__ */ new Date();
    await em.flush();
    if (guardResult?.shouldRunAfterSuccess) {
      await runCrudMutationGuardAfterSuccess(container, {
        tenantId: tenantId ?? "",
        organizationId: organizationId ?? null,
        userId: auth.sub ?? "",
        resourceKind: "workflows.definition",
        resourceId: String(definition.id),
        operation: "update",
        requestMethod: "PUT",
        requestHeaders: request.headers,
        metadata: guardResult.metadata
      });
    }
    if (tenantId) invalidateTriggerCache(tenantId, organizationId ?? void 0);
    return NextResponse.json({
      data: serializeWorkflowDefinition(definition),
      message: "Workflow definition updated successfully"
    });
  } catch (error) {
    logger.error("Error updating workflow definition", { err: error });
    return NextResponse.json(
      { error: "Failed to update workflow definition" },
      { status: 500 }
    );
  }
}
async function DELETE(request, context) {
  try {
    const params = await context.params;
    const container = await createRequestContainer();
    const em = container.resolve("em");
    const auth = await getAuthFromRequest(request);
    if (!auth) {
      return NextResponse.json({ error: "Unauthorized" }, { status: 401 });
    }
    const scope = await resolveOrganizationScopeForRequest({ container, auth, request });
    const tenantId = auth.tenantId;
    const organizationId = scope?.selectedId ?? auth.orgId;
    const rbacService = container.resolve("rbacService");
    const hasPermission = await rbacService.userHasAllFeatures(
      auth.sub,
      ["workflows.definitions.delete"],
      {
        tenantId,
        organizationId
      }
    );
    if (!hasPermission) {
      return NextResponse.json(
        { error: "Insufficient permissions" },
        { status: 403 }
      );
    }
    const definition = await em.findOne(WorkflowDefinition, {
      id: params.id,
      tenantId,
      organizationId,
      deletedAt: null
    });
    if (!definition) {
      return NextResponse.json(
        { error: "Workflow definition not found" },
        { status: 404 }
      );
    }
    const guardResult = await validateCrudMutationGuard(container, {
      tenantId: tenantId ?? "",
      organizationId: organizationId ?? null,
      userId: auth.sub ?? "",
      resourceKind: "workflows.definition",
      resourceId: params.id,
      operation: "delete",
      requestMethod: "DELETE",
      requestHeaders: request.headers
    });
    if (guardResult && !guardResult.ok) {
      return NextResponse.json(guardResult.body, { status: guardResult.status });
    }
    const { WorkflowInstance } = await import("../../../data/entities.js");
    const activeInstances = await em.count(WorkflowInstance, {
      definitionId: definition.id,
      status: { $in: ["RUNNING", "WAITING"] }
    });
    if (activeInstances > 0) {
      return NextResponse.json(
        {
          error: `Cannot delete workflow definition with ${activeInstances} active instance(s)`
        },
        { status: 409 }
      );
    }
    definition.deletedAt = /* @__PURE__ */ new Date();
    definition.updatedAt = /* @__PURE__ */ new Date();
    await em.flush();
    if (guardResult?.shouldRunAfterSuccess) {
      await runCrudMutationGuardAfterSuccess(container, {
        tenantId: tenantId ?? "",
        organizationId: organizationId ?? null,
        userId: auth.sub ?? "",
        resourceKind: "workflows.definition",
        resourceId: String(definition.id),
        operation: "delete",
        requestMethod: "DELETE",
        requestHeaders: request.headers,
        metadata: guardResult.metadata
      });
    }
    if (tenantId) invalidateTriggerCache(tenantId, organizationId ?? void 0);
    return NextResponse.json({
      message: "Workflow definition deleted successfully"
    });
  } catch (error) {
    logger.error("Error deleting workflow definition", { err: error });
    return NextResponse.json(
      { error: "Failed to delete workflow definition" },
      { status: 500 }
    );
  }
}
const openApi = {
  methods: {
    GET: {
      summary: "Get workflow definition",
      description: "Get a single workflow definition by ID. Returns the complete workflow structure including steps and transitions (with embedded activities).",
      tags: ["Workflows"],
      pathParams: z.object({
        id: z.string().describe('UUID for DB definitions, or "code:<workflowId>" for code-based definitions')
      }),
      responses: [
        {
          status: 200,
          description: "Workflow definition found",
          example: {
            data: {
              id: "123e4567-e89b-12d3-a456-426614174000",
              workflowId: "checkout-flow",
              workflowName: "Checkout Flow",
              description: "Complete checkout workflow for processing orders",
              version: 1,
              definition: {
                steps: [
                  {
                    stepId: "start",
                    stepName: "Start",
                    stepType: "START"
                  },
                  {
                    stepId: "validate-cart",
                    stepName: "Validate Cart",
                    stepType: "AUTOMATED",
                    description: "Validate cart items and check inventory"
                  },
                  {
                    stepId: "payment",
                    stepName: "Process Payment",
                    stepType: "AUTOMATED",
                    description: "Charge payment method",
                    retryPolicy: {
                      maxAttempts: 3,
                      backoffMs: 1e3
                    }
                  },
                  {
                    stepId: "end",
                    stepName: "End",
                    stepType: "END"
                  }
                ],
                transitions: [
                  {
                    transitionId: "start-to-validate",
                    fromStepId: "start",
                    toStepId: "validate-cart",
                    trigger: "auto"
                  },
                  {
                    transitionId: "validate-to-payment",
                    fromStepId: "validate-cart",
                    toStepId: "payment",
                    trigger: "auto"
                  },
                  {
                    transitionId: "payment-to-end",
                    fromStepId: "payment",
                    toStepId: "end",
                    trigger: "auto",
                    activities: [
                      {
                        activityName: "Send Order Confirmation",
                        activityType: "SEND_EMAIL",
                        config: {
                          to: "{{context.customerEmail}}",
                          subject: "Order Confirmation #{{context.orderId}}",
                          template: "order_confirmation"
                        }
                      }
                    ]
                  }
                ]
              },
              enabled: true,
              tenantId: "123e4567-e89b-12d3-a456-426614174001",
              organizationId: "123e4567-e89b-12d3-a456-426614174002",
              createdAt: "2025-12-08T10:00:00.000Z",
              updatedAt: "2025-12-08T10:00:00.000Z"
            }
          }
        },
        {
          status: 404,
          description: "Workflow definition not found",
          example: {
            error: "Workflow definition not found"
          }
        }
      ]
    },
    PUT: {
      summary: "Update workflow definition",
      description: "Update an existing workflow definition. Supports partial updates - only provided fields will be updated.",
      tags: ["Workflows"],
      pathParams: z.object({
        id: z.string().uuid()
      }),
      requestBody: {
        schema: updateWorkflowDefinitionInputSchema,
        example: {
          definition: {
            steps: [
              {
                stepId: "start",
                stepName: "Start",
                stepType: "START"
              },
              {
                stepId: "validate-cart",
                stepName: "Validate Cart",
                stepType: "AUTOMATED"
              },
              {
                stepId: "payment",
                stepName: "Process Payment",
                stepType: "AUTOMATED"
              },
              {
                stepId: "confirmation",
                stepName: "Order Confirmation",
                stepType: "AUTOMATED"
              },
              {
                stepId: "end",
                stepName: "End",
                stepType: "END"
              }
            ],
            transitions: [
              {
                transitionId: "start-to-validate",
                fromStepId: "start",
                toStepId: "validate-cart",
                trigger: "auto"
              },
              {
                transitionId: "validate-to-payment",
                fromStepId: "validate-cart",
                toStepId: "payment",
                trigger: "auto"
              },
              {
                transitionId: "payment-to-confirmation",
                fromStepId: "payment",
                toStepId: "confirmation",
                trigger: "auto"
              },
              {
                transitionId: "confirmation-to-end",
                fromStepId: "confirmation",
                toStepId: "end",
                trigger: "auto"
              }
            ]
          },
          enabled: true
        }
      },
      responses: [
        {
          status: 200,
          description: "Workflow definition updated successfully",
          example: {
            data: {
              id: "123e4567-e89b-12d3-a456-426614174000",
              workflowId: "checkout-flow",
              workflowName: "Checkout Flow",
              description: "Complete checkout workflow for processing orders",
              version: 1,
              definition: {
                steps: [
                  { stepId: "start", stepName: "Start", stepType: "START" },
                  {
                    stepId: "validate-cart",
                    stepName: "Validate Cart",
                    stepType: "AUTOMATED"
                  },
                  {
                    stepId: "payment",
                    stepName: "Process Payment",
                    stepType: "AUTOMATED"
                  },
                  {
                    stepId: "confirmation",
                    stepName: "Order Confirmation",
                    stepType: "AUTOMATED"
                  },
                  { stepId: "end", stepName: "End", stepType: "END" }
                ],
                transitions: [
                  {
                    transitionId: "start-to-validate",
                    fromStepId: "start",
                    toStepId: "validate-cart",
                    trigger: "auto"
                  },
                  {
                    transitionId: "validate-to-payment",
                    fromStepId: "validate-cart",
                    toStepId: "payment",
                    trigger: "auto"
                  },
                  {
                    transitionId: "payment-to-confirmation",
                    fromStepId: "payment",
                    toStepId: "confirmation",
                    trigger: "auto"
                  },
                  {
                    transitionId: "confirmation-to-end",
                    fromStepId: "confirmation",
                    toStepId: "end",
                    trigger: "auto"
                  }
                ]
              },
              enabled: true,
              tenantId: "123e4567-e89b-12d3-a456-426614174001",
              organizationId: "123e4567-e89b-12d3-a456-426614174002",
              createdAt: "2025-12-08T10:00:00.000Z",
              updatedAt: "2025-12-08T11:30:00.000Z"
            },
            message: "Workflow definition updated successfully"
          }
        },
        {
          status: 400,
          description: "Validation error",
          example: {
            error: "Validation failed",
            details: [
              {
                code: "invalid_type",
                message: "Expected object, received string",
                path: ["definition"]
              }
            ]
          }
        },
        {
          status: 404,
          description: "Workflow definition not found",
          example: {
            error: "Workflow definition not found"
          }
        }
      ]
    },
    DELETE: {
      summary: "Delete workflow definition",
      description: "Soft delete a workflow definition. Cannot be deleted if there are active workflow instances (RUNNING or WAITING status) using this definition.",
      tags: ["Workflows"],
      pathParams: z.object({
        id: z.string().uuid()
      }),
      responses: [
        {
          status: 200,
          description: "Workflow definition deleted successfully",
          example: {
            message: "Workflow definition deleted successfully"
          }
        },
        {
          status: 404,
          description: "Workflow definition not found",
          example: {
            error: "Workflow definition not found"
          }
        },
        {
          status: 409,
          description: "Cannot delete - active workflow instances exist",
          example: {
            error: "Cannot delete workflow definition with 3 active instance(s)"
          }
        }
      ]
    }
  }
};
export {
  DELETE,
  GET,
  PUT,
  metadata,
  openApi
};
//# sourceMappingURL=route.js.map
