import logging
import random

from colorama import Fore, Style

from GramAddict.core.session_state import SessionState

logger = logging.getLogger(__name__)


def _humanized_scroll_down(device):
    # Same as bot_flow._humanized_scroll but strictly downward
    info = device.get_info()
    w, h = info.get("displayWidth", 1080), info.get("displayHeight", 2400)
    start_x = int(w * 0.8) + device.cm_to_pixels(random.uniform(-0.3, 0.3))
    start_y = int(h * 0.7) + device.cm_to_pixels(random.uniform(-0.5, 0.5))
    end_y = int(h * 0.2) + device.cm_to_pixels(random.uniform(-0.5, 0.5))
    duration = random.uniform(0.08, 0.12)
    device.swipe(start_x, start_y, start_x, end_y, duration)
    from GramAddict.core.utils import random_sleep

    random_sleep(0.8, 1.5)


def _run_zero_latency_unfollow_loop(
    device, zero_engine, nav_graph, configs, session_state, current_target, cognitive_stack
):
    """
    Executes the autonomous Unfollow logic in the Zero-Latency architecture.
    Assumes the bot is already at the "FollowingList" UI state.
    """
    logger.info(
        f"🧠 [Unfollow Engine] Initiating cleanup routine in {current_target}...",
        extra={"color": f"{Style.BRIGHT}{Fore.CYAN}"},
    )

    telepathic = cognitive_stack.get("telepathic")
    dopamine = cognitive_stack.get("dopamine")

    unfollow_limit = int(getattr(configs.args, "total_unfollows_limit", 50))
    failed_scrolls = 0
    total_unfollowed_this_session = 0

    from GramAddict.core.bot_flow import _humanized_click
    from GramAddict.core.utils import random_sleep

    # Initialize basic tuple if it's missing (helps with tests and initializations)
    if not hasattr(session_state, "totalUnfollowed"):
        session_state.totalUnfollowed = 0

    while not dopamine.is_app_session_over():
        # Check global limit tuple logic
        limit_val = session_state.check_limit(SessionState.Limit.UNFOLLOWS)
        if isinstance(limit_val, tuple) and limit_val[0]:
            logger.info("🛑 Unfollow limit reached for session. Yielding control.")
            return "BOREDOM_CHANGE_FEED"
        elif limit_val is True:
            logger.info("🛑 Unfollow limit reached for session. Yielding control.")
            return "BOREDOM_CHANGE_FEED"

        if total_unfollowed_this_session >= unfollow_limit:
            logger.info("🛑 Configured unfollow limit reached. Yielding control.")
            return "BOREDOM_CHANGE_FEED"

        try:
            xml_dump = device.dump_hierarchy()

            # ── Perimeter Guard: Verify we're still inside Instagram ──
            if xml_dump:
                import re

                unfollow_packages = set(re.findall(r'package="([^"]+)"', xml_dump))
                unfollow_app_id = getattr(device, "app_id", "com.instagram.android")
                if unfollow_packages and unfollow_app_id not in unfollow_packages:
                    logger.error(
                        f"🚨 [UnfollowLoop] FOREIGN APP DETECTED! Packages: {unfollow_packages}. Aborting loop."
                    )
                    device.press("back")
                    random_sleep(1.0, 1.5)
                    return "CONTEXT_LOST"

            # Autonomously identify user rows via Semantic Extraction
            telepathic = cognitive_stack.get("telepathic")
            nodes = []
            if telepathic:
                nodes = telepathic._extract_semantic_nodes(
                    xml_dump, "List item containing a user profile image, username, and following/following button"
                )
            else:
                logger.warning("No telepathic engine found, skipping semantic extraction.")

            action_taken = False
            for node in nodes:
                if node.get("skip") or not node.get("bounds"):
                    continue

                # 1. Tap the profile row to navigate to their page
                _humanized_click(device, node["x"], node["y"])
                action_taken = True
                logger.debug(f"👆 Tapped profile row at ({node['x']}, {node['y']})")

                # Wait for profile to load
                random_sleep(1.5, 2.5)
                profile_xml = device.dump_hierarchy()

                # 2. Close Friend Guard
                profile_text = profile_xml.lower()
                if "close friend" in profile_text:
                    logger.info(
                        "💚 [Anti-Friend] Profile is a Close Friend. Skipping unfollow.", extra={"color": Fore.GREEN}
                    )
                    device.back()
                    random_sleep(0.8, 1.5)
                    break  # Go next in loop

                # 3. Resonance Evaluation
                resonance = cognitive_stack.get("resonance")
                res_score = 0.5
                if resonance:
                    # Parse the description from the XML (rough pass, ResonanceEngine handles noise)
                    res_score = resonance.calculate_resonance({"description": profile_xml})

                # 4. Decision: If < 0.4, Unfollow. Else Keep.
                if res_score < 0.4:
                    logger.info(
                        f"🗑️ [Smart Cleanup] Resonance is low ({res_score:.2f}). Unfollowing.",
                        extra={"color": Fore.YELLOW},
                    )

                    # Find 'Following' button on their profile
                    following_nodes = telepathic._extract_semantic_nodes(
                        profile_xml, "find 'Following' button", threshold=0.7
                    )
                    if following_nodes and not following_nodes[0].get("skip"):
                        f_node = following_nodes[0]
                        _humanized_click(device, f_node["x"], f_node["y"])
                        random_sleep(1.0, 2.0)

                        # Find 'Unfollow' confirm
                        confirm_xml = device.dump_hierarchy()
                        confirm_nodes = telepathic._extract_semantic_nodes(
                            confirm_xml, "find 'Unfollow' confirmation button", threshold=0.8
                        )

                        if confirm_nodes and not confirm_nodes[0].get("skip"):
                            c_node = confirm_nodes[0]
                            _humanized_click(device, c_node["x"], c_node["y"])
                            random_sleep(0.8, 1.5)

                        logger.info("✅ [Unfollow Engine] Unfollowed a user.", extra={"color": Fore.GREEN})
                        session_state.totalUnfollowed += 1
                        total_unfollowed_this_session += 1
                        failed_scrolls = 0
                        dopamine.boredom += random.uniform(1.0, 3.0)
                else:
                    logger.info(
                        f"✨ [Smart Cleanup] Resonance is high ({res_score:.2f}). Keeping subscription.",
                        extra={"color": Fore.MAGENTA},
                    )
                    failed_scrolls = 0

                # 5. Always return to the Following list
                device.back()
                random_sleep(1.0, 2.0)
                break

            if not action_taken:
                # No following buttons in view, scroll down to find more
                _humanized_scroll_down(device)
                dopamine.boredom += 0.5
                failed_scrolls += 1

                if failed_scrolls > 5:
                    logger.warning(
                        "⚠️ [Unfollow Engine] No 'Following' buttons found after multiple scrolls. Aborting or reaching bottom."
                    )
                    return "BOREDOM_CHANGE_FEED"

            if dopamine.wants_to_change_feed():
                logger.info("🧠 [Unfollow Engine] Desire to clean up following list satisfied. Navigating elsewhere.")
                return "BOREDOM_CHANGE_FEED"

        except Exception as e:
            logger.error(f"⚠️ [Anomaly Handler] Exception in Unfollow Loop: {e}")
            _humanized_scroll_down(device)
            failed_scrolls += 1
            if failed_scrolls > 3:
                return "CONTEXT_LOST"

    return "FEED_EXHAUSTED"
