"""Tests for ProjectConfig inheritance from UserConfig."""

import tempfile
from pathlib import Path

import pytest
import tomli_w

from src.fwauto.config import ProjectConfig, ConfigError
from src.fwauto.user_config import UserConfig


@pytest.fixture
def temp_home(monkeypatch):
    """Create a temporary home directory for testing."""
    with tempfile.TemporaryDirectory() as tmpdir:
        monkeypatch.setenv("HOME", tmpdir)
        # Monkey-patch Path.home() to return the temp directory
        monkeypatch.setattr(Path, "home", lambda: Path(tmpdir))
        yield Path(tmpdir)


def test_sdk_path_inheritance(temp_home):
    """測試 SDK 路徑從 User Config 繼承"""
    # Setup User Config
    user_config = UserConfig()
    user_config.set_sdk_config("stm32_keil", {"type": "keil", "path": "C:\\Keil_v5"})

    # Setup Project Config
    with tempfile.TemporaryDirectory() as tmpdir:
        project_root = Path(tmpdir)
        (project_root / ".fwauto").mkdir()
        config_path = project_root / ".fwauto" / "config.toml"

        with open(config_path, "wb") as f:
            tomli_w.dump({"sdk": {"type": "stm32_keil"}}, f)

        config = ProjectConfig(config_path)
        assert config.sdk_path == "C:\\Keil_v5"


def test_sdk_path_project_override(temp_home):
    """測試 Project Config 可以覆寫 SDK 路徑"""
    # Setup User Config
    user_config = UserConfig()
    user_config.set_sdk_config("stm32_keil", {"type": "keil", "path": "C:\\Keil_v5"})

    # Setup Project Config with override
    with tempfile.TemporaryDirectory() as tmpdir:
        project_root = Path(tmpdir)
        (project_root / ".fwauto").mkdir()
        config_path = project_root / ".fwauto" / "config.toml"

        with open(config_path, "wb") as f:
            tomli_w.dump({"sdk": {"type": "stm32_keil", "path": "D:\\Custom\\Keil"}}, f)

        config = ProjectConfig(config_path)
        # Project Scope 的路徑應該優先於 User Scope
        assert config.sdk_path == "D:\\Custom\\Keil"


def test_device_properties(temp_home):
    """測試 device_family 和 device_model properties"""
    with tempfile.TemporaryDirectory() as tmpdir:
        project_root = Path(tmpdir)
        (project_root / ".fwauto").mkdir()
        config_path = project_root / ".fwauto" / "config.toml"

        with open(config_path, "wb") as f:
            tomli_w.dump({"device": {"family": "stm32f4", "model": "STM32F407VGT6"}}, f)

        config = ProjectConfig(config_path)
        assert config.device_family == "stm32f4"
        assert config.device_model == "STM32F407VGT6"


def test_sdk_type_property(temp_home):
    """測試 sdk_type property"""
    with tempfile.TemporaryDirectory() as tmpdir:
        project_root = Path(tmpdir)
        (project_root / ".fwauto").mkdir()
        config_path = project_root / ".fwauto" / "config.toml"

        with open(config_path, "wb") as f:
            tomli_w.dump({"sdk": {"type": "stm32_keil"}}, f)

        config = ProjectConfig(config_path)
        assert config.sdk_type == "stm32_keil"


def test_sdk_path_no_user_config(temp_home):
    """測試沒有 User Config 時的行為"""
    with tempfile.TemporaryDirectory() as tmpdir:
        project_root = Path(tmpdir)
        (project_root / ".fwauto").mkdir()
        config_path = project_root / ".fwauto" / "config.toml"

        with open(config_path, "wb") as f:
            tomli_w.dump({"sdk": {"type": "stm32_keil"}}, f)

        config = ProjectConfig(config_path)
        # 沒有 User Config，應該返回 None
        assert config.sdk_path is None


def test_deployment_config_inheritance(temp_home):
    """測試 deployment config 從 User Config 繼承"""
    # Setup User Config
    user_config = UserConfig()
    user_config.set_deployment_config(
        "am62x",
        {
            "board_ip": "192.168.1.100",
            "board_user": "admin",
            "deploy_path": "/tmp/test",
            "ssh_options": "-o ConnectTimeout=10",
        },
    )

    # Setup Project Config
    with tempfile.TemporaryDirectory() as tmpdir:
        project_root = Path(tmpdir)
        (project_root / ".fwauto").mkdir()
        config_path = project_root / ".fwauto" / "config.toml"

        with open(config_path, "wb") as f:
            tomli_w.dump({"sdk": {"type": "am62x"}}, f)

        config = ProjectConfig(config_path)
        assert config.board_ip == "192.168.1.100"
        assert config.board_user == "admin"
        assert config.deploy_path == "/tmp/test"
        assert config.ssh_options == "-o ConnectTimeout=10"


