#!/usr/bin/env node
/**
 * ===============================================================================
 *                    MATTERMOST BTCPAY ONION ADDRESS WEBHOOK
 * ===============================================================================
 * Created: September 10, 2025
 * Purpose: Retrieve BTCPay Server and Bitcoin onion addresses via Mattermost
 * Domain: thebankofdebbie.giiz.com
 * Usage: Post "!btcpay" or "!onion" in Mattermost to get current addresses
 */

const express = require('express');
const { exec } = require('child_process');
const fs = require('fs');
const path = require('path');

const app = express();
const PORT = process.env.PORT || 3001;

// Configuration
const config = {
    domain: 'thebankofdebbie.giize.com',
    mattermost_token: process.env.MATTERMOST_TOKEN || 'dr7gz6xwmt8qjg71wxcqjwqz1r',
    btcpay_tor_path: '/var/lib/docker/volumes/generated_tor_servicesdir/_data/BTCPayServer/hostname',
    bitcoin_tor_path: '/var/lib/docker/volumes/generated_tor_servicesdir/_data/BTC-P2P/hostname',
    allowed_users: ['admin', 'sysadmin', 'bankofdebbie'], // Add authorized users
    webhook_secret: process.env.WEBHOOK_SECRET || 'your-secret-here'
};

app.use(express.json());
app.use(express.urlencoded({ extended: true }));

/**
 * Utility function to read onion address from file
 */
function readOnionAddress(filePath) {
    return new Promise((resolve, reject) => {
        fs.readFile(filePath, 'utf8', (err, data) => {
            if (err) {
                resolve(null);
            } else {
                resolve(data.trim());
            }
        });
    });
}

/**
 * Get BTCPay Server status
 */
function getBTCPayStatus() {
    return new Promise((resolve) => {
        exec('docker ps --format "table {{.Names}}\\t{{.Status}}" | grep -E "(btcpay|bitcoin|tor)"', (error, stdout) => {
            if (error) {
                resolve('BTCPay services status unavailable');
            } else {
                resolve(stdout.trim() || 'No BTCPay services found');
            }
        });
    });
}

/**
 * Get Bitcoin sync status
 */
function getBitcoinSync() {
    return new Promise((resolve) => {
        exec('docker exec btcpayserver_bitcoind bitcoin-cli getblockchaininfo 2>/dev/null', (error, stdout) => {
            if (error) {
                resolve('Bitcoin RPC not available');
            } else {
                try {
                    const info = JSON.parse(stdout);
                    const progress = (info.verificationprogress * 100).toFixed(2);
                    resolve(`Blocks: ${info.blocks}/${info.headers} (${progress}% synced)${info.pruned ? ' - PRUNED' : ''}`);
                } catch (e) {
                    resolve('Bitcoin sync data unavailable');
                }
            }
        });
    });
}

/**
 * Get disk usage
 */
function getDiskUsage() {
    return new Promise((resolve) => {
        exec('df -h / | grep -v Filesystem', (error, stdout) => {
            if (error) {
                resolve('Disk usage unavailable');
            } else {
                const parts = stdout.trim().split(/\s+/);
                resolve(`${parts[2]} used / ${parts[1]} total (${parts[4]} full)`);
            }
        });
    });
}

/**
 * Main webhook endpoint
 */
