import asyncio
import json
import math
import random
import re
import ctypes
from playwright.async_api import async_playwright

# ================== ẨN CỬA SỔ CMD ==================
def hide_console():
    try:
        hwnd = ctypes.windll.kernel32.GetConsoleWindow()
        if hwnd:
            ctypes.windll.user32.ShowWindow(hwnd, 0)  # 0 = SW_HIDE
    except Exception:
        pass

hide_console()
# ===================================================



# ================== CẤU HÌNH ==================
USERNAME = "nhi1509"
PASSWORD = "abc13579"
LOGIN_URL = "https://1900.fun/login.php"
THAM_HIEM_URL = "https://1900.fun/city/thamhiem/"

# Thời gian nghỉ giữa các vòng (giây)
DELAY_AFTER_WIN = 30          # Nghỉ 30s sau khi leo hết / hoàn thành 1 vòng
DELAY_AFTER_LOSE = 1 * 10     # Nghỉ 10 giây khi thua (có thể đang cooldown 24h)
DELAY_AFTER_ERROR = 2 * 60    # Nghỉ 2 phút khi lỗi
# ==============================================


def clean_and_parse_json(raw_text: str) -> dict:
    try:
        match = re.search(r"\{.*\}", raw_text, re.DOTALL)
        if match:
            return json.loads(match.group(0))
        return {"success": False, "error": f"Không tìm thấy JSON: {raw_text[:150]}"}
    except Exception as e:
        return {"success": False, "error": f"Lỗi parse JSON: {e}"}


async def fetch_ajax(page, body: str) -> dict:
    raw = await page.evaluate(
        f"""async () => {{
            try {{
                const res = await fetch('ajax_dungeon.php', {{
                    method: 'POST',
                    headers: {{ 'Content-Type': 'application/x-www-form-urlencoded' }},
                    body: '{body}'
                }});
                return await res.text();
            }} catch (e) {{
                return e.toString();
            }}
        }}"""
    )
    return clean_and_parse_json(raw)


async def run_boss_bot() -> str:
    """
    Chạy 1 vòng thám hiểm.
    Trả về: "win_cycle" | "lose" | "error"
    """
    async with async_playwright() as p:
        browser = await p.chromium.launch(headless=True)
        context = await browser.new_context(
            user_agent="Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36"
        )
        page = await context.new_page()

        try:
            # 1. Đăng nhập
            print(f"[*] Đăng nhập: {USERNAME}")
            await page.goto(LOGIN_URL, wait_until="domcontentloaded")
            await page.fill("input[name='username']", USERNAME)
            await page.fill("input[name='password']", PASSWORD)
            async with page.expect_navigation(wait_until="domcontentloaded"):
                await page.click("button[type='submit']")
            await page.wait_for_timeout(1200)

            # 2. Vào trang Thám hiểm
            print("[*] Vào trang Thám hiểm...")
            await page.goto(THAM_HIEM_URL, wait_until="domcontentloaded")
            await page.wait_for_timeout(1500)

            # 3. Lấy dữ liệu cửa ải hiện tại
            init_data = await fetch_ajax(page, "action=get_current_floor")
            if not init_data.get("success"):
                err = init_data.get("error", "Không xác định")
                print(f"[!] Lỗi khởi tạo: {err}")
                # Có thể đang trong thời gian chờ reset 24h
                if "reset" in str(err).lower() or "chờ" in str(err).lower() or "đợi" in str(err).lower():
                    return "lose"
                return "error"

            current_floor = init_data.get("floor", 1)
            monster = init_data.get("monster", {})
            monster_hp = monster.get("hp", 0)
            monster_strength = monster.get("strength", 0)
            monster_name = monster.get("name", "Boss")
            player_hp = init_data.get("player_hp", 0)
            player_strength = init_data.get("player_strength", 0)

            # 4. Vòng lặp leo ải
            while True:
                print(f"\n========== [ CỬA ẢI {current_floor} ] ==========")
                print(f"👤 Bạn     | HP: {player_hp:,} | SM: {player_strength}")
                print(f"👾 {monster_name} | HP: {monster_hp:,} | SM: {monster_strength}")

                # Mô phỏng trận đấu client-side
                curr_p_hp = player_hp
                curr_m_hp = monster_hp
                is_my_turn = True

                while curr_p_hp > 0 and curr_m_hp > 0:
                    if is_my_turn:
                        dmg = max(5, math.floor(random.random() * player_strength) + 8)
                        curr_m_hp = max(0, curr_m_hp - dmg)
                        is_my_turn = False
                    else:
                        dmg = max(5, math.floor(random.random() * monster_strength) + 8)
                        curr_p_hp = max(0, curr_p_hp - dmg)
                        is_my_turn = True

                is_win = curr_m_hp <= 0
                print(f"[⚔️] Kết quả: {'CHIẾN THẮNG' if is_win else 'THẤT BẠI'}")

                result = "win" if is_win else "lose"
                battle_res = await fetch_ajax(
                    page,
                    f"action=end_battle&result={result}&floor={current_floor}"
                )

                if not battle_res.get("success"):
                    print(f"[!] Server từ chối: {battle_res.get('error')}")
                    return "error"

                print(f"  └─ {battle_res.get('message', 'OK')}")
                if battle_res.get("drop_item"):
                    item = battle_res["drop_item"]
                    print(f"  └─ 🎁 {item.get('name')} (+{item.get('enhance_level', 0)})")
                if battle_res.get("new_xu"):
                    print(f"  └─ 🪙 Xu mới: {battle_res['new_xu']:,}")

                if not is_win:
                    print("\n[⛔] Thua → về cửa ải 1.")
                    return "lose"

                # Chờ nhẹ rồi lấy cửa ải tiếp
                await asyncio.sleep(random.uniform(1.2, 2.0))
                next_data = await fetch_ajax(page, "action=get_current_floor")
                if not next_data.get("success"):
                    print("[!] Không lấy được cửa ải tiếp theo.")
                    return "error"

                current_floor = next_data.get("floor", current_floor + 1)
                monster = next_data.get("monster", {})
                monster_hp = monster.get("hp", 0)
                monster_strength = monster.get("strength", 0)
                monster_name = monster.get("name", "Boss")
                player_hp = next_data.get("player_hp", player_hp)
                player_strength = next_data.get("player_strength", player_strength)

        except Exception as e:
            print(f"[!] Lỗi: {e}")
            return "error"
        finally:
            await browser.close()

    return "win_cycle"


async def main():
    cycle = 1
    while True:
        print("\n" + "=" * 60)
        print(f"  BẮT ĐẦU VÒNG LẶP THỨ {cycle}")
        print("=" * 60)

        try:
            result = await run_boss_bot()
        except Exception as e:
            print(f"[!] Lỗi ngoài: {e}")
            result = "error"

        if result == "lose":
            wait = DELAY_AFTER_LOSE
            print(f"\n[⏳] Thua / đang cooldown. Nghỉ {wait // 60} phút rồi thử lại...")
        elif result == "error":
            wait = DELAY_AFTER_ERROR
            print(f"\n[⏳] Có lỗi. Nghỉ {wait // 60} phút rồi thử lại...")
        else:
            wait = DELAY_AFTER_WIN
            print(f"\n[⏳] Hoàn thành vòng. Nghỉ {wait} giây rồi chạy tiếp...")

        await asyncio.sleep(wait)
        cycle += 1


if __name__ == "__main__":
    asyncio.run(main())