"""
E2E: Account Switcher Regression
===================================
PRODUCTION BUG 2026-04-30 11:50:
Bot was on OTHER_PROFILE (ehsan.nura). Account switcher called
telepath.find_best_node(xml, "tap profile tab") which returned the
BACK BUTTON (id: action_bar_button_back, desc: Back) instead of the
actual profile tab in the bottom tab bar.

This caused:
1. Bot navigated away from OwnProfile instead of opening account selector
2. Account switcher couldn't find target account in bottom sheet
3. Session halted: "Cannot verify or switch to target account"

Root cause: VLM confused "profile tab" with "Back" button because
Back is more visually prominent on OTHER_PROFILE screens.

Mock: ONLY the device (XML dumps).
Real: Cognitive stack, PluginRegistry, SessionState, Config.
"""

import os
import xml.etree.ElementTree as ET

E2E_FIXTURES_DIR = os.path.join(os.path.dirname(__file__), "fixtures")
FIXTURES_DIR = os.path.join(os.path.dirname(os.path.dirname(__file__)), "fixtures")


def _load_fixture(name, e2e=False):
    base = E2E_FIXTURES_DIR if e2e else FIXTURES_DIR
    with open(os.path.join(base, name), "r", encoding="utf-8") as f:
        return f.read()


def _extract_tab_bar_nodes(xml_str):
    """Extract only nodes that are in the bottom tab bar."""
    import re

    clean_xml = re.sub(r"<\?xml.*?\?>", "", xml_str).strip()
    root = ET.fromstring(clean_xml)

    tab_nodes = []
    for elem in root.iter("node"):
        res_id = elem.attrib.get("resource-id", "")
        content_desc = elem.attrib.get("content-desc", "")
        bounds = elem.attrib.get("bounds", "")

        # Tab bar nodes have specific resource-ids and are at the bottom
        if "tab_bar" in res_id or "tab_icon" in res_id:
            tab_nodes.append({
                "resource-id": res_id,
                "content-desc": content_desc,
                "text": elem.attrib.get("text", ""),
                "bounds": bounds,
                "clickable": elem.attrib.get("clickable", "false"),
            })

        # Profile tab specifically
        if "profile" in content_desc.lower() and "tab" in content_desc.lower():
            tab_nodes.append({
                "resource-id": res_id,
                "content-desc": content_desc,
                "text": elem.attrib.get("text", ""),
                "bounds": bounds,
                "clickable": elem.attrib.get("clickable", "false"),
            })

    return tab_nodes


def test_other_profile_has_back_button_and_profile_tab():
    """
    STRUCTURAL GUARD: On OTHER_PROFILE, both a Back button AND a profile
    tab must exist. If our XML fixture doesn't have both, we can't test
    the confusion bug.
    """
    xml = _load_fixture("other_profile_real.xml", e2e=True)

    has_back = "action_bar_button_back" in xml or 'content-desc="Back"' in xml
    has_profile_tab = "profile_tab" in xml or 'content-desc="Profile"' in xml

    assert has_back, (
        "other_profile_real.xml is missing the Back button — "
        "cannot reproduce the VLM confusion bug"
    )
    # Note: if profile tab is missing from fixture, the bug is even worse
    # because there's nothing correct for the VLM to find


def test_account_switcher_navigates_to_own_profile_first():
    """
    The account_switcher.verify_and_switch_account() MUST first navigate
    to OwnProfile before checking identity. If it starts on OTHER_PROFILE,
    the nav must happen first.
    """
    import inspect
    from GramAddict.core.account_switcher import verify_and_switch_account

    source = inspect.getsource(verify_and_switch_account)

    # The function must call navigate_to("OwnProfile") BEFORE
    # calling find_best_node for profile tab
    nav_pos = source.find('navigate_to("OwnProfile"')
    assert nav_pos >= 0, (
        "account_switcher does not navigate to OwnProfile — "
        "it will try to switch from arbitrary screens!"
    )


def test_back_button_is_not_profile_tab():
    """
    STRUCTURAL ASSERTION: The Back button (action_bar_button_back)
    must NEVER be considered a valid match for "tap profile tab".

    This is the exact bug: VLM returned Back button for "tap profile tab"
    which navigated away instead of opening the account selector.
    """
    xml = _load_fixture("other_profile_real.xml", e2e=True)

    import re

    clean_xml = re.sub(r"<\?xml.*?\?>", "", xml).strip()
    root = ET.fromstring(clean_xml)

    back_buttons = []
    profile_tabs = []

    for elem in root.iter("node"):
        res_id = elem.attrib.get("resource-id", "")
        desc = elem.attrib.get("content-desc", "")
        bounds = elem.attrib.get("bounds", "")

        if "action_bar_button_back" in res_id or desc == "Back":
            back_buttons.append({"id": res_id, "desc": desc, "bounds": bounds})

        if "profile" in desc.lower() and elem.attrib.get("selected", "false") == "true":
            profile_tabs.append({"id": res_id, "desc": desc, "bounds": bounds})

    assert len(back_buttons) > 0, (
        "No Back button found in OTHER_PROFILE XML — fixture is incomplete"
    )

    # The back button bounds must be in the TOP of the screen (action bar)
    # while profile tab must be at the BOTTOM (tab bar)
    for back in back_buttons:
        coords = re.findall(r"\d+", back["bounds"])
        if len(coords) >= 4:
            back_top = int(coords[1])
            assert back_top < 500, (
                f"Back button at y={back_top} — expected top of screen! "
                "If this is in the tab bar, the VLM confusion is structural."
            )
