const mineflayer = require('mineflayer');
const WebSocket = require('ws');
const fs = require('fs');
const path = require('path');

// Silence annoying Minecraft partial packet warning spams from Mineflayer
const overrideWrite = (stream) => {
    const originalWrite = stream.write;
    stream.write = function (chunk, encoding, callback) {
        const str = chunk.toString();
        if (str.includes("Chunk size") || str.includes("partial packet")) {
            return true;
        }
        return originalWrite.apply(stream, arguments);
    };
};
overrideWrite(process.stdout);
overrideWrite(process.stderr);

// Simple native .env loader to avoid dependencies
function loadEnv() {
    const envPath = path.join(__dirname, '.env');
    if (!fs.existsSync(envPath)) return {};
    const content = fs.readFileSync(envPath, 'utf8');
    const config = {};
    content.split('\n').forEach(line => {
        const cleanedLine = line.trim();
        if (!cleanedLine || cleanedLine.startsWith('#')) return;
        const parts = cleanedLine.split('=');
        if (parts.length >= 2) {
            const key = parts[0].trim();
            const value = parts.slice(1).join('=').trim();
            config[key] = value;
        }
    });
    return config;
}

const env = loadEnv();

const CONFIG = {
    host: env.MC_HOST || 'kolichub.net',
    port: parseInt(env.MC_PORT || '25565'),
    username: env.MC_USERNAME || 'KolicGambleBot',
    password: env.MC_PASSWORD || '',
    bridgeUrl: 'ws://127.0.0.1:8000/ws'
};

console.log(`🤖 Minecraft Client Bot (SMP) Başlatılıyor: ${CONFIG.username} -> ${CONFIG.host}:${CONFIG.port}`);

let bot = null;
let ws = null;
let isMcConnected = false;
let hasSentLogin = false;
let lastPayTimestamp = 0;
let lastPayKey = '';

// Money Parsing Helper (matches the player's custom in-game money formatting)
function parseMoney(rawStr) {
    if (!rawStr) return 0;
    const str = rawStr.toString().toLowerCase().trim();

    const suffixMatch = str.match(/([\d\.,]+)\s*([mkb])/i);
    if (suffixMatch) {
        let numVal = parseFloat(suffixMatch[1].replace(/,/g, ''));
        if (isNaN(numVal)) return 0;
        let unit = suffixMatch[2].toLowerCase();
        if (unit === 'm') return Math.round(numVal * 1000000);
        if (unit === 'b') return Math.round(numVal * 1000000000);
        if (unit === 'k') return Math.round(numVal * 1000);
    }

    const cleanDigits = str.replace(/[^\d]/g, '');
    if (cleanDigits.length > 0) {
        const val = parseInt(cleanDigits, 10);
        return isNaN(val) ? 0 : val;
    }
    return 0;
}