app.post('/webhook/btcpay', async (req, res) => {
    try {
        // Log the incoming request for debugging
        console.log('Webhook received:', JSON.stringify(req.body, null, 2));

        const { token, team_domain, user_name, text, trigger_word } = req.body;

        // Validate token (basic security)
        if (token !== config.mattermost_token) {
            return res.status(401).json({ text: 'Unauthorized: Invalid token' });
        }

        // Check if user is authorized
        if (!config.allowed_users.includes(user_name)) {
            return res.status(403).json({ 
                text: `❌ Access denied for user: ${user_name}. Contact admin for BTCPay access.` 
            });
        }

        // Parse command
        const command = text.toLowerCase().trim();
        const isOnionCommand = command.includes('onion') || command.includes('btcpay') || command.includes('tor');
        const isStatusCommand = command.includes('status');
        const isHelpCommand = command.includes('help');

        if (isHelpCommand) {
            return res.json({
                text: `## BTCPay Server Commands\n\n` +
                      `**Available commands:**\n` +
                      `• \`!btcpay onion\` - Get onion addresses\n` +
                      `• \`!btcpay status\` - Get system status\n` +
                      `• \`!btcpay help\` - Show this help\n\n` +
                      `**Domain:** ${config.domain}\n` +
                      `**User:** ${user_name}\n` +
                      `**Access:** ✅ Authorized`
            });
        }

        if (isOnionCommand || isStatusCommand) {
            // Get onion addresses
            const [btcpayOnion, bitcoinOnion] = await Promise.all([
                readOnionAddress(config.btcpay_tor_path),
                readOnionAddress(config.bitcoin_tor_path)
            ]);

            // Get system status if requested
            let statusInfo = '';
            if (isStatusCommand) {
                const [btcpayStatus, bitcoinSync, diskUsage] = await Promise.all([
                    getBTCPayStatus(),
                    getBitcoinSync(),
                    getDiskUsage()
                ]);

                statusInfo = `\n\n**📊 System Status:**\n` +
                           `**Bitcoin:** ${bitcoinSync}\n` +
                           `**Disk:** ${diskUsage}\n` +
                           `**Services:** Running\n\n` +
                           `\`\`\`\n${btcpayStatus}\n\`\`\``;
            }

            // Format response
            const response = {
                text: `## 🧅 BTCPay Server Information\n\n` +
                      `**Domain:** ${config.domain}\n\n` +
                      `**🌐 Clearnet Access:**\n` +
                      `• https://${config.domain}\n\n` +
                      `**🧅 Tor Hidden Services:**\n` +
                      `• **BTCPay:** ${btcpayOnion || '⏳ Generating...'}\n` +
                      `• **Bitcoin P2P:** ${bitcoinOnion || '⏳ Generating...'}\n\n` +
                      `**🔐 Access Methods:**\n` +
                      `• **Tor Browser:** \`http://${btcpayOnion || 'pending'}\`\n` +
                      `• **SSH Tunnel:** \`ssh -L 8080:localhost:80 ubuntu@${config.domain}\`\n\n` +
                      `**⚡ Integration:**\n` +
                      `• **API Endpoint:** \`https://${config.domain}/api\`\n` +
                      `• **Webhook URL:** \`https://${config.domain}/webhook\`\n` +
                      `• **Onion API:** \`http://${btcpayOnion || 'pending'}/api\`\n\n` +
                      `**🔒 Security Status:** ✅ Tor-enabled, Pruned Bitcoin, Hardened VPS\n` +
                      `**📅 Updated:** ${new Date().toLocaleString()}\n` +
                      `**👤 Requested by:** ${user_name}` +
                      statusInfo
            };

            return res.json(response);
        }

        // Default response
        return res.json({
            text: `❓ Unknown command. Use \`!btcpay help\` for available commands.\n\n` +
                  `**Quick commands:**\n` +
                  `• \`!btcpay onion\` - Get onion addresses\n` +
                  `• \`!btcpay status\` - Get system status`
        });

    } catch (error) {
        console.error('Webhook error:', error);
        return res.status(500).json({ 
            text: `❌ Error retrieving BTCPay information: ${error.message}` 
        });
    }
});

/**
 * Health check endpoint
 */
app.get('/health', (req, res) => {
    res.json({ 
        status: 'healthy', 
        service: 'BTCPay Mattermost Webhook',
        domain: config.domain,
        timestamp: new Date().toISOString()
    });
});

/**
 * Root health endpoint with HTML response
 */
