import json
import os
from enum import Enum

import pytest

from target_simulator.utils.config_manager import ConfigManager


def _new_cm_with_tmpfile(tmp_path, filename="settings.json"):
    """Create a ConfigManager but point its filepath to a temp file and reload settings."""
    cm = ConfigManager(filename=filename)
    cm.filepath = str(tmp_path / filename)
    cm._settings = cm._load_or_initialize_settings()
    return cm


def test_missing_file_defaults_and_save_creates_file(tmp_path):
    cm = _new_cm_with_tmpfile(tmp_path)

    # When the file is missing we should get empty default sections
    assert cm.get_general_settings() == {}
    assert cm.get_scenario_names() == []

    # Saving general settings should create the file
    cm.save_general_settings({"foo": "bar"})
    assert os.path.exists(cm.filepath)

    with open(cm.filepath, "r", encoding="utf-8") as f:
        data = json.load(f)

    assert data["general"]["foo"] == "bar"


def test_save_and_get_connection_settings(tmp_path):
    cm = _new_cm_with_tmpfile(tmp_path)

    conn = {"host": "127.0.0.1", "port": 12345}
    cm.save_connection_settings(conn)

    # Reload from disk via a fresh manager pointed at same file
    cm2 = _new_cm_with_tmpfile(tmp_path)
    with open(cm.filepath, "r", encoding="utf-8") as f:
        data = json.load(f)

    assert data["general"]["connection"] == conn
    assert cm.get_connection_settings() == conn
    assert cm2.get_connection_settings() == conn


def test_invalid_json_returns_defaults(tmp_path):
    p = tmp_path / "settings.json"
    p.write_text("{ invalid json }")

    cm = ConfigManager()
    cm.filepath = str(p)
    cm._settings = cm._load_or_initialize_settings()

    # Invalid JSON should be handled gracefully and result in defaults
    assert cm.get_general_settings() == {}
    assert cm.get_scenario_names() == []


def test_non_dict_settings_are_wrapped_into_general(tmp_path):
    p = tmp_path / "settings.json"
    p.write_text(json.dumps(["a", "b"]))

    cm = ConfigManager()
    cm.filepath = str(p)
    cm._settings = cm._load_or_initialize_settings()

    # If the top-level JSON is not a dict, the implementation wraps it into 'general'
    assert cm.get_general_settings() == ["a", "b"]


def test_save_and_delete_scenario(tmp_path):
    cm = _new_cm_with_tmpfile(tmp_path)

    cm.save_scenario("s1", {"a": 1})
    assert cm.get_scenario("s1") == {"a": 1}

    # Deleting removes it and persists change
    cm.delete_scenario("s1")
    assert cm.get_scenario("s1") is None


def test_enum_values_are_serialized_as_values(tmp_path):
    class Color(Enum):
        RED = "red"
        BLUE = "blue"

    cm = _new_cm_with_tmpfile(tmp_path)
    cm._settings = {"general": {"color": Color.RED}, "scenarios": {}}
    cm._save_settings()

    with open(cm.filepath, "r", encoding="utf-8") as f:
        data = json.load(f)

    # The Enum should be written using its .value via EnumEncoder
    assert data["general"]["color"] == "red"
import pytest
from target_simulator.utils.config_manager import ConfigManager


def test_config_manager_save_and_get_connection(tmp_path):
    cm = ConfigManager(filename=str(tmp_path / "settings.json"))
    conn_data = {"host": "127.0.0.1", "port": 1234}
    cm.save_connection_settings(conn_data)
    loaded = cm.get_connection_settings()
    assert loaded["host"] == "127.0.0.1"
    assert loaded["port"] == 1234


def test_config_manager_settings_direct(tmp_path):
    cm = ConfigManager(filename=str(tmp_path / "settings.json"))
    cm._settings["custom"] = {"foo": 42}
    cm._save_settings()
    cm2 = ConfigManager(filename=str(tmp_path / "settings.json"))
    assert cm2._settings["custom"]["foo"] == 42
