"use strict";
var __importDefault = (this && this.__importDefault) || function (mod) {
    return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.runSetupWizard = runSetupWizard;
const prompts_1 = require("@clack/prompts");
const search_1 = __importDefault(require("@inquirer/search"));
const picocolors_1 = __importDefault(require("picocolors"));
const fs_1 = __importDefault(require("fs"));
const path_1 = __importDefault(require("path"));
const paths_1 = require("../config/paths");
const parser_1 = require("../config/parser");
const crypto_1 = __importDefault(require("crypto"));
function encryptKey(privateKey, password) {
    const salt = crypto_1.default.randomBytes(16);
    const key = crypto_1.default.pbkdf2Sync(password, salt, 100000, 32, 'sha256');
    const iv = crypto_1.default.randomBytes(12);
    const cipher = crypto_1.default.createCipheriv('aes-256-gcm', key, iv);
    let encrypted = cipher.update(privateKey, 'utf8', 'hex');
    encrypted += cipher.final('hex');
    const authTag = cipher.getAuthTag().toString('hex');
    return {
        salt: salt.toString('hex'),
        iv: iv.toString('hex'),
        authTag,
        encryptedData: encrypted
    };
}
const accounts_1 = require("viem/accounts");
async function runSetupWizard() {
    console.clear();
    const logo = `
███╗   ██╗██╗   ██╗██╗  ██╗ ██████╗ ██████╗  █████╗ 
████╗  ██║╚██╗ ██╔╝╚██╗██╔╝██╔═══██╗██╔══██╗██╔══██╗
██╔██╗ ██║ ╚████╔╝  ╚███╔╝ ██║   ██║██████╔╝███████║
██║╚██╗██║  ╚██╔╝   ██╔██╗ ██║   ██║██╔══██╗██╔══██║
██║ ╚████║   ██║   ██╔╝ ██╗╚██████╔╝██║  ██║██║  ██║
╚═╝  ╚═══╝   ╚═╝   ╚═╝  ╚═╝ ╚═════╝ ╚═╝  ╚═╝╚═╝  ╚═╝
  `;
    console.log(picocolors_1.default.cyan(logo));
    (0, prompts_1.intro)(picocolors_1.default.inverse(' Nyxora CLI Setup '));
    const appDir = (0, paths_1.getAppDir)();
    const config = (0, parser_1.loadConfig)();
    const disclaimer = `Nyxora is a Web3 Assistant that operates with full access under your control.

Critical Precautions:
- Your Private Key is the lifeblood of your assets. NEVER copy or share the keystore.json file.
- Any instructions you provide via Telegram or Dashboard can trigger on-chain transactions.
- It is recommended to use a smart AI model for maximum accuracy.

By using Nyxora, you retain full control over your own keys.`;
    (0, prompts_1.note)(disclaimer, 'Security Warning');
    const understand = await (0, prompts_1.confirm)({
        message: 'I understand that Private Key security is my responsibility. Continue?',
        initialValue: true,
    });
    if ((0, prompts_1.isCancel)(understand) || !understand) {
        (0, prompts_1.cancel)('Setup cancelled.');
        return process.exit(0);
    }
    const existingConfigNote = `Workspace: ${appDir}
Current Model: ${config.llm.model}
Provider: ${config.llm.provider}`;
    (0, prompts_1.note)(existingConfigNote, 'Configuration Detected');
    const action = await (0, prompts_1.select)({
        message: 'What would you like to do?',
        options: [
            { value: 'keep', label: 'Keep current values' },
            { value: 'update', label: 'Review and update settings' },
        ],
    });
    if ((0, prompts_1.isCancel)(action)) {
        (0, prompts_1.cancel)('Setup cancelled.');
        return process.exit(0);
    }
    if (action === 'keep') {
        (0, prompts_1.outro)(picocolors_1.default.green('Done! Configuration unchanged. Starting Nyxora...'));
        return;
    }
    // --- WIZARD FORM ---
    // 1. LLM Provider
    const provider = await (0, prompts_1.select)({
        message: 'Select AI Engine (Provider):',
        initialValue: config.llm.provider,
        options: [
            { value: 'openai', label: 'OpenAI (Recommended)' },
            { value: 'gemini', label: 'Google Gemini' },
            { value: 'openrouter', label: 'OpenRouter (Many Models)' },
            { value: 'ollama', label: 'Ollama (Local)' },
            { value: 'groq', label: 'Groq (Ultra-fast)' },
            { value: 'mistral', label: 'Mistral AI' },
            { value: 'xai', label: 'xAI (Grok)' },
            { value: 'deepseek', label: 'DeepSeek' },
        ],
    });
    if ((0, prompts_1.isCancel)(provider))
        return process.exit(0);
    // 2. Model Name
    let modelOptions = [];
    if (provider === 'gemini') {
        modelOptions = [
            { value: 'gemini-3.1-pro', name: 'gemini-3.1-pro' },
            { value: 'gemini-3.1-flash-lite', name: 'gemini-3.1-flash-lite' },
            { value: 'gemini-2.5-flash', name: 'gemini-2.5-flash' },
            { value: 'gemini-2.5-pro', name: 'gemini-2.5-pro' },
            { value: 'gemini-1.5-pro', name: 'gemini-1.5-pro' },
            { value: 'gemini-1.5-flash', name: 'gemini-1.5-flash' },
        ];
    }
    else if (provider === 'openai') {
        modelOptions = [
            { value: 'gpt-5.5-pro', name: 'gpt-5.5-pro' },
            { value: 'gpt-5.5', name: 'gpt-5.5' },
            { value: 'gpt-5.4-mini', name: 'gpt-5.4-mini' },
            { value: 'gpt-5.4-nano', name: 'gpt-5.4-nano' },
            { value: 'gpt-4o', name: 'gpt-4o' },
            { value: 'o3-mini', name: 'o3-mini' },
        ];
    }
    else if (provider === 'openrouter') {
        modelOptions = [
            { value: 'anthropic/claude-3.5-sonnet', name: 'Claude 3.5 Sonnet' },
            { value: 'meta-llama/llama-3.3-70b-instruct', name: 'Llama 3.3 70B' },
            { value: 'google/gemini-3.1-pro', name: 'Gemini 3.1 Pro' },
            { value: 'openai/gpt-5.5', name: 'GPT-5.5' },
            { value: 'x-ai/grok-2', name: 'Grok 2' },
            { value: 'mistralai/mistral-large', name: 'Mistral Large' },
        ];
    }
    else if (provider === 'groq') {
        modelOptions = [
            { value: 'llama-3.3-70b-versatile', name: 'llama-3.3-70b-versatile' },
            { value: 'llama-3.1-8b-instant', name: 'llama-3.1-8b-instant' },
            { value: 'mixtral-8x7b-32768', name: 'mixtral-8x7b-32768' },
        ];
    }
    else if (provider === 'mistral') {
        modelOptions = [
            { value: 'mistral-large-latest', name: 'mistral-large-latest' },
            { value: 'mistral-small-latest', name: 'mistral-small-latest' },
            { value: 'open-mistral-nemo', name: 'open-mistral-nemo' },
        ];
    }
    else if (provider === 'xai') {
        modelOptions = [
            { value: 'grok-4.3', name: 'grok-4.3' },
            { value: 'grok-2-latest', name: 'grok-2-latest' },
            { value: 'grok-beta', name: 'grok-beta' },
        ];
    }
    else if (provider === 'deepseek') {
        modelOptions = [
            { value: 'deepseek-chat', name: 'deepseek-chat (V3)' },
            { value: 'deepseek-reasoner', name: 'deepseek-reasoner (R1)' },
        ];
    }
    else {
        modelOptions = [
            { value: 'llama3.2', name: 'llama3.2' },
            { value: 'llama3.1', name: 'llama3.1' },
            { value: 'qwen2.5', name: 'qwen2.5' },
            { value: 'phi4', name: 'phi4' },
            { value: 'mistral', name: 'mistral' },
        ];
    }
    modelOptions.push({ value: 'custom', name: '[Tulis Manual / Custom Model]' });
    let model = '';
    try {
        model = await (0, search_1.default)({
            message: 'Select AI Model (Type to search):',
            source: async (input) => {
                if (!input) {
                    return modelOptions;
                }
                return modelOptions.filter((opt) => opt.name.toLowerCase().includes(input.toLowerCase()) ||
                    opt.value.toLowerCase().includes(input.toLowerCase()));
            }
        });
    }
    catch (err) {
        if (err.name === 'ExitPromptError') {
            return process.exit(0);
        }
        throw err;
    }
    if (model === 'custom') {
        model = (await (0, prompts_1.text)({
            message: 'Enter custom model name (e.g., deepseek-coder, llama-3-8b-instruct):',
            initialValue: config.llm.model,
        }));
        if ((0, prompts_1.isCancel)(model))
            return process.exit(0);
    }
    // 3. API Key for LLM (Saved to config.yaml)
    let apiKey = '';
    if (provider !== 'ollama') {
        apiKey = (await (0, prompts_1.password)({
            message: `Enter API Key for ${provider} (Leave empty if already set):`,
        }));
        if ((0, prompts_1.isCancel)(apiKey))
            return process.exit(0);
    }
    // 3.5. Smart Web Search Setup
    const searchProvider = await (0, prompts_1.select)({
        message: 'Enable Smart Web Search for Nyxora AI?',
        options: [
            { value: 'skip', label: 'Skip (Use basic decentralized mesh)' },
            { value: 'tavily', label: 'Tavily Search (Built for AI - 1000 free/mo)' },
            { value: 'brave', label: 'Brave Search (Privacy focused - 2000 free/mo)' },
        ],
    });
    if ((0, prompts_1.isCancel)(searchProvider))
        return process.exit(0);
    let searchApiKey = '';
    if (searchProvider !== 'skip') {
        searchApiKey = (await (0, prompts_1.password)({
            message: `Enter API Key for ${searchProvider} (Get it free at ${searchProvider === 'tavily' ? 'tavily.com' : 'search.brave.com'}):`,
        }));
        if ((0, prompts_1.isCancel)(searchApiKey))
            return process.exit(0);
    }
    // 4. Default Chain
    const defaultChain = await (0, prompts_1.select)({
        message: 'Select Default Chain:',
        initialValue: config.agent.default_chain,
        options: [
            { value: 'ethereum', label: 'Ethereum Mainnet' },
            { value: 'bsc', label: 'BSC' },
            { value: 'base', label: 'Base' },
            { value: 'arbitrum', label: 'Arbitrum One' },
            { value: 'optimism', label: 'OP Mainnet' },
            { value: 'polygon', label: 'Polygon (Matic)' },
            { value: 'sepolia', label: 'Sepolia (Testnet)' },
        ],
    });
    if ((0, prompts_1.isCancel)(defaultChain))
        return process.exit(0);
    // 5. Telegram Bot
    const setupTelegram = await (0, prompts_1.confirm)({
        message: 'Do you want to setup the Telegram Bot?',
        initialValue: config.integrations?.telegram?.enabled || false,
    });
    if ((0, prompts_1.isCancel)(setupTelegram))
        return process.exit(0);
    let telegramToken = '';
    let authorizedChatId = config.integrations?.telegram?.authorized_chat_id;
    if (setupTelegram) {
        telegramToken = (await (0, prompts_1.password)({
            message: 'Enter Telegram Bot Token from @BotFather (Leave empty if already set):',
        }));
        if ((0, prompts_1.isCancel)(telegramToken))
            return process.exit(0);
        if (telegramToken && !authorizedChatId) {
            const s = (0, prompts_1.spinner)();
            const pin = Math.floor(100000 + Math.random() * 900000).toString();
            (0, prompts_1.note)(picocolors_1.default.cyan(`1. Open Telegram and search for your Bot.\n2. Send this exact message to your bot:\n\n   /auth ${pin}\n\nWaiting for your message...`), 'Telegram Pairing Required');
            s.start(`Waiting for /auth ${pin} on Telegram...`);
            try {
                const { Telegraf } = require('telegraf');
                const bot = new Telegraf(telegramToken);
                let paired = false;
                bot.command('auth', (ctx) => {
                    const text = ctx.message.text.split(' ');
                    if (text[1] === pin) {
                        authorizedChatId = ctx.chat.id;
                        paired = true;
                        ctx.reply('✅ Bot successfully paired with Nyxora!');
                        bot.stop();
                    }
                    else {
                        ctx.reply('❌ Invalid PIN.');
                    }
                });
                bot.launch();
                // Wait until paired
                while (!paired) {
                    await new Promise(r => setTimeout(r, 1000));
                }
                s.stop(`Bot successfully paired with Chat ID: ${authorizedChatId}`);
            }
            catch (err) {
                s.stop(`Failed to start bot listener: ${err.message}. You can pair it later.`);
            }
        }
    }
    // 6. Wallet Setup
    const walletSetupType = await (0, prompts_1.select)({
        message: 'Web3 Wallet Setup:',
        options: [
            { value: 'skip', label: 'Skip for now (No Web3 execution)' },
            { value: 'generate', label: 'Auto-Generate New Wallet' },
            { value: 'manual', label: 'Manual Input (Existing Private Key)' },
        ],
    });
    if ((0, prompts_1.isCancel)(walletSetupType))
        return process.exit(0);
    let privateKey = '';
    if (walletSetupType === 'manual') {
        privateKey = (await (0, prompts_1.password)({
            message: 'Enter Wallet Private Key (0x...)\n  (Will be securely locked in your OS Native Keyring Vault):',
        }));
        if ((0, prompts_1.isCancel)(privateKey))
            return process.exit(0);
    }
    else if (walletSetupType === 'generate') {
        privateKey = (0, accounts_1.generatePrivateKey)();
        const account = (0, accounts_1.privateKeyToAccount)(privateKey);
        (0, prompts_1.note)(`New Wallet Generated!\n\nAddress: ${account.address}\nPrivate Key: ${privateKey}\n\nIMPORTANT: Backup this Private Key NOW! It is securely injected into your local vault, but you will need it to import your wallet elsewhere.`, 'Wallet Created');
    }
    // --- SAVING ---
    // Update Config.yaml
    config.llm.provider = provider;
    config.llm.model = model;
    config.agent.default_chain = defaultChain;
    const newApiKeys = {};
    if (apiKey) {
        newApiKeys[`${provider}_key`] = apiKey;
    }
    if (!config.web_search)
        config.web_search = { provider: 'mesh', enabled: true };
    if (searchProvider !== 'skip') {
        config.web_search.provider = searchProvider;
        if (searchApiKey) {
            if (searchProvider === 'tavily')
                newApiKeys.tavily_key = searchApiKey;
            if (searchProvider === 'brave')
                newApiKeys.brave_key = searchApiKey;
        }
    }
    else {
        config.web_search.provider = 'mesh';
    }
    if (Object.keys(newApiKeys).length > 0) {
        await (0, parser_1.saveApiKeys)(newApiKeys);
    }
    if (!config.integrations)
        config.integrations = {};
    if (!config.integrations.telegram)
        config.integrations.telegram = { enabled: false };
    config.integrations.telegram.enabled = setupTelegram;
    if (setupTelegram && telegramToken) {
        config.integrations.telegram.bot_token = telegramToken;
    }
    if (authorizedChatId) {
        config.integrations.telegram.authorized_chat_id = authorizedChatId;
    }
    (0, parser_1.saveConfig)(config);
    // Save Private Key to OS Keyring or fallback to .env
    if (privateKey) {
        try {
            const { Entry } = require('@napi-rs/keyring');
            const entry = new Entry('nyxora', 'wallet');
            await entry.setPassword(privateKey);
            console.log(picocolors_1.default.green('Private key saved securely to OS Keyring.'));
        }
        catch (error) {
            console.warn(picocolors_1.default.yellow('Failed to save to OS Keyring (Module mismatch or headless server). Falling back to local vault.key'));
            const vaultPath = path_1.default.join(appDir, 'vault.key');
            fs_1.default.writeFileSync(vaultPath, `PRIVATE_KEY=${privateKey}\n`, { mode: 0o600 });
            console.log(picocolors_1.default.green('Private key saved to ~/.nyxora/vault.key with 0600 permissions.'));
        }
    }
    (0, prompts_1.outro)(picocolors_1.default.green('✨ Setup Successful! All configurations have been securely saved.'));
}