// Payment Message Parser
function extractPayment(message) {
    if (!message || typeof message !== 'string') return null;
    
    const cleanMsg = message.replace(/§[0-9a-fk-or]/gi, '').replace(/&[0-9a-fk-or]/gi, '').trim();
    const lower = cleanMsg.toLowerCase();

    // Skip outgoing messages unconditionally
    const isOutgoing = lower.includes('gönderdin') || lower.includes('gonderdin') || 
                       lower.includes('ödedin') || lower.includes('odedin') || 
                       lower.includes('gönderdiniz') || lower.includes('gonderdiniz') ||
                       lower.includes('ödediniz') || lower.includes('odediniz') ||
                       lower.includes('yolladınız') || lower.includes('yolladiniz') ||
                       lower.includes('yolladım') || lower.includes('yolladim');
    if (isOutgoing) {
        return null;
    }

    const isPaymentMsg = lower.includes('aldın') || lower.includes('aldin') || 
                         lower.includes('gönderdi') || lower.includes('gonderdi') || 
                         lower.includes('ödedi') || lower.includes('odedi') || 
                         lower.includes('yolladı') || lower.includes('yolladi') || 
                         lower.includes('aktarıldı') || lower.includes('transfer');

    if (!isPaymentMsg) return null;

    console.log(`🔍 [ÖDEME MESAJI DİNLENİYOR]: "${cleanMsg}"`);

    let player = null;
    let amount = 0;

    if (lower.includes('adlı oyuncudan') || lower.includes('adli oyuncudan')) {
        try {
            const parts = cleanMsg.split(/adlı oyuncudan|adli oyuncudan/i);
            const senderPart = parts[0].trim();
            const senderWords = senderPart.split(/\s+/);
            player = senderWords[senderWords.length - 1].replace(/[^a-zA-Z0-9_]/g, '');

            const amountPart = parts[1].replace(/aldın|aldin/gi, '').trim();
            amount = parseMoney(amountPart);

            if (player && amount > 0) return { player, amount };
        } catch (e) {}
    }

    try {
        const words = cleanMsg.split(/\s+/);
        for (let w of words) {
            let cleanW = w.replace(/[^a-zA-Z0-9_]/g, '');
            if (cleanW.length >= 3 && !['size', 'sana', 'hesabınıza', 'adlı', 'adli', 'oyuncudan', 'aldın', 'aldin', 'gönderdi', 'ödedi', 'gonderdi', 'odedi', 'yolladı', 'aktarıldı'].includes(cleanW.toLowerCase())) {
                player = cleanW;
                break;
            }
        }

        if (player) {
            const playerIndex = cleanMsg.indexOf(player);
            const afterPlayer = cleanMsg.substring(playerIndex + player.length);
            amount = parseMoney(afterPlayer);
        }
        if (amount === 0) {
            amount = parseMoney(cleanMsg);
        }

        if (player && amount > 0) return { player, amount };
    } catch (e) {}

    return null;
}

function handleChatMessage(rawMsg) {
    if (!rawMsg) return;
    const cleanMsg = rawMsg.replace(/§[0-9a-fk-or]/gi, '').trim();
    
    // Print all Minecraft server messages to the console for easy debugging
    console.log(`💬 [MC CHAT] ${cleanMsg}`);
    
    // Check if login is successful to automatically switch to SMP
    const lower = cleanMsg.toLowerCase();
    if (!cleanMsg.includes(':') && (lower.includes("successful login") || lower.includes("already logged in") || lower.includes("giriş başarılı") || lower.includes("giriş yaptın") || lower.includes("logged-in"))) {
        console.log("⏳ Giriş onaylandı! 2 saniye sonra SMP sunucusuna otomatik geçiş yapılıyor...");
        setTimeout(() => {
            if (bot && isMcConnected) {
                console.log("⏳ SMP sunucusuna geçiliyor... Fizik geçici olarak durduruluyor.");
                bot.physics.enabled = false;
                bot.chat('/smp');
            }
        }, 2000);
    }
    
    // Parse verification codes sent via custom server whisper formats:
    // e.g. "CastroFX_ size fısıldadı: onay 123456"
    // e.g. "[CastroFX_ -> bana] onay 123456"
    const whisperRegex = /(?:([a-zA-Z0-9_]+)\s*->\s*(?:KolicGambleBot|KolicGambleBot_)\s*:\s*|\[([^\]\s]+)\s*->\s*(?:bana|me)\]\s*|([a-zA-Z0-9_]+)\s*(?:size fısıldadı|size fisildadi|fısıldadı|fisildadi)\s*:\s*)(?:onay\s+)?(\d{6})/i;
    const whisperMatch = cleanMsg.match(whisperRegex);
    if (whisperMatch) {
        const player = (whisperMatch[1] || whisperMatch[2] || whisperMatch[3]).trim().replace(/[^a-zA-Z0-9_]/g, '');
        const code = whisperMatch[4];
        if (player && code) {
            if (ws && ws.readyState === WebSocket.OPEN) {
                ws.send(JSON.stringify({
                    type: 'verify_code',
                    username: player,
                    code: code
                }));
                console.log(`📤 [DOĞRULAMA KODU GÖNDERİLDİ - CHAT PARSER] Oyuncu: ${player} -> Kod: ${code}`);
            }
            return;
        }
    }

    // Parse payments
    const payment = extractPayment(cleanMsg);
    if (payment) {
        const payKey = `${payment.player}_${payment.amount}`;
        const now = Date.now();
        
        if (payKey === lastPayKey && (now - lastPayTimestamp) < 2000) {
            return;
        }
        lastPayKey = payKey;
        lastPayTimestamp = now;

        console.log(`💵 [ÖDEME TESPİT EDİLDİ] Oyuncu: ${payment.player}, Miktar: ${payment.amount}`);
        
        // Send to Discord Bot via WebSocket for automatic linking
        if (ws && ws.readyState === WebSocket.OPEN) {
            ws.send(JSON.stringify({
                type: 'auto_deposit',
                username: payment.player,
                amount: payment.amount
            }));
            console.log(`📤 [OTOMATİK YÜKLEME TALEBİ GÖNDERİLDİ] Oyuncu: ${payment.player}, Miktar: ${payment.amount}`);
        } else {
            console.log(`❌ Discord WebSocket bağlantısı kapalı! Bakiye otomatik yüklenemedi.`);
            bot.chat(`/msg ${payment.player} Hata: Discord bot bağlantısı kapalı. Lütfen yetkililere bildirin.`);
        }
    }
}

