import { z } from "zod";
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 { POLLING_ONLY_DEFAULT_INTERVAL_SECONDS } from "../lib/connect-channel.js";
import { emitCommunicationChannelsEvent } from "../events.js";
import { createLogger } from "@open-mercato/shared/lib/logger";
const logger = createLogger("communication_channels").child({ component: "push-unregister" });
const pushUnregisterSchema = z.object({
  channelId: z.string().uuid()
});
async function pushUnregister(params) {
  const input = pushUnregisterSchema.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
    },
    void 0,
    dscope
  );
  if (!channel) {
    return { channelId: input.channelId, status: "noop" };
  }
  const adapter = getChannelAdapterRegistry().get(channel.providerKey);
  if (!adapter || typeof adapter.unregisterPush !== "function") {
    return { channelId: channel.id, status: "noop" };
  }
  const channelState = channel.channelState ?? {};
  const pushStatus = typeof channelState.pushStatus === "string" ? channelState.pushStatus : null;
  if (!pushStatus || pushStatus === "inactive") {
    return { channelId: channel.id, status: "noop" };
  }
  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 = {};
    }
  }
  try {
    const refreshed = await refreshCredentialsIfNeeded(
      { adapter, channelId: channel.id, credentials, scope: credentialsScope },
      { credentialsService }
    );
    credentials = refreshed.credentials;
  } catch {
  }
  try {
    await adapter.unregisterPush({
      channelId: channel.id,
      credentials,
      scope: { tenantId: scope.tenantId, organizationId: scope.organizationId },
      channelState
    });
  } catch (err) {
    const message = err instanceof Error ? err.message : String(err);
    logger.warn("adapter.unregisterPush failed for channel", { channelId: channel.id, reason: message });
    return {
      channelId: channel.id,
      status: "failed",
      error: { code: "adapter_unregister_failed", message: message.slice(0, 500) }
    };
  }
  channel.channelState = {
    ...channelState,
    pushStatus: "inactive",
    watchExpirationMs: null
  };
  channel.pollIntervalSeconds = POLLING_ONLY_DEFAULT_INTERVAL_SECONDS;
  await em.flush();
  await emitCommunicationChannelsEvent(
    "communication_channels.push.deactivated",
    {
      channelId: channel.id,
      providerKey: channel.providerKey,
      tenantId: scope.tenantId,
      organizationId: scope.organizationId,
      reason: "unregistered"
    },
    { persistent: true }
  );
  return { channelId: channel.id, status: "unregistered" };
}
export {
  pushUnregister,
  pushUnregisterSchema
};
//# sourceMappingURL=push-unregister.js.map
