import fs from "node:fs";
import path from "node:path";
import { logger } from "../logger.js";
import { getPackageRoot } from "../utils/version-check.js";
const AVATARS_DIR = path.resolve(getPackageRoot(), "assets/avatars");
export const AVATAR_OPTIONS = [
    { name: "visionclaw", label: "VisionClaw", file: "visionclaw.jpg" },
    { name: "robot", label: "Friendly Robot", file: "robot.jpg" },
    { name: "owl", label: "Wise Owl", file: "owl.jpg" },
    { name: "orb", label: "Crystal Orb", file: "orb.jpg" },
    { name: "fox", label: "Clever Fox", file: "fox.jpg" },
    { name: "cat", label: "Curious Cat", file: "cat.jpg" },
    { name: "abstract", label: "Abstract Geometry", file: "abstract.jpg" },
];
async function callSetProfilePhoto(botToken, photoBuffer, maxRetries = 2) {
    for (let attempt = 0; attempt <= maxRetries; attempt++) {
        const file = new File([photoBuffer], "photo.jpg", { type: "image/jpeg" });
        const form = new FormData();
        form.append("photo", JSON.stringify({ type: "static", photo: "attach://photo_file" }));
        form.append("photo_file", file);
        const res = await fetch(`https://api.telegram.org/bot${botToken}/setMyProfilePhoto`, {
            method: "POST",
            body: form,
            signal: AbortSignal.timeout(30_000),
        });
        const data = (await res.json());
        if (data.ok)
            return data;
        const desc = data.description ?? "";
        const isRetryable = /timeout|gateway|retry|temporarily|too many/i.test(desc);
        if (!isRetryable || attempt === maxRetries)
            return data;
        logger.warn(`setMyProfilePhoto attempt ${attempt + 1} failed (${desc}), retrying…`);
        await new Promise((r) => setTimeout(r, 3000 * (attempt + 1)));
    }
    return { ok: false, description: "max retries exceeded" };
}
function resolvePhotoSourcePath(source) {
    const trimmed = source.trim();
    if (trimmed === "~") {
        return process.env.HOME ?? trimmed;
    }
    if (trimmed.startsWith("~/")) {
        return path.join(process.env.HOME ?? "", trimmed.slice(2));
    }
    return trimmed;
}
export async function setProfilePhotoAsync(botToken, source) {
    let photoPath;
    let tempFile;
    try {
        const optionNum = parseInt(source, 10);
        if (!isNaN(optionNum) && optionNum >= 1 && optionNum <= AVATAR_OPTIONS.length) {
            const opt = AVATAR_OPTIONS[optionNum - 1];
            photoPath = path.join(AVATARS_DIR, opt.file);
            if (!fs.existsSync(photoPath)) {
                logger.warn(`Avatar file not found at ${photoPath}`);
                return false;
            }
        }
        else if (source.startsWith("https://")) {
            const res = await fetch(source);
            if (!res.ok) {
                logger.warn(`Failed to download user photo: HTTP ${res.status}`);
                return false;
            }
            const buffer = Buffer.from(await res.arrayBuffer());
            tempFile = path.join(AVATARS_DIR, `_temp_upload_${Date.now()}.jpg`);
            fs.writeFileSync(tempFile, buffer);
            photoPath = tempFile;
        }
        else {
            const localPath = resolvePhotoSourcePath(source);
            if (fs.existsSync(localPath)) {
                photoPath = localPath;
            }
            else {
                logger.warn(`Invalid profile photo source: ${source}`);
                return false;
            }
        }
        const fileBuffer = fs.readFileSync(photoPath);
        logger.debug(`Setting bot profile photo from ${photoPath} (${fileBuffer.length} bytes)`);
        const data = await callSetProfilePhoto(botToken, fileBuffer);
        if (data.ok) {
            logger.system("Telegram bot profile photo updated");
            return true;
        }
        logger.warn(`setMyProfilePhoto failed: ${data.description ?? "unknown"}`);
        return false;
    }
    catch (err) {
        logger.warn(`setMyProfilePhoto error: ${err instanceof Error ? err.message : String(err)}`);
        return false;
    }
    finally {
        if (tempFile && fs.existsSync(tempFile)) {
            fs.unlinkSync(tempFile);
        }
    }
}
/**
 * Read the bot's display name via Bot API `getMyName` (Telegram Bot API 7+).
 * Returns null if the method is unavailable or the request fails.
 */
async function getBotDisplayName(botToken) {
    try {
        const res = await fetch(`https://api.telegram.org/bot${botToken}/getMyName`, { method: "GET", signal: AbortSignal.timeout(15_000) });
        const data = (await res.json());
        if (data.ok && typeof data.result?.name === "string") {
            return data.result.name;
        }
    }
    catch {
        // ignore — caller will try setMyName
    }
    return null;
}
/**
 * Whitelist of bot commands to register in the Telegram command menu.
 * Only these commands will appear when users type "/" in the chat.
 */
