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 { CustomerPipeline } from "../../data/entities.js";
import {
  pipelineCreateSchema,
  pipelineUpdateSchema,
  pipelineDeleteSchema
} from "../../data/validators.js";
import { withScopedPayload } from "../utils.js";
import { CrudHttpError, isCrudHttpError } from "@open-mercato/shared/lib/crud/errors";
import { resolveTranslations } from "@open-mercato/shared/lib/i18n/server";
import { serializeOperationMetadata } from "@open-mercato/shared/lib/commands/operationMetadata";
import {
  runCrudMutationGuardAfterSuccess,
  validateCrudMutationGuard
} from "@open-mercato/shared/lib/crud/mutation-guard";
import { createLogger } from "@open-mercato/shared/lib/logger";
const logger = createLogger("customers");
const PIPELINE_RESOURCE_KIND = "customers.pipeline";
const metadata = {
  GET: { requireAuth: true, requireFeatures: ["customers.pipelines.view"] },
  POST: { requireAuth: true, requireFeatures: ["customers.pipelines.manage"] },
  PUT: { requireAuth: true, requireFeatures: ["customers.pipelines.manage"] },
  DELETE: { requireAuth: true, requireFeatures: ["customers.pipelines.manage"] }
};
async function buildContext(req) {
  const container = await createRequestContainer();
  const auth = await getAuthFromRequest(req);
  const { translate } = await resolveTranslations();
  if (!auth) throw new CrudHttpError(401, { error: translate("customers.errors.unauthorized", "Unauthorized") });
  const scope = await resolveOrganizationScopeForRequest({ container, auth, request: req });
  const ctx = {
    container,
    auth,
    organizationScope: scope,
    selectedOrganizationId: scope?.selectedId ?? auth.orgId ?? null,
    organizationIds: scope?.filterIds ?? (auth.orgId ? [auth.orgId] : null),
    request: req
  };
  const organizationId = scope?.selectedId ?? auth.orgId ?? null;
  const tenantId = auth.tenantId ?? null;
  return { ctx, organizationId, tenantId, translate };
}
async function GET(req) {
  try {
    const { ctx, tenantId, translate } = await buildContext(req);
    if (!tenantId) {
      return NextResponse.json({ error: translate("customers.errors.context_required", "Organization and tenant context required") }, { status: 400 });
    }
    const orgFilter = resolveOrganizationScopeFilter(ctx.organizationScope, ctx.auth);
    const url = new URL(req.url);
    const isDefaultParam = url.searchParams.get("isDefault");
    const em = ctx.container.resolve("em");
    const where = { tenantId, ...orgFilter.where };
    if (isDefaultParam === "true") where.isDefault = true;
    if (isDefaultParam === "false") where.isDefault = false;
    const pipelines = await em.find(CustomerPipeline, where, { orderBy: { createdAt: "ASC" } });
    const items = pipelines.map((pipeline) => ({
      id: pipeline.id,
      name: pipeline.name,
      isDefault: pipeline.isDefault,
      organizationId: pipeline.organizationId,
      tenantId: pipeline.tenantId,
      createdAt: pipeline.createdAt,
      updatedAt: pipeline.updatedAt
    }));
    return NextResponse.json({ items, total: items.length });
  } catch (err) {
    if (isCrudHttpError(err)) {
      return NextResponse.json(err.body, { status: err.status });
    }
    logger.error("customers.pipelines GET failed", { err });
    return NextResponse.json({ error: "Failed to load pipelines" }, { status: 500 });
  }
}
async function POST(req) {
  try {
    const { ctx, organizationId, tenantId, translate } = await buildContext(req);
    if (!organizationId || !tenantId) {
      return NextResponse.json({ error: translate("customers.errors.context_required", "Organization and tenant context required") }, { status: 400 });
    }
    const body = await req.json().catch(() => ({}));
    const scoped = withScopedPayload(body, ctx, translate);
    const input = pipelineCreateSchema.parse(scoped);
    const guardResult = await validateCrudMutationGuard(ctx.container, {
      tenantId,
      organizationId,
      userId: ctx.auth.sub,
      resourceKind: PIPELINE_RESOURCE_KIND,
      resourceId: organizationId,
      operation: "create",
      requestMethod: req.method,
      requestHeaders: req.headers,
      mutationPayload: input
    });
    if (guardResult && !guardResult.ok) {
      return NextResponse.json(guardResult.body, { status: guardResult.status });
    }
    const commandBus = ctx.container.resolve("commandBus");
    const { result, logEntry } = await commandBus.execute(
      "customers.pipelines.create",
      { input, ctx }
    );
    if (guardResult?.ok && guardResult.shouldRunAfterSuccess) {
      await runCrudMutationGuardAfterSuccess(ctx.container, {
        tenantId,
        organizationId,
        userId: ctx.auth.sub,
        resourceKind: PIPELINE_RESOURCE_KIND,
        resourceId: result?.pipelineId ?? organizationId,
        operation: "create",
        requestMethod: req.method,
        requestHeaders: req.headers,
        metadata: guardResult.metadata ?? null
      });
    }
    const response = NextResponse.json({ id: result?.pipelineId ?? null }, { status: 201 });
    if (logEntry?.undoToken && logEntry?.id && logEntry?.commandId) {
      response.headers.set(
        "x-om-operation",
        serializeOperationMetadata({
          id: logEntry.id,
          undoToken: logEntry.undoToken,
          commandId: logEntry.commandId,
          actionLabel: logEntry.actionLabel ?? null,
          resourceKind: logEntry.resourceKind ?? "customers.pipeline",
          resourceId: logEntry.resourceId ?? result?.pipelineId ?? null,
          executedAt: logEntry.createdAt instanceof Date ? logEntry.createdAt.toISOString() : void 0
        })
      );
    }
    return response;
  } catch (err) {
    if (isCrudHttpError(err)) {
      return NextResponse.json(err.body, { status: err.status });
    }
    logger.error("customers.pipelines POST failed", { err });
    return NextResponse.json({ error: "Failed to create pipeline" }, { status: 400 });
  }
}
async function PUT(req) {
  try {
    const { ctx, organizationId, tenantId, translate } = await buildContext(req);
    if (!organizationId || !tenantId) {
      return NextResponse.json({ error: translate("customers.errors.context_required", "Organization and tenant context required") }, { status: 400 });
    }
    const body = await req.json().catch(() => ({}));
    const scoped = withScopedPayload(body, ctx, translate);
    const input = pipelineUpdateSchema.parse(scoped);
    const guardResult = await validateCrudMutationGuard(ctx.container, {
      tenantId,
      organizationId,
      userId: ctx.auth.sub,
      resourceKind: PIPELINE_RESOURCE_KIND,
      resourceId: input.id,
      operation: "update",
      requestMethod: req.method,
      requestHeaders: req.headers,
      mutationPayload: input
    });
    if (guardResult && !guardResult.ok) {
      return NextResponse.json(guardResult.body, { status: guardResult.status });
    }
    const commandBus = ctx.container.resolve("commandBus");
    const { logEntry } = await commandBus.execute(
      "customers.pipelines.update",
      { input, ctx }
    );
    if (guardResult?.ok && guardResult.shouldRunAfterSuccess) {
      await runCrudMutationGuardAfterSuccess(ctx.container, {
        tenantId,
        organizationId,
        userId: ctx.auth.sub,
        resourceKind: PIPELINE_RESOURCE_KIND,
        resourceId: input.id,
        operation: "update",
        requestMethod: req.method,
        requestHeaders: req.headers,
        metadata: guardResult.metadata ?? null
      });
    }
    const response = NextResponse.json({ ok: true });
    if (logEntry?.undoToken && logEntry?.id && logEntry?.commandId) {
      response.headers.set(
        "x-om-operation",
        serializeOperationMetadata({
          id: logEntry.id,
          undoToken: logEntry.undoToken,
          commandId: logEntry.commandId,
          actionLabel: logEntry.actionLabel ?? null,
          resourceKind: logEntry.resourceKind ?? "customers.pipeline",
          resourceId: logEntry.resourceId ?? null,
          executedAt: logEntry.createdAt instanceof Date ? logEntry.createdAt.toISOString() : void 0
        })
      );
    }
    return response;
  } catch (err) {
    if (isCrudHttpError(err)) {
      return NextResponse.json(err.body, { status: err.status });
    }
    logger.error("customers.pipelines PUT failed", { err });
    return NextResponse.json({ error: "Failed to update pipeline" }, { status: 400 });
  }
}
async function DELETE(req) {
  try {
    const { ctx, organizationId, tenantId, translate } = await buildContext(req);
    if (!organizationId || !tenantId) {
      return NextResponse.json({ error: translate("customers.errors.context_required", "Organization and tenant context required") }, { status: 400 });
    }
    const body = await req.json().catch(() => ({}));
    const scoped = withScopedPayload(body, ctx, translate);
    const input = pipelineDeleteSchema.parse(scoped);
    const guardResult = await validateCrudMutationGuard(ctx.container, {
      tenantId,
      organizationId,
      userId: ctx.auth.sub,
      resourceKind: PIPELINE_RESOURCE_KIND,
      resourceId: input.id,
      operation: "delete",
      requestMethod: req.method,
      requestHeaders: req.headers,
      mutationPayload: input
    });
    if (guardResult && !guardResult.ok) {
      return NextResponse.json(guardResult.body, { status: guardResult.status });
    }
    const commandBus = ctx.container.resolve("commandBus");
    await commandBus.execute(
      "customers.pipelines.delete",
      { input, ctx }
    );
    if (guardResult?.ok && guardResult.shouldRunAfterSuccess) {
      await runCrudMutationGuardAfterSuccess(ctx.container, {
        tenantId,
        organizationId,
        userId: ctx.auth.sub,
        resourceKind: PIPELINE_RESOURCE_KIND,
        resourceId: input.id,
        operation: "delete",
        requestMethod: req.method,
        requestHeaders: req.headers,
        metadata: guardResult.metadata ?? null
      });
    }
    return NextResponse.json({ ok: true });
  } catch (err) {
    if (isCrudHttpError(err)) {
      return NextResponse.json(err.body, { status: err.status });
    }
    logger.error("customers.pipelines DELETE failed", { err });
    return NextResponse.json({ error: "Failed to delete pipeline" }, { status: 400 });
  }
}
const pipelineItemSchema = z.object({
  id: z.string().uuid(),
  name: z.string(),
  isDefault: z.boolean(),
  organizationId: z.string().uuid(),
  tenantId: z.string().uuid(),
  createdAt: z.date(),
  updatedAt: z.date()
});
const pipelineListResponseSchema = z.object({
  items: z.array(pipelineItemSchema),
  total: z.number()
});
const pipelineCreateResponseSchema = z.object({
  id: z.string().uuid().nullable()
});
const pipelineOkResponseSchema = z.object({
  ok: z.boolean()
});
const pipelineErrorSchema = z.object({
  error: z.string()
});
const openApi = {
  tag: "Customers",
  summary: "Manage customer pipelines",
  methods: {
    GET: {
      summary: "List pipelines",
      description: "Returns a list of pipelines scoped to the authenticated organization.",
      query: z.object({ isDefault: z.string().optional() }),
      responses: [
        { status: 200, description: "Pipeline list", schema: pipelineListResponseSchema }
      ],
      errors: [
        { status: 401, description: "Unauthorized", schema: pipelineErrorSchema },
        { status: 400, description: "Invalid request", schema: pipelineErrorSchema }
      ]
    },
    POST: {
      summary: "Create pipeline",
      description: "Creates a new pipeline within the authenticated organization.",
      requestBody: { contentType: "application/json", schema: pipelineCreateSchema },
      responses: [
        { status: 201, description: "Pipeline created", schema: pipelineCreateResponseSchema }
      ],
      errors: [
        { status: 400, description: "Validation failed", schema: pipelineErrorSchema },
        { status: 401, description: "Unauthorized", schema: pipelineErrorSchema }
      ]
    },
    PUT: {
      summary: "Update pipeline",
      description: "Updates an existing pipeline.",
      requestBody: { contentType: "application/json", schema: pipelineUpdateSchema },
      responses: [
        { status: 200, description: "Pipeline updated", schema: pipelineOkResponseSchema }
      ],
      errors: [
        { status: 400, description: "Validation failed", schema: pipelineErrorSchema },
        { status: 404, description: "Pipeline not found", schema: pipelineErrorSchema }
      ]
    },
    DELETE: {
      summary: "Delete pipeline",
      description: "Deletes a pipeline. Returns 409 if active deals exist.",
      requestBody: { contentType: "application/json", schema: pipelineDeleteSchema },
      responses: [
        { status: 200, description: "Pipeline deleted", schema: pipelineOkResponseSchema }
      ],
      errors: [
        { status: 409, description: "Pipeline has active deals", schema: pipelineErrorSchema },
        { status: 404, description: "Pipeline not found", schema: pipelineErrorSchema }
      ]
    }
  }
};
export {
  DELETE,
  GET,
  POST,
  PUT,
  metadata,
  openApi
};
//# sourceMappingURL=route.js.map
