import asyncio
import os
import ctypes
import time
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)
except Exception:
pass

hide_console()

# -------------------------------------------------------------
# CẤU HÌNH CÀI ĐẶT
# -------------------------------------------------------------
BASE_DIR = os.path.dirname(os.path.abspath(__file__))
ACCOUNTS_FILE = os.path.join(BASE_DIR, "accounts.txt")
INTERVAL_SECONDS = 1 * 60 * 60 # 1 giờ
HEADLESS = True # Chạy ẩn trình duyệt
# -------------------------------------------------------------

def load_accounts(file_path):
accounts = []
if not os.path.exists(file_path):
print(f"[-] File {file_path} không tồn tại!")
return accounts
with open(file_path, "r", encoding="utf-8") as f:
for line in f:
line = line.strip()
if "|" in line and not line.startswith("#"):
user, pwd = line.split("|", 1)
accounts.append((user.strip(), pwd.strip()))
return accounts


async def safe_goto(page, url, retries=3):
"""Hàm truy cập URL an toàn với cơ chế thử lại khi gặp lỗi mạng."""
for attempt in range(1, retries + 1):
try:
await page.goto(url, wait_until="domcontentloaded", timeout=60000)
return True
except Exception as e:
print(f" [!] Lỗi tải trang ({attempt}/{retries}): {e}")
if attempt < retries:
await asyncio.sleep(2)
else:
raise e


async def run_automation():
accounts = load_accounts(ACCOUNTS_FILE)
if not accounts:
print("[-] Danh sách tài khoản trống!")
return

async with async_playwright() as p:
browser = await p.chromium.launch(headless=HEADLESS)

for username, password in accounts:
print("\n==========================================")
print(f"[*] Đang xử lý tài khoản: {username}")
context = await browser.new_context()
page = await context.new_page()

page.set_default_timeout(60000)
page.set_default_navigation_timeout(60000)

try:
# 1. ĐĂNG NHẬP
print("[1] Mở trang đăng nhập...")
await safe_goto(page, "https://1900.fun/login.php")
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(1500)

# 2. THU HOẠCH VƯỜN
print("[2] Thu hoạch nông trại...")
await safe_goto(page, "https://1900.fun/nongtrai/index.php?harvest_all=1")
await page.wait_for_timeout(2000)

# 3. TỰ ĐỘNG CHỌN CÂY CẤP CAO NHẤT VÀ GIEO HẠT
print("[3] Kiểm tra cấp độ nông trại và chọn cây trồng phù hợp...")
await safe_goto(page, "https://1900.fun/nongtrai/index.php")

best_crop = await page.evaluate("""() => {
if (typeof cropsData !== 'undefined' && typeof userLevel !== 'undefined') {
const availableCrops = cropsData.filter(c => c.level_required <= userLevel);
if (availableCrops.length > 0) {
availableCrops.sort((a, b) => b.level_required - a.level_required);
return availableCrops[0];
}
}
return null;
}""")

if best_crop and await page.locator("#quickPlantForm").count() > 0:
crop_id = str(best_crop['id'])
crop_name = best_crop['name']
req_lvl = best_crop['level_required']

print(f" -> Cây phù hợp nhất: {crop_name} (ID: {crop_id} - Yêu cầu Cấp {req_lvl})")
print(f" -> Tiến hành gieo hạt nhanh {crop_name}...")

await page.evaluate(f"document.getElementById('quickCropId').value = '{crop_id}';")
async with page.expect_navigation(wait_until="domcontentloaded"):
await page.eval_on_selector("#quickPlantForm", "form => form.submit()")
await page.wait_for_timeout(2000)
else:
print(" -> Không tìm thấy thông tin cây trồng phù hợp hoặc form gieo hạt.")

# 4. BÁN TẤT CẢ CÁ
print("[4] Bán tất cả cá...")
await safe_goto(page, "https://1900.fun/nongtrai/hoca.php?sell_all_fish=1")
await page.wait_for_timeout(2000)

# 5. TỰ ĐỘNG CHỌN CÁ CẤP CAO NHẤT VÀ MUA MỚI
print("[5] Kiểm tra cấp độ và mua loại cá phù hợp nhất...")
await safe_goto(page, "https://1900.fun/nongtrai/hoca.php")

fish_info = await page.evaluate("""() => {
const el = document.querySelector('.pond-level-box span:last-child');
if (el) {
const match = el.innerText.match(/(\\d+)\\/(\\d+)/);
if (match) {
return { current: parseInt(match[1]), max: parseInt(match[2]) };
}
}
return { current: 0, max: 2 };
}""")

needed_fish = fish_info['max'] - fish_info['current']

if needed_fish > 0:
best_fish = await page.evaluate("""() => {
if (typeof fishList !== 'undefined' && typeof userLevel !== 'undefined' && typeof userMoney !== 'undefined') {
const available = fishList.filter(f => f.level_required <= userLevel && f.price <= userMoney);
if (available.length > 0) {
available.sort((a, b) => b.level_required - a.level_required);
return available[0];
}
}
return null;
}""")

if best_fish:
fish_id = str(best_fish['id'])
fish_name = best_fish.get('name', 'Cá')
print(f" -> Hồ hiện tại: {fish_info['current']}/{fish_info['max']}. Mua cá: {fish_name} (ID: {fish_id})")

for i in range(needed_fish):
print(f" -> Đang mua con thứ {i + 1}/{needed_fish}...")
await page.evaluate(f"""() => {{
document.getElementById('buyFishType').value = '{fish_id}';
}}""")
async with page.expect_navigation(wait_until="domcontentloaded"):
await page.eval_on_selector("#buyForm", "form => form.submit()")
await page.wait_for_timeout(1500)
else:
print(" -> Không tìm thấy loại cá phù hợp hoặc không đủ Xu để mua.")
else:
print(f" -> Hồ đã đầy ({fish_info['current']}/{fish_info['max']} con), không cần mua thêm.")

# 6. ĐĂNG XUẤT
print("[6] Đăng xuất...")
await safe_goto(page, "https://1900.fun/logout.php")
await page.wait_for_timeout(1500)
print(f"[+] Hoàn tất cho: {username}")

except Exception as e:
print(f"[-] Có lỗi xảy ra đối với {username}: {e}")
finally:
await context.close()
await asyncio.sleep(2)

await browser.close()


if __name__ == "__main__":
while True:
try:
print(f"\n==================== [ BẮT ĐẦU VÒNG LẶP NÔNG TRẠI ] ====================")
asyncio.run(run_automation())
except Exception as err:
print(f"[!] Gặp lỗi ngoài dự kiến: {err}")

print(f"\n[⏳] Đã hoàn thành. Chờ 1 giờ ({INTERVAL_SECONDS}s) để chạy tiếp...")
time.sleep(INTERVAL_SECONDS)