// Note: "hidden" commands (e.g. /rdp, /upgrade_beta, /upgrade_dev) are intentionally
// NOT listed here so they won't appear in the Telegram "/" autocomplete menu.
// They remain fully functional when typed manually and are documented in /help.
const BOT_COMMANDS = [
    { command: "stop", description: "Stop the current agent task" },
    { command: "restart", description: "Restart the agent" },
    { command: "screenshot", description: "Take a screenshot of the desktop" },
    { command: "status", description: "Show agent status and service health" },
    { command: "tasks", description: "Show current task, todos, and recent steps" },
    { command: "subscribe", description: "Show subscription status and manage billing" },
    { command: "refresh", description: "Compact the agent's context to clear corruption" },
    { command: "realtime", description: "Open the realtime voice Mini App" },
    { command: "settings", description: "Change language or timezone" },
];
/**
 * Sync registered Telegram bot commands on startup.
 * Compares current commands with the desired whitelist and updates if they differ.
 */
export async function syncBotCommands(botToken) {
    try {
        const getRes = await fetch(`https://api.telegram.org/bot${botToken}/getMyCommands`, { method: "GET", signal: AbortSignal.timeout(15_000) });
        const getData = (await getRes.json());
        if (getData.ok && getData.result) {
            const current = getData.result;
            const isMatch = current.length === BOT_COMMANDS.length &&
                BOT_COMMANDS.every((cmd, i) => current[i].command === cmd.command && current[i].description === cmd.description);
            if (isMatch) {
                logger.debug("Telegram bot commands already up to date");
                return true;
            }
        }
        const setRes = await fetch(`https://api.telegram.org/bot${botToken}/setMyCommands`, {
            method: "POST",
            headers: { "Content-Type": "application/json" },
            body: JSON.stringify({ commands: BOT_COMMANDS }),
            signal: AbortSignal.timeout(15_000),
        });
        const setData = (await setRes.json());
        if (setData.ok) {
            logger.system(`Telegram bot commands registered: ${BOT_COMMANDS.map((c) => `/${c.command}`).join(", ")}`);
            return true;
        }
        logger.warn(`setMyCommands failed: ${setData.description ?? "unknown"}`);
        return false;
    }
    catch (err) {
        logger.warn(`syncBotCommands error: ${err instanceof Error ? err.message : String(err)}`);
        return false;
    }
}
export async function updateBotName(botToken, name, maxRetries = 2) {
    const desired = name.trim();
    if (!desired) {
        logger.warn("updateBotName: empty name after trim");
        return false;
    }
    const before = await getBotDisplayName(botToken);
    if (before !== null && before === desired) {
        logger.system(`Telegram bot name already "${desired}" — skipping setMyName`);
        return true;
    }
    for (let attempt = 0; attempt <= maxRetries; attempt++) {
        try {
            const res = await fetch(`https://api.telegram.org/bot${botToken}/setMyName`, {
                method: "POST",
                headers: { "Content-Type": "application/json" },
                body: JSON.stringify({ name: desired }),
                signal: AbortSignal.timeout(30_000),
            });
            const data = (await res.json());
            if (data.ok) {
                logger.system(`Telegram bot name updated to "${desired}"`);
                return true;
            }
            const desc = data.description ?? "";
            // Rate limits often mean the name is already correct from a prior run — verify before retrying.
            const verified = await getBotDisplayName(botToken);
            if (verified !== null && verified === desired) {
                logger.system(`Telegram bot name already "${desired}" (setMyName returned error: ${desc || "unknown"})`);
                return true;
            }
            // Do not retry "Too many requests" — it makes rate limits worse; only transient errors.
            const isRetryable = /timeout|gateway|retry|temporarily/i.test(desc) && !/too many/i.test(desc);
            if (!isRetryable || attempt === maxRetries) {
                logger.warn(`Failed to update Telegram bot name: ${desc || "unknown error"}`);
                return false;
            }
            logger.warn(`setMyName attempt ${attempt + 1} failed (${desc}), retrying…`);
            await new Promise((r) => setTimeout(r, 3000 * (attempt + 1)));
        }
        catch (err) {
            const msg = err instanceof Error ? err.message : String(err);
            const verified = await getBotDisplayName(botToken);
            if (verified !== null && verified === desired) {
                logger.system(`Telegram bot name already "${desired}" (after exception: ${msg})`);
                return true;
            }
            if (attempt === maxRetries) {
                logger.warn(`Failed to update Telegram bot name: ${msg}`);
                return false;
            }
            logger.warn(`setMyName attempt ${attempt + 1} failed (${msg}), retrying…`);
            await new Promise((r) => setTimeout(r, 3000 * (attempt + 1)));
        }
    }
    return false;
}
//# sourceMappingURL=bot-profile.js.map