app.get('/', async (req, res) => {
    try {
        const [btcpayOnion, bitcoinOnion, diskUsage] = await Promise.all([
            readOnionAddress(config.btcpay_tor_path),
            readOnionAddress(config.bitcoin_tor_path),
            getDiskUsage()
        ]);

        const html = `<!DOCTYPE html>
<html>
<head>
    <title>BTCPay Server Health - ${config.domain}</title>
    <meta charset="UTF-8">
    <style>
        body { font-family: Arial, sans-serif; margin: 40px; background: #f5f5f5; }
        .container { max-width: 800px; margin: 0 auto; background: white; padding: 30px; border-radius: 8px; box-shadow: 0 2px 10px rgba(0,0,0,0.1); }
        .status { color: #28a745; font-weight: bold; }
        .onion { background: #f8f9fa; padding: 15px; border-radius: 5px; margin: 10px 0; word-break: break-all; }
        .section { margin: 20px 0; padding: 15px; border-left: 4px solid #007bff; }
    </style>
</head>
<body>
    <div class="container">
        <h1>🔒 BTCPay Server Health Status</h1>
        <p><strong>Domain:</strong> ${config.domain}</p>
        <p><strong>Status:</strong> <span class="status">✅ OPERATIONAL</span></p>
        <p><strong>Last Updated:</strong> ${new Date().toLocaleString()}</p>
        
        <div class="section">
            <h2>🌐 Access Points</h2>
            <p><strong>Clearnet:</strong> <a href="https://${config.domain}">https://${config.domain}</a></p>
            <p><strong>Health Dashboard:</strong> <a href="https://health.${config.domain}">https://health.${config.domain}</a></p>
        </div>

        <div class="section">
            <h2>🧅 Tor Hidden Services</h2>
            <p><strong>BTCPay Server:</strong></p>
            <div class="onion">${btcpayOnion || '⏳ Generating...'}</div>
            <p><strong>Bitcoin P2P Node:</strong></p>
            <div class="onion">${bitcoinOnion || '⏳ Generating...'}</div>
        </div>

        <div class="section">
            <h2>📊 System Information</h2>
            <p><strong>Disk Usage:</strong> ${diskUsage}</p>
            <p><strong>Bitcoin Mode:</strong> Pruned (10GB maximum)</p>
            <p><strong>Network:</strong> Tor-only Bitcoin connections</p>
            <p><strong>Security:</strong> Hardened Debian 13</p>
        </div>

        <div class="section">
            <h2>⚡ API Integration</h2>
            <p><strong>REST API:</strong> <code>https://${config.domain}/api</code></p>
            <p><strong>Tor API:</strong> <code>http://${btcpayOnion || 'pending'}/api</code></p>
            <p><strong>Webhooks:</strong> <code>https://${config.domain}/webhook</code></p>
        </div>

        <div class="section">
            <h2>🤖 Mattermost Integration</h2>
            <p><strong>Bot Account:</strong> bankofdebbie</p>
            <p><strong>Commands:</strong> !btcpay, !btcpay onion, !btcpay status</p>
            <p><strong>Webhook URL:</strong> <code>https://health.${config.domain}/webhook</code></p>
            <p><strong>Info API:</strong> <code>https://health.${config.domain}/info</code></p>
        </div>
    </div>
</body>
</html>`;

        res.send(html);
    } catch (error) {
        res.status(500).send(`<h1>Error</h1><p>${error.message}</p>`);
    }
});

/**
 * Info endpoint for API information (GET request)
 */
app.get('/info', async (req, res) => {
    try {
        const [btcpayOnion, bitcoinOnion, btcpayStatus, diskUsage] = await Promise.all([
            readOnionAddress(config.btcpay_tor_path),
            readOnionAddress(config.bitcoin_tor_path),
            getBTCPayStatus(),
            getDiskUsage()
        ]);

        res.json({
            domain: config.domain,
            btcpay_onion: btcpayOnion,
            bitcoin_onion: bitcoinOnion,
            clearnet_url: `https://${config.domain}`,
            api_url: `https://${config.domain}/api`,
            disk_usage: diskUsage,
            services_status: btcpayStatus,
            timestamp: new Date().toISOString()
        });
    } catch (error) {
        res.status(500).json({ error: error.message });
    }
});

/**
 * Start server
 */
app.listen(PORT, () => {
    console.log(`🚀 BTCPay Mattermost Webhook Server running on port ${PORT}`);
    console.log(`📡 Domain: ${config.domain}`);
    console.log(`🧅 Monitoring onion services...`);
    console.log(`💡 Endpoints:`);
    console.log(`   POST /webhook/btcpay - Main webhook`);
    console.log(`   GET  /webhook/btcpay/test - Test endpoint`);
    console.log(`   GET  /health - Health check`);
    console.log(`\n🔧 Setup in Mattermost:`);
    console.log(`   Trigger: !btcpay`);
    console.log(`   URL: http://localhost:${PORT}/webhook/btcpay`);
    console.log(`   Token: ${config.mattermost_token}`);
});

// Graceful shutdown
process.on('SIGTERM', () => {
    console.log('🛑 Shutting down webhook server...');
    process.exit(0);
});

module.exports = app;