"""
Diagnostic XML Dumper for Project Singularity
==============================================
Automatically captures UI hierarchy snapshots when the bot encounters
problematic states. These dumps serve as future test fixtures for TDD.

Dumps are saved to `debug/xml_dumps/` with timestamped filenames
and a structured reason tag for easy triage.

Retention: Keeps the last 50 dumps per reason category to avoid disk bloat.
"""

import json
import logging
import os
from datetime import datetime

logger = logging.getLogger(__name__)

DUMP_DIR = os.path.join(os.path.dirname(os.path.dirname(os.path.dirname(__file__))), "debug", "xml_dumps")
MAX_DUMPS_PER_CATEGORY = 5


def dump_ui_state(device, reason: str, extra_context: dict = None):
    """
    Capture and save the current UI hierarchy and screenshot to disk for debugging.
    """
    try:
        os.makedirs(DUMP_DIR, exist_ok=True)

        # Capture hierarchy
        xml = device.dump_hierarchy()

        # Generate filename: reason__2026-04-13_17-41-39.xml
        ts = datetime.now().strftime("%Y-%m-%d_%H-%M-%S")
        safe_reason = reason.replace(" ", "_").replace("/", "_")[:40]
        filename = f"{safe_reason}__{ts}.xml"
        filepath = os.path.join(DUMP_DIR, filename)

        # Write XML
        with open(filepath, "w", encoding="utf-8") as f:
            f.write(xml)

        # Capture and write screenshot
        try:
            import base64

            screenshot_b64 = device.get_screenshot_b64()
            if screenshot_b64:
                screenshot_data = base64.b64decode(screenshot_b64)
                screenshot_path = filepath.replace(".xml", ".jpg")
                with open(screenshot_path, "wb") as f:
                    f.write(screenshot_data)
        except Exception as e:
            logger.debug(f"[Diagnostic] Could not capture screenshot: {e}")

        # Write companion metadata JSON
        meta = {
            "reason": reason,
            "timestamp": ts,
            "xml_file": filename,
            "screenshot_file": filename.replace(".xml", ".jpg"),
        }
        # Capture the session log if available
        try:
            import shutil

            from GramAddict.core.log import get_log_file_config

            log_name, log_dir, _, _ = get_log_file_config()
            if log_name and log_dir:
                active_log = os.path.join(log_dir, log_name)
                if os.path.exists(active_log):
                    log_dest = filepath.replace(".xml", ".log")
                    shutil.copy2(active_log, log_dest)
                    meta["log_file"] = os.path.basename(log_dest)
        except Exception as e:
            logger.debug(f"[Diagnostic] Could not capture session log: {e}")

        if extra_context:
            meta["context"] = extra_context

        meta_path = filepath.replace(".xml", ".meta.json")
        with open(meta_path, "w", encoding="utf-8") as f:
            json.dump(meta, f, indent=2, ensure_ascii=False)

        logger.info(f"📸 [Diagnostic] UI state, screenshot, and session log dumped for '{reason}': {filepath}")

        # Rotate old dumps for this category
        _rotate_dumps(safe_reason)

        return filepath

    except Exception as e:
        # Dumping must NEVER crash the bot
        logger.debug(f"[Diagnostic] Could not dump UI state: {e}")
        return None


def _rotate_dumps(category_prefix: str = None):
    """Keep only the last MAX_DUMPS_PER_CATEGORY dumps per category. If no category, cleans all."""
    try:
        if not os.path.exists(DUMP_DIR):
            return

        # Get all unique timestamps/prefixes
        all_files = os.listdir(DUMP_DIR)
        prefixes = set()
        for f in all_files:
            # Format is usually reason__timestamp.ext
            if "__" in f:
                prefix = f.split(".")[0]
                prefixes.add(prefix)

        # Group prefixes by category
        categories = {}
        for p in prefixes:
            parts = p.split("__")
            if len(parts) >= 2:
                cat = parts[0]
                if cat not in categories:
                    categories[cat] = []
                categories[cat].append(p)

        for cat, prefs in categories.items():
            if category_prefix and cat != category_prefix:
                continue

            prefs.sort()  # chronological
            if len(prefs) > MAX_DUMPS_PER_CATEGORY:
                prefs_to_remove = prefs[: len(prefs) - MAX_DUMPS_PER_CATEGORY]
                for p_rm in prefs_to_remove:
                    for ext in [".xml", ".jpg", ".log", ".meta.json"]:
                        fp = os.path.join(DUMP_DIR, p_rm + ext)
                        if os.path.exists(fp):
                            os.remove(fp)

        # Also clean orphaned files that don't match any known prefix pattern
        for f in all_files:
            if "__" not in f:
                fp = os.path.join(DUMP_DIR, f)
                if os.path.isfile(fp):
                    os.remove(fp)

    except Exception as e:
        logger.debug(f"[Diagnostic] Error during dump rotation: {e}")