function sendBotStatus(connected, reason = '') {
    if (ws && ws.readyState === WebSocket.OPEN) {
        ws.send(JSON.stringify({
            type: 'bot_status',
            connected: Boolean(connected),
            username: (bot && bot.username) ? bot.username : CONFIG.username,
            server: `${CONFIG.host}:${CONFIG.port}`,
            reason: reason ? String(reason) : ''
        }));
    }
}

// Connect to Discord WebSocket Server
function connectToBridge() {
    console.log(`🔗 Discord köprü sunucusuna bağlanılıyor: ${CONFIG.bridgeUrl}`);
    ws = new WebSocket(CONFIG.bridgeUrl);

    ws.on('open', () => {
        console.log('✅ Discord bot köprü sunucusuna başarıyla bağlanıldı.');
        sendBotStatus(isMcConnected);
    });

    ws.on('message', async (messageStr) => {
        try {
            const data = JSON.parse(messageStr);
            if (data.type === 'auto_deposit_result') {
                const player = data.username;
                const amount = data.amount;
                const success = data.success;
                const reason = data.reason;
                const new_balance = data.new_balance;

                if (success) {
                    bot.chat(`/msg ${player} Discord bakiyeniz otomatik yüklendi! Güncel Bakiyeniz: ${new_balance.toLocaleString()} birim.`);
                    console.log(`✅ [OTOMATİK YÜKLEME BAŞARILI] Oyuncu: ${player}, Miktar: ${amount}`);
                } else {
                    if (reason === 'user_not_linked') {
                        bot.chat(`/msg ${player} Hata: Hesabınız Discord ile eşleşmemiş! Lütfen Discord'da /kayit ${player} yazın.`);
                        console.log(`❌ [OTOMATİK YÜKLEME BAŞARISIZ] Oyuncu ${player} hesap eşleştirmemiş.`);
                    } else {
                        bot.chat(`/msg ${player} Hata: Bakiye yüklenirken sistemsel hata oluştu.`);
                        console.log(`❌ [OTOMATİK YÜKLEME BAŞARISIZ] Veritabanı veya sistemsel hata.`);
                    }
                }
            }
            if (data.type === 'verify_result') {
                const player = data.username;
                const success = data.success;
                const reason = data.reason;

                if (success) {
                    bot.chat(`/msg ${player} Tebrikler! Discord hesabiniz basariyla eslestirildi. Artik bakiye yatirabilirsiniz.`);
                    console.log(`✅ [HESAP DOGRULAMA BASARILI] Oyuncu: ${player}`);
                } else {
                    if (reason === 'code_expired') {
                        bot.chat(`/msg ${player} Hata: Kodunuzun 5 dakikalik suresi dolmus. Lutfen Discord'dan yeni bir kod aliniz.`);
                        console.log(`❌ [HESAP DOGRULAMA BASARISIZ] Kodun suresi dolmus: ${player}`);
                    } else if (reason === 'too_many_attempts') {
                        bot.chat(`/msg ${player} Hata: 3 kez hatali kod girildi. Guvenlik sebebiyle kod iptal edildi.`);
                        console.log(`🚨 [HESAP DOGRULAMA KILITLENDI] Cok fazla hatali kod denemesi: ${player}`);
                    } else if (reason === 'invalid_code') {
                        const rem = data.remaining_attempts !== undefined ? ` (Kalan Hak: ${data.remaining_attempts})` : '';
                        bot.chat(`/msg ${player} Hata: Girdiginiz dogrulama kodu gecersiz${rem}.`);
                        console.log(`❌ [HESAP DOGRULAMA BASARISIZ] Oyuncu ${player} gecersiz kod girdi.`);
                    } else {
                        bot.chat(`/msg ${player} Hata: Eslestirme sirasinda sistemsel hata olustu.`);
                        console.log(`❌ [HESAP DOGRULAMA BASARISIZ] Sistemsel hata.`);
                    }
                }
            }
            if (data.type === 'execute_payout') {
                const tx_id = data.tx_id;
                const player = data.username;
                const amount = data.amount;

                console.log(`💸 [ÇEKİM EMRİ ALINDI] Oyuncu: ${player}, Miktar: ${amount} (TX ID: ${tx_id})`);

                if (bot && isMcConnected) {
                    let handled = false;

                    // Temporary chat listener for pay response
                    const onPayoutChat = (username, message) => {
                        const rawMsg = typeof message === 'string' ? message : (message.toString ? message.toString() : '');
                        const clean = stripMinecraftColors(rawMsg).toLowerCase();

                        // Check for insufficient bot treasury
                        if (clean.includes('yetersiz bakiye') || clean.includes('yeterli paranız') || clean.includes('yeterli para') ||
                            clean.includes('not enough money') || clean.includes('insufficient funds') || clean.includes('paranız yetmiyor') ||
                            clean.includes('bakiyeniz yetersiz') || clean.includes('paranız yok') || clean.includes('yeterli bakiyeniz') ||
                            clean.includes('paran yok')) {
                            if (!handled) {
                                handled = true;
                                bot.removeListener('chat', onPayoutChat);
                                bot.removeListener('messagestr', onPayoutMessageStr);
                                console.log(`🚨 [KASA YETERSİZ] Botun oyun içi kasasında yeterli para yok: ${amount}`);
                                ws.send(JSON.stringify({
                                    type: 'payout_result',
                                    tx_id: tx_id,
                                    success: false,
                                    reason: 'insufficient_bot_balance'
                                }));
                            }
                        } else if (clean.includes('oyuncu bulunamadı') || clean.includes('player not found') || clean.includes('çevrimdışı') || clean.includes('offline') || clean.includes('oyunda degil') || clean.includes('oyunda değil')) {
                            if (!handled) {
                                handled = true;
                                bot.removeListener('chat', onPayoutChat);
                                bot.removeListener('messagestr', onPayoutMessageStr);
                                console.log(`❌ [OYUNCU OFFLINE] Oyuncu bulunamadı: ${player}`);
                                ws.send(JSON.stringify({
                                    type: 'payout_result',
                                    tx_id: tx_id,
                                    success: false,
                                    reason: 'player_offline'
                                }));
                            }
                        }
                    };

                    const onPayoutMessageStr = (message) => {
                        onPayoutChat('', message);
                    };

                    bot.on('chat', onPayoutChat);
                    bot.on('messagestr', onPayoutMessageStr);

                    // Send payout command in game
                    bot.chat(`/pay ${player} ${amount}`);
                    console.log(`✅ Oyun içi pay komutu gönderildi: /pay ${player} ${amount}`);

                    // Wait 2.2 seconds. If no error caught, confirm success!
                    setTimeout(() => {
                        if (!handled) {
                            handled = true;
                            bot.removeListener('chat', onPayoutChat);
                            bot.removeListener('messagestr', onPayoutMessageStr);
                            ws.send(JSON.stringify({
                                type: 'payout_result',
                                tx_id: tx_id,
                                success: true
                            }));
                        }
                    }, 2200);
                } else {
                    ws.send(JSON.stringify({
                        type: 'payout_result',
                        tx_id: tx_id,
                        success: false,
                        reason: 'Minecraft botu sunucuya bağlı değil.'
                    }));
                }
            }
            if (data.type === 'remote_chat') {
                const msgToSend = data.message;
                console.log(`💬 [UZAKTAN CHAT KOMUTU] Mesaj: ${msgToSend}`);
                if (bot && isMcConnected) {
                    bot.chat(msgToSend);
                    ws.send(JSON.stringify({
                        type: 'remote_chat_result',
                        success: true,
                        message: msgToSend
                    }));
                } else {
                    ws.send(JSON.stringify({
                        type: 'remote_chat_result',
                        success: false,
                        reason: 'Minecraft botu bağlı değil.'
                    }));
                }
            }
            if (data.type === 'remote_reconnect') {
                console.log(`🔄 [UZAKTAN YENİDEN BAĞLANMA TALEBİ]`);
                if (bot) {
                    try { bot.end(); } catch (e) {}
                }
                setTimeout(connectToMinecraft, 2000);
                ws.send(JSON.stringify({
                    type: 'remote_reconnect_result',
                    success: true
                }));
            }
            if (data.type === 'get_bot_info') {
                const req_id = data.req_id;
                if (bot && isMcConnected) {
                    const pos = bot.entity ? bot.entity.position : { x: 0, y: 0, z: 0 };
                    ws.send(JSON.stringify({
                        type: 'bot_info_response',
                        req_id: req_id,
                        success: true,
                        is_online: true,
                        username: bot.username,
                        health: bot.health || 20,
                        food: bot.food || 20,
                        x: Math.round(pos.x),
                        y: Math.round(pos.y),
                        z: Math.round(pos.z),
                        player_count: Object.keys(bot.players || {}).length,
                        server: `${CONFIG.host}:${CONFIG.port}`
                    }));
                } else {
                    ws.send(JSON.stringify({
                        type: 'bot_info_response',
                        req_id: req_id,
                        success: false,
                        is_online: false,
                        server: `${CONFIG.host}:${CONFIG.port}`
                    }));
                }
            }
        } catch (e) {
            console.error('⚠️ Bridge message parsing error:', e);
        }
    });

    ws.on('close', () => {
        console.warn('❌ Discord bot köprü bağlantısı kesildi. 5 saniye sonra tekrar bağlanılıyor...');
        setTimeout(connectToBridge, 5000);
    });

    ws.on('error', (err) => {
        console.error('⚠️ Bridge connection error:', err.message);
    });
}

