import asyncio
import time
from selenium import webdriver
from selenium.webdriver.chrome.options import Options
from selenium.webdriver.common.by import By
from selenium.webdriver.support.wait import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
import re
import MetaTrader5 as mt5
import pandas as pd
from telegram import Bot

# telegram
TOKEN = '<TRUFFLEHOG_REDACTED_TELEGRAMBOTTOKEN>'
CHAT_ID = '882283026'
URL = 'https://id.tradingview.com/chart/2f71DPzH/?symbol=OANDA%3AXAUUSD'
login = 124385496
server = "Exness-MT5Trial7"
password = "748798lokaldeN#" 
symbol = "XAUUSDm"
volume = 0.01
timeframe = mt5.TIMEFRAME_M5
time_candle = 30 #second
time_check = 900 #second

# chrome_options = Options()
# chrome_options.add_argument('--headless')

# driver = webdriver.Chrome(options=chrome_options)
bot = Bot(TOKEN)

driver = webdriver.Chrome()
driver.get(URL)

async def send_message_async(message):
    await bot.send_message(chat_id=CHAT_ID, text=message)
    
async def wait_dot(driver):
    try:

        while True:
            
        # Menunggu hingga elemen muncul
            element = WebDriverWait(driver, 5).until(
                lambda driver: re.search(r'color: rgb\((\d+), (\d+), (\d+)\)', driver.find_element(By.XPATH, "/html/body/div[2]/div[5]/div[1]/div[1]/div/div[2]/div[3]/div[2]/div/div[2]/div/div[2]/div[2]/div[2]/div/div[4]/div").get_attribute("style"))
            )
        
            if element:
                red, green, blue = map(int, element.groups())
            
                if red == 255 and green == 255 and blue == 255:
                    print("Sell")
                    await send_message_async("Dot Sell")
                    return "Sell"
                # Check if color is black
                elif red == 0 and green == 0 and blue == 0:
                    print("Buy")
                    await send_message_async("Dot Buy")
                    return "Buy"
                else:
                    print("Unknown color")
                    await send_message_async("Dot Unknown")
                
                await asyncio.sleep(1)

            else:
                print("Warna tidak ditemukan")
                await send_message_async("Dot Color Unknown")

    except Exception as e:
        print("Gagal menemukan elemen:", e)
        await send_message_async("Dot Still Running")

async def check_trend(driver):
    try:
        trend = driver.find_element(By.XPATH, "/html/body/div[2]/div[5]/div[1]/div[1]/div/div[2]/div[1]/div[2]/div/div[2]/div[2]/div[2]/div[2]/div[2]/div/div[3]/div")
        price = driver.find_element(By.XPATH, "/html/body/div[2]/div[5]/div[1]/div[1]/div/div[2]/div[1]/div[2]/div/div[2]/div[1]/div[1]/div[2]/div/div[5]/div[2]")
        
        trend_value = float(trend.text)
        price_value = float(price.text)

        if trend_value < price_value:
            print("Trend: Buy")
            await send_message_async("Trend Buy")
            return "Buy"
        elif trend_value > price_value:
            print("Trend: Sell")
            await send_message_async("Trend Sell")
            return "Sell"
        else:
            print("Trend: Neutral")
            await send_message_async("Trend Neutral")
    except Exception as e:
        print("Gagal menemukan Trend:", e)
        await send_message_async("Trend Not Found")

prev_candle_color = "merah"

async def wait_candle(symbol, timeframe, initial_color, target_color):
    global prev_candle_color

    if not mt5.initialize():
        print("initialize() failed, error code =", mt5.last_error())
        return None

    while True:
        candles = mt5.copy_rates_from_pos(symbol, timeframe, 0, 2)
        df = pd.DataFrame(candles)
        
        current_candle_color = 'hijau' if df['close'][1] > df['close'][0] else 'merah'
        print("Warna candle saat ini:", current_candle_color)
        await send_message_async(f"Candle Color now: {current_candle_color}")
        
        # Jika arah perdagangan adalah buy, tunggu perubahan dari merah ke hijau
        if prev_candle_color == 'merah' and current_candle_color == 'hijau' and target_color == 'hijau':
            print("Perubahan candle dari merah ke hijau terdeteksi!")
            await send_message_async("Red Candle to Green Detected!!")
            prev_candle_color = current_candle_color
            mt5.shutdown()
            return True
        # Jika arah perdagangan adalah sell, tunggu perubahan dari hijau ke merah
        elif prev_candle_color == 'hijau' and current_candle_color == 'merah' and target_color == 'merah':
            print("Perubahan candle dari hijau ke merah terdeteksi!")
            await send_message_async("Green Candle to Red Detected!!")
            prev_candle_color = current_candle_color
            mt5.shutdown()
            return True
        else:
            prev_candle_color = current_candle_color
            await asyncio.sleep(2)

