import { logger } from "../logger.js";
import { getAgentState } from "../agent/state.js";
function getOwnerNotifyContext(config) {
    try {
        const state = getAgentState();
        return {
            config,
            ownerConfig: state.ownerConfig,
            channelManager: state.channelManager,
        };
    }
    catch {
        return null;
    }
}
/**
 * Try to reach the owner over a single channel tier.
 *
 * A "tier" is one of telegram / discord / gmail. Each tier may have zero,
 * one, or many concrete targets:
 *   - telegram → single owner chat
 *   - discord  → every allowed owner channel (we send to all, for redundancy
 *                within the tier — if at least one delivers, the tier is
 *                considered successful and we do not fall back further)
 *   - gmail    → single owner email
 *
 * Returns true iff at least one target in the tier was successfully sent
 * to. Per-target failures are logged but never thrown — the whole point
 * of this helper is best-effort delivery.
 */
async function tryChannelTier(tier, targets, message, channelManager, logKind) {
    let anyDelivered = false;
    for (const target of targets) {
        try {
            await channelManager.sendMessage(tier, target, message);
            anyDelivered = true;
        }
        catch (err) {
            logger.warn(`Failed to send ${logKind} via ${tier} (target ${target}): ${err instanceof Error ? err.message : String(err)}`);
        }
    }
    return anyDelivered;
}
/**
 * Reach the owner via a fallback chain: Telegram → Discord → Gmail.
 *
 * We stop at the first tier that successfully delivers to at least one
 * target. A tier that's unconfigured (empty target list) is skipped
 * without consuming a fallback attempt, so a user with only Discord
 * configured still gets a first-try delivery via Discord.
 *
 * Returns true iff some tier delivered. The caller decides what to do
 * when nothing was delivered (log-and-drop vs. surface to the user).
 */
async function notifyOwnerViaFallbackChain(ctx, message, logKind) {
    const { config, ownerConfig, channelManager } = ctx;
    const telegramTargets = config.channels.telegram?.enabled && ownerConfig.telegramChatId
        ? [String(ownerConfig.telegramChatId)]
        : [];
    if (telegramTargets.length > 0) {
        if (await tryChannelTier("telegram", telegramTargets, message, channelManager, logKind)) {
            return true;
        }
    }
    const discordTargets = config.channels.discord?.enabled && ownerConfig.allowedDiscordChannelIds.length > 0
        ? ownerConfig.allowedDiscordChannelIds
        : [];
    if (discordTargets.length > 0) {
        if (await tryChannelTier("discord", discordTargets, message, channelManager, logKind)) {
            return true;
        }
    }
    const gmailTargets = ownerConfig.ownerEmail ? [ownerConfig.ownerEmail] : [];
    if (gmailTargets.length > 0) {
        if (await tryChannelTier("gmail", gmailTargets, message, channelManager, logKind)) {
            return true;
        }
    }
    return false;
}
/**
 * Notify the owner about the tunnel status via the fallback chain
 * (Telegram → Discord → Gmail). Handles both success (URL available) and
 * failure cases.
 *
 * Must be called after startAgentLoop() has initialized the agent state
 * (the tunnel takes ~15-30s to resolve, so this is naturally the case).
 */
// TODO(obs-review): `notifyOwnerTunnelUrl` is no longer called anywhere —
// the OBS server stopped sending tunnel-up/restart notifications when the
// public surface was locked down. Delete this export (or repurpose it for
// a future, owner-initiated "tunnel changed" notification) instead of
// leaving it as dead code.
export async function notifyOwnerTunnelUrl(tunnelUrl, config) {
    const ctx = getOwnerNotifyContext(config);
    if (!ctx) {
        logger.warn("Cannot notify tunnel URL — agent state not yet initialized");
        return;
    }
    const message = tunnelUrl
        ? `I'm up and running and my console is now publicly accessible:\n${tunnelUrl}/console`
        : "Tunnel failed to start. Use /tunnel to retry, or /restart to restart the agent.";
    const sent = await notifyOwnerViaFallbackChain(ctx, message, "tunnel notification");
    if (!sent) {
        if (tunnelUrl) {
            logger.system(`Tunnel URL ready (no channels configured to notify): ${tunnelUrl}`);
        }
        return;
    }
}
/**
 * Notify the owner with a plain message via the fallback chain
 * (Telegram → Discord → Gmail).
 *
 * This is a general-purpose helper for one-shot notifications (startup
 * display-size failure, LLM-stuck retry alerts, etc.). It requires
 * `startAgentLoop()` to have initialized the agent state — callers
 * scheduling from pre-loop code should defer this via the `onReady`
 * callback.
 */
export async function notifyOwner(message, config) {
    const ctx = getOwnerNotifyContext(config);
    if (!ctx) {
        logger.warn(`Cannot notify owner (agent state not yet initialized): ${message}`);
        return;
    }
    const sent = await notifyOwnerViaFallbackChain(ctx, message, "owner notification");
    if (!sent) {
        logger.warn(`Owner notification dropped (no channels configured): ${message}`);
        return;
    }
}
//# sourceMappingURL=notify.js.map