import { z } from "zod";
import { createCrudFormError } from "@open-mercato/ui/backend/utils/serverErrors";
import { findOneWithDecryption } from "@open-mercato/shared/lib/encryption/find";
import { CommunicationChannel } from "../data/entities.js";
import { getChannelAdapterRegistry } from "../lib/adapter-registry-singleton.js";
import { refreshCredentialsIfNeeded } from "../lib/credential-refresh.js";
import { emitCommunicationChannelsEvent } from "../events.js";
const pushRegisterSchema = z.object({
  channelId: z.string().uuid()
});
async function pushRegister(params) {
  const input = pushRegisterSchema.parse(params.input);
  const { container, scope } = params;
  const em = container.resolve("em").fork();
  const dscope = { tenantId: scope.tenantId, organizationId: scope.organizationId };
  const channel = await findOneWithDecryption(
    em,
    CommunicationChannel,
    {
      id: input.channelId,
      tenantId: scope.tenantId,
      organizationId: scope.organizationId,
      deletedAt: null
    },
    void 0,
    dscope
  );
  if (!channel) {
    throw createCrudFormError(
      "Channel not found",
      { channelId: "Channel not found" },
      { status: 404 }
    );
  }
  if (!channel.isActive || channel.status !== "connected") {
    throw createCrudFormError(
      "Channel must be connected to register push",
      { channelId: `Channel status is ${channel.status}` },
      { status: 400 }
    );
  }
  const adapter = getChannelAdapterRegistry().get(channel.providerKey);
  if (!adapter) {
    throw createCrudFormError(
      "Channel provider is not available",
      { channelId: `No adapter for provider "${channel.providerKey}"` },
      { status: 400 }
    );
  }
  if (typeof adapter.registerPush !== "function") {
    throw createCrudFormError(
      "Push delivery is not supported on this provider",
      { channelId: `Provider "${channel.providerKey}" does not implement registerPush` },
      { status: 409 }
    );
  }
  let credentialsService = null;
  try {
    credentialsService = container.resolve("integrationCredentialsService");
  } catch {
    credentialsService = null;
  }
  const credentialsScope = {
    tenantId: scope.tenantId,
    organizationId: scope.organizationId,
    userId: channel.userId ?? null
  };
  let credentials = {};
  if (channel.credentialsRef && credentialsService) {
    try {
      credentials = await credentialsService.resolve(`channel_${channel.providerKey}`, credentialsScope) ?? {};
    } catch {
      credentials = {};
    }
  }
  const refreshed = await refreshCredentialsIfNeeded(
    { adapter, channelId: channel.id, credentials, scope: credentialsScope },
    { credentialsService }
  );
  credentials = refreshed.credentials;
  let providerConfig;
  let notificationUrl = "";
  if (channel.providerKey === "gmail") {
    const topic = process.env.OM_GMAIL_PUBSUB_TOPIC;
    providerConfig = { pubsubTopic: topic ?? "" };
    notificationUrl = "";
  }
  let registration;
  try {
    registration = await adapter.registerPush({
      channelId: channel.id,
      credentials,
      scope: { tenantId: scope.tenantId, organizationId: scope.organizationId },
      notificationUrl,
      providerConfig
    });
  } catch (err) {
    const message = err instanceof Error ? err.message : "registerPush threw";
    throw createCrudFormError(
      "Push registration failed",
      { channelId: message.slice(0, 500) },
      { status: 502 }
    );
  }
  const previousState = channel.channelState ?? {};
  channel.channelState = { ...previousState, ...registration.channelStatePatch };
  if (registration.status === "active" && typeof registration.recommendedPollIntervalSeconds === "number") {
    channel.pollIntervalSeconds = registration.recommendedPollIntervalSeconds;
  }
  await em.flush();
  if (registration.status === "active") {
    await emitCommunicationChannelsEvent(
      "communication_channels.push.registered",
      {
        channelId: channel.id,
        providerKey: channel.providerKey,
        tenantId: scope.tenantId,
        organizationId: scope.organizationId
      },
      { persistent: true }
    );
  } else {
    await emitCommunicationChannelsEvent(
      "communication_channels.push.failed",
      {
        channelId: channel.id,
        providerKey: channel.providerKey,
        tenantId: scope.tenantId,
        organizationId: scope.organizationId,
        error: registration.error ?? null
      },
      { persistent: true }
    );
  }
  return {
    channelId: channel.id,
    pushStatus: registration.status,
    channelState: channel.channelState ?? {},
    error: registration.error
  };
}
export {
  pushRegister,
  pushRegisterSchema
};
//# sourceMappingURL=push-register.js.map