def test_deployment_config_project_override(temp_home):
    """測試 Project Config 可以覆寫 deployment config"""
    # Setup User Config
    user_config = UserConfig()
    user_config.set_deployment_config(
        "am62x",
        {
            "board_ip": "192.168.1.100",
            "board_user": "admin",
            "deploy_path": "/tmp/test",
            "ssh_options": "-o ConnectTimeout=10",
        },
    )

    # Setup Project Config with override
    with tempfile.TemporaryDirectory() as tmpdir:
        project_root = Path(tmpdir)
        (project_root / ".fwauto").mkdir()
        config_path = project_root / ".fwauto" / "config.toml"

        with open(config_path, "wb") as f:
            tomli_w.dump(
                {
                    "sdk": {"type": "am62x"},
                    "deployment": {
                        "am62x": {
                            "board_ip": "192.168.2.200",
                            "board_user": "root",
                            "deploy_path": "/home/root",
                        }
                    },
                },
                f,
            )

        config = ProjectConfig(config_path)
        # Project Scope 應該優先於 User Scope
        assert config.board_ip == "192.168.2.200"
        assert config.board_user == "root"
        assert config.deploy_path == "/home/root"


def test_deployment_config_defaults(temp_home):
    """測試沒有 deployment config 時會拋出 ConfigError"""
    with tempfile.TemporaryDirectory() as tmpdir:
        project_root = Path(tmpdir)
        (project_root / ".fwauto").mkdir()
        config_path = project_root / ".fwauto" / "config.toml"

        with open(config_path, "wb") as f:
            tomli_w.dump({"sdk": {"type": "am62x"}}, f)

        config = ProjectConfig(config_path)
        # 沒有配置 board_ip 時應該拋出 ConfigError
        with pytest.raises(ConfigError) as exc_info:
            _ = config.board_ip
        assert "board_ip not configured" in str(exc_info.value)


def test_get_scenarios(temp_home):
    """測試從 Project Config 載入 scenarios"""
    with tempfile.TemporaryDirectory() as tmpdir:
        project_root = Path(tmpdir)
        (project_root / ".fwauto").mkdir()
        config_path = project_root / ".fwauto" / "config.toml"

        config_data = {
            "sdk": {"type": "am62x"},
            "scenarios": [
                {"name": "led-on", "description": "Turn on LED", "binary_args": "on"},
                {"name": "led-off", "description": "Turn off LED", "binary_args": "off"},
            ],
        }

        with open(config_path, "wb") as f:
            tomli_w.dump(config_data, f)

        config = ProjectConfig(config_path)
        scenarios = config.get_scenarios()

        assert len(scenarios) == 2
        assert scenarios[0].name == "led-on"
        assert scenarios[0].binary_args == "on"
        assert scenarios[1].name == "led-off"
        assert scenarios[1].binary_args == "off"


def test_get_scenarios_empty(temp_home):
    """測試沒有 scenarios 時返回空列表"""
    with tempfile.TemporaryDirectory() as tmpdir:
        project_root = Path(tmpdir)
        (project_root / ".fwauto").mkdir()
        config_path = project_root / ".fwauto" / "config.toml"

        with open(config_path, "wb") as f:
            tomli_w.dump({"sdk": {"type": "am62x"}}, f)

        config = ProjectConfig(config_path)
        scenarios = config.get_scenarios()

        assert scenarios == []


def test_get_scenario_manager(temp_home):
    """測試建立 ScenarioManager"""
    with tempfile.TemporaryDirectory() as tmpdir:
        project_root = Path(tmpdir)
        (project_root / ".fwauto").mkdir()
        config_path = project_root / ".fwauto" / "config.toml"

        config_data = {
            "sdk": {"type": "am62x"},
            "scenarios": [
                {"name": "test", "description": "Test", "binary_args": "--test"},
            ],
        }

        with open(config_path, "wb") as f:
            tomli_w.dump(config_data, f)

        config = ProjectConfig(config_path)
        manager = config.get_scenario_manager()

        # 驗證 manager 可以正確查詢 scenario
        scenario = manager.get_scenario("test")
        assert scenario is not None
        assert scenario.name == "test"
        assert scenario.binary_args == "--test"