// Connect to Minecraft Server
function connectToMinecraft() {
    isMcConnected = false;
    hasSentLogin = false;
    
    bot = mineflayer.createBot({
        host: CONFIG.host,
        port: CONFIG.port,
        username: CONFIG.username,
        version: false, // Auto-negotiate version
        auth: 'offline',
        checkTimeoutInterval: 60000
    });

    bot.on('login', () => {
        isMcConnected = true;
        console.log(`🔑 Minecraft sunucusuna giriş yapıldı! (${CONFIG.username})`);
        sendBotStatus(true);
    });

    bot.on('spawn', () => {
        isMcConnected = true;
        bot.physics.enabled = true; // Ensure physics is enabled when spawning
        console.log(`✅ Minecraft Dünyasına Doğuldu (Spawn)! Bot Adı: ${bot.username}`);
        sendBotStatus(true);
        
        if (CONFIG.password && !hasSentLogin) {
            hasSentLogin = true;
            setTimeout(() => {
                bot.chat(`/login ${CONFIG.password}`);
            }, 2000);
        }
    });

    bot.on('resourcePackSend', (url, hash) => {
        console.log(`📥 [KAYNAK PAKETİ] Sunucudan kaynak paketi isteği alındı, kabul ediliyor...`);
        try {
            bot.acceptResourcePack();
        } catch (err) {
            console.error('⚠️ Kaynak paketi kabul edilirken hata:', err.message);
        }
    });

    bot.on('end', (reason) => {
        isMcConnected = false;
        sendBotStatus(false, reason);
        console.log(`❌ Minecraft sunucusu bağlantısı kesildi. Sebeb: ${reason}. 5 saniye sonra tekrar bağlanılıyor...`);
        setTimeout(connectToMinecraft, 5000);
    });

    bot.on('kicked', (reason) => {
        isMcConnected = false;
        sendBotStatus(false, typeof reason === 'object' ? JSON.stringify(reason) : reason);
        console.warn(`❌ Sunucudan Atıldı! Sebep: ${typeof reason === 'object' ? JSON.stringify(reason) : reason}`);
    });

    bot.on('error', (err) => {
        isMcConnected = false;
        sendBotStatus(false, err.message || String(err));
        console.error('⚠️ Minecraft Bot Hatası:', err.message || err);
    });

    bot.on('messagestr', (message) => {
        if (!isMcConnected) {
            isMcConnected = true;
            sendBotStatus(true);
        }
        handleChatMessage(message);
    });

    bot.on('chat', (username, message) => {
        if (message) {
            handleChatMessage(`${username}: ${message}`);
        }
    });

    bot.on('whisper', (username, message) => {
        if (username === bot.username) return;
        console.log(`💬 [FISILTI] ${username}: ${message}`);
        
        const cleanMsg = message.trim();
        const match = cleanMsg.match(/(?:onay\s+)?(\d{6})/i);
        if (match) {
            const code = match[1];
            if (ws && ws.readyState === WebSocket.OPEN) {
                ws.send(JSON.stringify({
                    type: 'verify_code',
                    username: username,
                    code: code
                }));
                console.log(`📤 [DOĞRULAMA KODU GÖNDERİLDİ - FISILTI] Oyuncu: ${username} -> Kod: ${code}`);
            } else {
                bot.chat(`/msg ${username} Hata: Discord bot bağlantısı kopuk.`);
            }
        }
    });
}

const readline = require('readline');
const rl = readline.createInterface({
    input: process.stdin,
    output: process.stdout
});

rl.on('line', (line) => {
    const input = line.trim();
    if (input) {
        if (bot && isMcConnected) {
            if (input === '/smp') {
                console.log("⏳ Sunucu geçişi algılandı! Fizik motoru ve hareket paketleri geçici olarak durduruluyor...");
                bot.physics.enabled = false;
            }
            bot.chat(input);
            console.log(`💬 [KONSOLDAN GÖNDERİLDİ] ${input}`);
        } else {
            console.log("⚠️ Minecraft botu sunucuya bağlı değil. Mesaj gönderilemedi.");
        }
    }
});

// Periodic heartbeat to ensure Discord status channel stays in sync
setInterval(() => {
    if (bot && isMcConnected) {
        sendBotStatus(true);
    }
}, 60000);

// Start both connections
connectToBridge();
connectToMinecraft();
