"""Tests for proxym.virt._vm_config — VM configuration injection, templates, keys."""

from __future__ import annotations

import json
from pathlib import Path
from unittest.mock import patch

import pytest

from proxym.virt._config import VMConfig
from proxym.virt._vm_config import _ConfigMixin


class _FakeConfigMixin(_ConfigMixin):
    """Concrete class wrapping _ConfigMixin for testing."""

    def __init__(self, tmp_path: Path):
        self.config_dir = tmp_path / "config"
        self.config_dir.mkdir()
        self.profiles_dir = tmp_path / "profiles"
        self.profiles_dir.mkdir()
        self._vm_key_registry: dict = {}


@pytest.fixture
def mixin(tmp_path):
    return _FakeConfigMixin(tmp_path)


class TestGenerateVmKey:
    def test_key_starts_with_prefix(self, mixin):
        key = mixin._generate_vm_key("vm-42", "acct-1")
        assert key.startswith("vm-key-vm-42-")

    def test_key_is_unique(self, mixin):
        k1 = mixin._generate_vm_key("vm-1")
        k2 = mixin._generate_vm_key("vm-1")
        assert k1 != k2

    def test_key_registered_in_memory(self, mixin):
        key = mixin._generate_vm_key("vm-7", "acct-x")
        assert key in mixin._vm_key_registry
        assert mixin._vm_key_registry[key]["vm_id"] == "vm-7"
        assert mixin._vm_key_registry[key]["account_id"] == "acct-x"


class TestRenderTemplate:
    def test_replaces_variables(self, mixin):
        tmpl = "Hello ${NAME}, your key is ${KEY}."
        result = mixin._render_template(tmpl, {"NAME": "Alice", "KEY": "sk-123"})
        assert result == "Hello Alice, your key is sk-123."

    def test_leaves_unknown_placeholders(self, mixin):
        tmpl = "Host: ${HOST}, Port: ${PORT}"
        result = mixin._render_template(tmpl, {"HOST": "10.0.2.2"})
        assert result == "Host: 10.0.2.2, Port: ${PORT}"

    def test_empty_variables(self, mixin):
        tmpl = "no vars here"
        assert mixin._render_template(tmpl, {}) == "no vars here"


class TestGetGitConfig:
    @patch("subprocess.run")
    def test_reads_git_user(self, mock_run, mixin, tmp_path):
        # Mock git config calls
        from types import SimpleNamespace
        mock_run.side_effect = [
            SimpleNamespace(returncode=0, stdout="Tom Dev\n"),
            SimpleNamespace(returncode=0, stdout="tom@dev.io\n"),
        ]
        with patch("pathlib.Path.home", return_value=tmp_path):
            (tmp_path / ".gitconfig").write_text("[user]\n\tname = Tom Dev\n")
            result = mixin._get_git_config()
        assert result["user.name"] == "Tom Dev"
        assert result["user.email"] == "tom@dev.io"

    def test_returns_empty_when_no_gitconfig(self, mixin, tmp_path):
        with patch("pathlib.Path.home", return_value=tmp_path):
            result = mixin._get_git_config()
        assert result == {}


class TestSaveVmKeyMapping:
    def test_creates_mapping_file(self, mixin):
        config = VMConfig(name="test", id="vm-1", account_id="acct-1", tool="windsurf")
        mixin._save_vm_key_mapping("vm-key-test-123", config)

        mapping_file = mixin.config_dir / "vm_key_mappings.json"
        assert mapping_file.exists()
        data = json.loads(mapping_file.read_text())
        assert "vm-key-test-123" in data
        assert data["vm-key-test-123"]["vm_id"] == "vm-1"
        assert data["vm-key-test-123"]["account_id"] == "acct-1"

    def test_appends_to_existing_mapping(self, mixin):
        config1 = VMConfig(name="a", id="vm-1", account_id="a1")
        config2 = VMConfig(name="b", id="vm-2", account_id="a2")
        mixin._save_vm_key_mapping("key-1", config1)
        mixin._save_vm_key_mapping("key-2", config2)

        data = json.loads((mixin.config_dir / "vm_key_mappings.json").read_text())
        assert len(data) == 2


class TestResolveVmKeyAccount:
    def test_resolves_from_registry(self, mixin):
        mixin._vm_key_registry["vm-key-abc"] = {"vm_id": "v1", "account_id": "acct-7"}
        assert mixin.resolve_vm_key_account("vm-key-abc") == "acct-7"

    def test_resolves_from_file(self, mixin):
        mapping_file = mixin.config_dir / "vm_key_mappings.json"
        mapping_file.write_text(json.dumps({
            "vm-key-file": {"vm_id": "v2", "account_id": "acct-file"}
        }))
        assert mixin.resolve_vm_key_account("vm-key-file") == "acct-file"

    def test_returns_none_for_unknown_key(self, mixin):
        assert mixin.resolve_vm_key_account("unknown-key") is None
