import { z } from "zod";
import { registerCommand } from "@open-mercato/shared/lib/commands";
import { extractUndoPayload as extractSharedUndoPayload } from "@open-mercato/shared/lib/commands/undo";
import { findOneWithDecryption } from "@open-mercato/shared/lib/encryption/find";
import { CommunicationChannel } from "../data/entities.js";
import { pushUnregister } from "./push-unregister.js";
import { emitCommunicationChannelsEvent } from "../events.js";
import { createLogger } from "@open-mercato/shared/lib/logger";
const logger = createLogger("communication_channels").child({ component: "delete-channel" });
const deleteChannelSchema = z.object({
  channelId: z.string().uuid(),
  userId: z.string().uuid(),
  scope: z.object({
    tenantId: z.string().uuid(),
    organizationId: z.string().uuid().nullable()
  })
});
const COMMUNICATION_CHANNELS_DELETE_CHANNEL_COMMAND_ID = "communication_channels.channel.delete";
const deleteChannelCommand = {
  id: COMMUNICATION_CHANNELS_DELETE_CHANNEL_COMMAND_ID,
  // Explicitly undoable (the bus also infers this from `undo` below, but
  // declaring it keeps undoability from silently dropping under a refactor).
  isUndoable: true,
  async execute(rawInput, ctx) {
    const input = deleteChannelSchema.parse(rawInput);
    const em = ctx.container.resolve("em").fork();
    const dscope = {
      tenantId: input.scope.tenantId,
      organizationId: input.scope.organizationId ?? null
    };
    const channel = await findOneWithDecryption(
      em,
      CommunicationChannel,
      {
        id: input.channelId,
        tenantId: input.scope.tenantId,
        organizationId: input.scope.organizationId ?? null,
        deletedAt: null
      },
      void 0,
      dscope
    );
    if (!channel) {
      return { status: "noop", reason: "channel not found" };
    }
    if (channel.userId !== input.userId) {
      return { status: "not_owner", reason: "channel is not owned by the current user" };
    }
    if (input.scope.organizationId) {
      try {
        await pushUnregister({
          container: ctx.container,
          scope: {
            tenantId: input.scope.tenantId,
            organizationId: input.scope.organizationId,
            userId: input.userId
          },
          input: { channelId: channel.id }
        });
      } catch (err) {
        logger.warn("push unregister failed for channel", { channelId: channel.id, err });
      }
    }
    channel.deletedAt = /* @__PURE__ */ new Date();
    channel.isPrimary = false;
    await em.flush();
    await emitCommunicationChannelsEvent(
      "communication_channels.channel.deleted",
      {
        channelId: channel.id,
        userId: input.userId,
        providerKey: channel.providerKey,
        channelType: channel.channelType,
        tenantId: input.scope.tenantId,
        organizationId: input.scope.organizationId ?? null
      },
      { persistent: true }
    );
    return {
      status: "deleted",
      channelId: channel.id,
      undo: { channelId: channel.id, tenantId: channel.tenantId }
    };
  },
  // Persist the undo snapshot into the action log. Without this, the command bus
  // mints an undo token (so the UI offers "Undo") but the snapshot returned from
  // execute() is never stored, and undo() (which clears deleted_at) would no-op.
  async buildLog({ input, result }) {
    if (result.status !== "deleted") return null;
    return {
      resourceKind: "communication_channels.channel",
      resourceId: result.channelId,
      tenantId: result.undo.tenantId ?? input.scope.tenantId,
      organizationId: input.scope.organizationId ?? null,
      payload: { undo: result.undo }
    };
  },
  async undo({ ctx, logEntry }) {
    const snapshot = extractSnapshotFromLog(logEntry);
    if (!snapshot || !snapshot.tenantId) return;
    const em = ctx.container.resolve("em").fork();
    const channel = await findOneWithDecryption(
      em,
      CommunicationChannel,
      { id: snapshot.channelId, tenantId: snapshot.tenantId },
      void 0,
      { tenantId: snapshot.tenantId, organizationId: null }
    );
    if (!channel) return;
    channel.deletedAt = null;
    await em.flush();
  }
};
function extractUndoPayload(value) {
  if (!value || typeof value !== "object") return null;
  const candidate = value.undo ?? value;
  if (!candidate || typeof candidate !== "object") return null;
  const obj = candidate;
  if (typeof obj.channelId !== "string") return null;
  return {
    channelId: obj.channelId,
    tenantId: typeof obj.tenantId === "string" ? obj.tenantId : void 0
  };
}
function extractSnapshotFromLog(logEntry) {
  const undo = extractSharedUndoPayload(logEntry ?? null);
  if (undo) return extractUndoPayload(undo);
  return extractUndoPayload(logEntry);
}
registerCommand(deleteChannelCommand);
var delete_channel_default = deleteChannelCommand;
export {
  COMMUNICATION_CHANNELS_DELETE_CHANNEL_COMMAND_ID,
  delete_channel_default as default,
  extractUndoPayload
};
//# sourceMappingURL=delete-channel.js.map
