#!/usr/bin/env python3
import os, sys, warnings

# ========== FORCE FFMPEG PATH (NO WARNING) ==========
FFMPEG_DIR = r"C:\Users\inter\AppData\Local\Microsoft\WinGet\Packages\Gyan.FFmpeg_Microsoft.Winget.Source_8wekyb3d8bbwe\ffmpeg-8.1.1-full_build\bin"
os.environ["PATH"] = FFMPEG_DIR + os.pathsep + os.environ.get("PATH", "")
os.environ["PYDUB_FFMPEG"] = os.path.join(FFMPEG_DIR, "ffmpeg.exe")
warnings.filterwarnings("ignore", category=RuntimeWarning, module="pydub.utils")

# Monkey-patch pydub's which()
from pydub.utils import which
_original_which = which
def _forced_which(prog):
    if prog in ('ffmpeg', 'avconv'):
        return os.environ["PYDUB_FFMPEG"]
    return _original_which(prog)
import pydub.utils
pydub.utils.which = _forced_which

import pydub
pydub.AudioSegment.converter = os.environ["PYDUB_FFMPEG"]

# Other imports
import json, time, asyncio, threading
from http.server import HTTPServer, BaseHTTPRequestHandler
from telegram import Update
from telegram.ext import Application, MessageHandler, filters, ContextTypes
import speech_recognition as sr

# ==================== CONFIG ====================
TELEGRAM_TOKEN = "REPLACE WITH YOUR BOT TOKEN"
ALLOWED_CHAT_ID = 000000000 #REPLACE WITH YOUR CHAT ID
HTTP_PORT = 8082

command_queue = []
queue_lock = threading.Lock()
result = None
result_event = threading.Event()

# ==================== HTTP SERVER ====================
class CommandHandler(BaseHTTPRequestHandler):
    def log_message(self, format, *args):
        pass
    def do_GET(self):
        if self.path == '/get_command':
            self.send_response(200)
            self.send_header('Content-Type', 'application/json')
            self.end_headers()
            with queue_lock:
                if command_queue:
                    cmd = command_queue.pop(0)
                    self.wfile.write(json.dumps(cmd).encode())
                    print(f"Served: {cmd}")
                else:
                    self.wfile.write(json.dumps({"action": None}).encode())
        else:
            self.send_response(404)
    def do_POST(self):
        if self.path == '/post_response':
            length = int(self.headers.get('Content-Length', 0))
            raw = self.rfile.read(length)
            try:
                data_str = raw.decode('utf-8').strip().rstrip('\x00')
                global result
                result = json.loads(data_str)
                result_event.set()
                print(f"Result: {result}")
            except Exception as e:
                print(f"POST error: {e}")
            self.send_response(200)
            self.end_headers()
        else:
            self.send_response(404)

def start_http_server():
    server = HTTPServer(('127.0.0.1', HTTP_PORT), CommandHandler)
    print(f"✅ HTTP server on {HTTP_PORT}")
    server.serve_forever()

# ==================== AUDIO ====================
def transcribe_audio(wav_path):
    recognizer = sr.Recognizer()
    with sr.AudioFile(wav_path) as src:
        recognizer.adjust_for_ambient_noise(src, 0.5)
        audio = recognizer.record(src)
    try:
        return recognizer.recognize_google(audio).lower()
    except:
        return ""

def parse_command(text):
    text = text.lower().strip()
    if "close all" in text:
        return {"action": "CLOSE_ALL"}
    if "balance" in text:
        return {"action": "BALANCE"}
    action = None
    if text.startswith("buy"):
        action = "BUY"
        text = text[3:].strip()
    elif text.startswith("sell"):
        action = "SELL"
        text = text[4:].strip()
    else:
        return None
    # ✅ DEFAULT LOT SIZE = 0.001 (micro lot, ~$117 for EURUSD)
    volume = 0.001
    words = text.split()
    for i, w in enumerate(words):
        if w == "half":
            volume = 0.5
            words.pop(i)
            break
        elif w in ["one", "a"]:
            volume = 1.0
            words.pop(i)
            break
        else:
            try:
                volume = float(w)
                words.pop(i)
                break
            except:
                pass
    sym_text = " ".join(words)
    m = {"gold": "XAUUSD", "euro": "EURUSD", "pound": "GBPUSD", "silver": "XAGUSD", "oil": "USOIL"}
    symbol = "EURUSD"
    for k, v in m.items():
        if k in sym_text:
            symbol = v
            break
    return {"action": action, "symbol": symbol, "volume": volume}

def cleanup(*files):
    for f in files:
        if os.path.exists(f):
            try:
                os.remove(f)
            except:
                pass

async def handle_voice(update, context):
    if update.effective_chat.id != ALLOWED_CHAT_ID:
        await update.message.reply_text("Unauthorized")
        return
    await update.message.reply_text("🎤 Processing...")
    voice = await update.message.voice.get_file()
    ogg, wav = "temp.ogg", "temp.wav"
    try:
        await voice.download_to_drive(ogg)
        audio = pydub.AudioSegment.from_ogg(ogg)
        audio = audio.set_frame_rate(16000).set_channels(1)
        audio.export(wav, format="wav")
        text = transcribe_audio(wav)
        if not text:
            await update.message.reply_text("❌ Could not understand")
            return
        await update.message.reply_text(f"📝 Heard: {text}")
        cmd = parse_command(text)
        if not cmd:
            await update.message.reply_text("❌ Invalid command. Example: 'buy 0.001 euro'")
            return
        with queue_lock:
            command_queue.append(cmd)
        await update.message.reply_text("⏳ Sending to MT5...")
        global result
        result = None
        result_event.clear()
        if result_event.wait(timeout=10):
            if result and result.get("status") == "success":
                msg = f"✅ Success!\nTicket: {result['ticket']}\nPrice: {result['price']}"
            else:
                msg = f"❌ Error: {result.get('message') if result else 'Unknown'}"
        else:
            msg = "⏰ No response from MT5. Is EA running?"
        await update.message.reply_text(msg)
    except Exception as e:
        await update.message.reply_text(f"❌ {str(e)[:100]}")
    finally:
        cleanup(ogg, wav)

async def error_handler(update, context):
    print(f"Telegram error: {context.error}")

def main():
    threading.Thread(target=start_http_server, daemon=True).start()
    app = Application.builder().token(TELEGRAM_TOKEN).build()
    app.add_handler(MessageHandler(filters.VOICE, handle_voice))
    app.add_error_handler(error_handler)
    print("✅ Telegram bot polling...")
    app.run_polling()

if __name__ == "__main__":
    main()