import os
import json
import logging

from target_simulator.utils.config_manager import ConfigManager
from target_simulator.utils.logger import apply_saved_logger_levels


def _prefs_path(cfg: ConfigManager) -> str:
    return os.path.join(os.path.dirname(cfg.filepath), "logger_prefs.json")


def test_apply_saved_logger_levels_from_prefs_file(tmp_path):
    cfg = ConfigManager()
    settings_path = cfg.filepath
    prefs = {"saved_levels": {"test.logger.persistence": "DEBUG"}}
    prefs_path = _prefs_path(cfg)

    # Backup existing settings.json and prefs if present
    if os.path.exists(settings_path):
        with open(settings_path, "r", encoding="utf-8") as f:
            orig_settings = f.read()
    else:
        orig_settings = None

    if os.path.exists(prefs_path):
        with open(prefs_path, "r", encoding="utf-8") as f:
            orig_prefs = f.read()
    else:
        orig_prefs = None

    try:
        # Ensure the logger starts at INFO
        lg = logging.getLogger("test.logger.persistence")
        lg.setLevel(logging.INFO)

        # Write prefs file and apply
        with open(prefs_path, "w", encoding="utf-8") as f:
            json.dump(prefs, f, indent=2)

        apply_saved_logger_levels()

        # After applying, the logger should be DEBUG
        assert logging.getLogger("test.logger.persistence").level == logging.DEBUG

        # Now change prefs to WARNING and re-apply
        prefs["saved_levels"]["test.logger.persistence"] = "WARNING"
        with open(prefs_path, "w", encoding="utf-8") as f:
            json.dump(prefs, f, indent=2)

        apply_saved_logger_levels()
        assert logging.getLogger("test.logger.persistence").level == logging.WARNING

    finally:
        # Restore original files
        if orig_settings is not None:
            with open(settings_path, "w", encoding="utf-8") as f:
                f.write(orig_settings)
        if orig_prefs is not None:
            with open(prefs_path, "w", encoding="utf-8") as f:
                f.write(orig_prefs)
        else:
            try:
                if os.path.exists(prefs_path):
                    os.remove(prefs_path)
            except Exception:
                pass


def test_apply_saved_logger_levels_fallback_to_settings(tmp_path):
    cfg = ConfigManager()
    settings_path = cfg.filepath
    prefs_path = _prefs_path(cfg)

    # Backup
    if os.path.exists(settings_path):
        with open(settings_path, "r", encoding="utf-8") as f:
            orig_settings = f.read()
    else:
        orig_settings = None
    if os.path.exists(prefs_path):
        with open(prefs_path, "r", encoding="utf-8") as f:
            orig_prefs = f.read()
    else:
        orig_prefs = None

    try:
        # Remove prefs file to force fallback
        if os.path.exists(prefs_path):
            os.remove(prefs_path)

        # Prepare settings.json general.logger_panel
        cfg_gen = cfg.get_general_settings() or {}
        cfg_gen["logger_panel"] = {"saved_levels": {"test.logger.fallback": "ERROR"}}
        cfg.save_general_settings(cfg_gen)

        # Ensure logger initial level is lower
        logging.getLogger("test.logger.fallback").setLevel(logging.DEBUG)

        apply_saved_logger_levels()

        assert logging.getLogger("test.logger.fallback").level == logging.ERROR

    finally:
        # Restore originals
        if orig_settings is not None:
            with open(settings_path, "w", encoding="utf-8") as f:
                f.write(orig_settings)
        if orig_prefs is not None:
            with open(prefs_path, "w", encoding="utf-8") as f:
                f.write(orig_prefs)
        else:
            try:
                if os.path.exists(prefs_path):
                    os.remove(prefs_path)
            except Exception:
                pass