async def wait_candle2(symbol, timeframe, initial_color, target_color, order_type):
    prev_candle_color = initial_color 

    if not mt5.initialize():
        print("initialize() failed, error code =", mt5.last_error())
        return None

    candles = mt5.copy_rates_from_pos(symbol, timeframe, 0, 2)
    df = pd.DataFrame(candles)
    
    current_candle_color = 'hijau' if df['close'][1] > df['close'][0] else 'merah'
    
    # print("Warna candle sebelumnya:", prev_candle_color)
    # print("Warna candle saat ini:", current_candle_color)

    if order_type == 'buy':
        return prev_candle_color == 'merah' and current_candle_color == 'hijau'
    elif order_type == 'sell':
        return prev_candle_color == 'hijau' and current_candle_color == 'merah'
    else:
        result = False
    
    # Setelah pengecekan, atur ulang nilai prev_candle_color
    prev_candle_color = current_candle_color

    return result

async def execute_trade(symbol, timeframe, initial_color, target_color, order_type):
    global prev_candle_color

    prev_candle_color = initial_color
    result = await wait_candle(symbol, timeframe, initial_color, target_color)
    await asyncio.sleep(time_candle)
    result2 = await wait_candle2(symbol, timeframe, initial_color, target_color, order_type)
    if result and result2:
        await send_order(order_type=order_type)
    else:
        await execute_trade(symbol, timeframe, initial_color, target_color, order_type)

async def check_candle_after_order(symbol, timeframe, duration, order_type):
    global prev_candle_color
    
    if not mt5.initialize():
        print("initialize() failed, error code =", mt5.last_error())
        return None
    
    start_time = time.time()
    end_time = start_time + duration
    
    while time.time() < end_time:
        candles = mt5.copy_rates_from_pos(symbol, timeframe, 0, 2)
        df = pd.DataFrame(candles)

        current_candle_color = 'hijau' if df['close'][1] > df['open'][1] else 'merah'
        print("Warna candle saat ini setelah open order:", current_candle_color)
        await send_message_async(f"Candle Color After Order: {current_candle_color}")
        
        if order_type == "buy" and current_candle_color == 'merah':
            print("Candle close nya merah, kembali ke wait_candle")
            await send_message_async("Red Candle, Back to Wait Candle")
            prev_candle_color = current_candle_color
            return False
        elif order_type == "sell" and current_candle_color == 'hijau':
            print("Candle close nya hijau, kembali ke wait_candle")
            await send_message_async("Green Candle, Back to Wait Candle")
            prev_candle_color = current_candle_color
            return False
        await asyncio.sleep(time_candle)
    
    print("Waktu pengecekan candle setelah open order sudah habis, lanjut ke langkah berikutnya")
    await send_message_async("Candle Check Timeout")
    return True
        
async def send_order(login=login, server=server, password=password, symbol=symbol, volume=volume, order_type=None):
    if not mt5.initialize(login=login, server=server, password=password):
        print("initialize() failed, error code =", mt5.last_error())
        return
    
    action = mt5.TRADE_ACTION_DEAL
    order_type = mt5.ORDER_TYPE_BUY if order_type == "buy" else mt5.ORDER_TYPE_SELL

    result = mt5.order_send({
        "action": action,
        "symbol": symbol,
        "volume": volume,
        "type": order_type,
        "price": mt5.symbol_info_tick(symbol).ask if order_type == mt5.ORDER_TYPE_BUY else mt5.symbol_info_tick(symbol).bid,
        "deviation": 20,
        "magic": 234000,
        "type_time": mt5.ORDER_TIME_GTC,
        "type_filling": mt5.ORDER_FILLING_FOK,
    })
    
    if result.retcode == mt5.TRADE_RETCODE_DONE:
        print("Order successful")
        await send_message_async("Order Position Open")
    else:
        print("Order failed")
        await send_message_async("Order Failed")
    mt5.shutdown()

async def main():
    while True:
        try:
            await send_message_async("Waiting.....")

            driver.refresh()
            
            dot_result = await wait_dot(driver)
            trend_result = await check_trend(driver)

            if dot_result == "Buy" and trend_result == "Sell":
                print("Wait Candle for Sell")
                await send_message_async("Wait Candle for Sell")
                await execute_trade(symbol, timeframe, "hijau", "merah", order_type="sell")
                result = await check_candle_after_order(symbol, timeframe, time_check, order_type="sell")
                if not result:
                    await execute_trade(symbol, timeframe, "hijau", "merah", order_type="sell")

            elif dot_result == "Sell" and trend_result == "Buy":
                print("Wait Candle for Buy")
                await send_message_async("Wait Candle for Buy")
                await execute_trade(symbol, timeframe, "merah", "hijau", order_type="buy")
                result = await check_candle_after_order(symbol, timeframe, time_check, order_type="buy")
                if not result:
                    await execute_trade(symbol, timeframe, "merah", "hijau", order_type="buy")

            else:
                print("No suitable conditions found for trade execution.")
                await send_message_async("Wait next Dot, No Trade Open")

        except Exception as e:
            # Tangani kesalahan di sini
            print("An error occurred:", str(e))
            await send_message_async("An error occurred: " + str(e))
            await asyncio.sleep(3)  # Contoh: Jeda 60 detik sebelum melanjutkan loop
            continue
        
        finally:
            # Optional: Pause execution before continuing the loop
            await asyncio.sleep(5)

asyncio.run(main())