"""
Independent Adversarial Stress Test Suite for FreeExile PC Desktop Web Client.
Conducted by reviewer_18_3 (Lead Client Re-Reviewer & Adversarial Critic).
"""
import sys
import socketserver
import threading
from pathlib import Path

PROJECT_ROOT = Path(__file__).resolve().parent.parent.parent.parent
sys.path.insert(0, str(PROJECT_ROOT))
from tools.serve_web_pc import FreeExilePCRequestHandler
from playwright.sync_api import sync_playwright


class SilentPCServer(FreeExilePCRequestHandler):
    def log_message(self, format, *args):
        pass


def run_adversarial_stress():
    server = socketserver.TCPServer(("127.0.0.1", 0), SilentPCServer)
    port = server.server_address[1]
    threading.Thread(target=server.serve_forever, daemon=True).start()
    base_url = f"http://127.0.0.1:{port}"

    try:
        with sync_playwright() as p:
            try:
                browser = p.chromium.launch(channel="msedge", headless=True)
            except Exception:
                browser = p.chromium.launch(headless=True)
            page = browser.new_page(viewport={"width": 1920, "height": 1080})
            page.add_init_script("try { localStorage.setItem('fe_sim_mode', 'fullscreen'); } catch(err){}")

            errors = []
            page.on("pageerror", lambda err: errors.append(f"PAGE_ERR: {err}"))
            page.on("console", lambda m: errors.append(f"CONSOLE_ERR: {m.text}") if m.type == "error" and "favicon" not in m.text else None)

            page.goto(f"{base_url}/index.html")
            page.wait_for_function("() => window.player && window.PcInputController")

            # Stress Test 1: Rapid Space hammering (10 times in 100ms)
            for _ in range(10):
                page.keyboard.press("Space")
                page.wait_for_timeout(10)

            charges_hamm = page.evaluate("() => window.skillBarController?.slots?.get('dodge')?.charges")
            print(f"Charges after 10 rapid space taps during iframe: {charges_hamm}")
            assert charges_hamm == 2, f"Expected 2 charges after hammering space during iframe, got {charges_hamm}"

            # Stress Test 2: Wait for i-frame to expire, then check charges and errors
            page.wait_for_timeout(350)
            assert len(errors) == 0, f"Errors after hammer: {errors}"

            # Stress Test 3: Interleaved rapid skills and flasks
            for key in ["1", "KeyQ", "2", "KeyW", "3", "KeyE", "4", "KeyR", "5"]:
                page.keyboard.press(key)
                page.wait_for_timeout(15)

            assert len(errors) == 0, f"Errors after rapid skill/flask fire: {errors}"

            # Stress Test 4: Dynamic reactive i18n
            txt_vi = page.locator("#txt-char-name").inner_text()
            page.select_option("#lang-select", "en")
            page.wait_for_timeout(50)
            txt_en = page.locator("#txt-char-name").inner_text()
            page.select_option("#lang-select", "zh")
            page.wait_for_timeout(50)
            txt_zh = page.locator("#txt-char-name").inner_text()
            page.select_option("#lang-select", "vi")
            page.wait_for_timeout(50)
            print(f'i18n check: VI="{txt_vi}", EN="{txt_en}", ZH="{txt_zh}"')
            assert txt_vi != txt_en or txt_en != txt_zh, "i18n did not translate #txt-char-name in-place"

            # Stress Test 5: Dynamic modal opening and dual-docking
            page.keyboard.press("KeyC")
            page.wait_for_timeout(50)
            page.keyboard.press("KeyI")
            page.wait_for_timeout(50)
            c_box = page.locator("#modal-character").bounding_box()
            b_box = page.locator("#modal-bag").bounding_box()
            print(f"Character modal box: {c_box}")
            print(f"Inventory modal box: {b_box}")
            assert c_box is not None and b_box is not None
            # Verify left vs right side-by-side
            assert c_box["x"] < b_box["x"], f'Character modal (x={c_box["x"]}) must be to the left of bag modal (x={b_box["x"]})'
            assert c_box["x"] + c_box["width"] < b_box["x"], "Modals must not overlap horizontally!"

            # Stress Test 6: Escape closes modals one by one until none remain, then toggles pause
            while page.evaluate("() => document.querySelectorAll('#modal-container > div:not(.hidden), #modal-item-link-tooltip:not(.hidden)').length > 0"):
                page.keyboard.press("Escape")
                page.wait_for_timeout(50)
            
            # Now with zero open modals, press Escape to trigger Pause
            page.keyboard.press("Escape")
            page.wait_for_timeout(50)
            is_paused = page.evaluate("() => window.isGamePaused")
            print(f"Game paused state after clearing modals and pressing Esc: {is_paused}")
            assert is_paused is True, "Pause overlay must be active after closing modals and pressing Esc"

            # Press Escape once more to unpause
            page.keyboard.press("Escape")
            page.wait_for_timeout(50)
            is_unpaused = page.evaluate("() => window.isGamePaused")
            print(f"Game paused state after unpausing with Esc: {is_unpaused}")
            assert is_unpaused is False, "Pause overlay must dismiss when pressing Esc again"

            page.close()
            browser.close()
            print("ALL ADVERSARIAL RUNTIME STRESS TESTS PASSED CLEANLY!")
    finally:
        server.shutdown()
        server.server_close()


if __name__ == "__main__":
    run_adversarial_stress()
