"""Tests for variable extraction and resolution service."""
import pytest

from app.services.variable_service import extract_variables, resolve_variables


TREE_WITH_VARIABLES = {
    "id": "root",
    "type": "decision",
    "question": "What is the hostname of [USER_INPUT:hostname]?",
    "help_text": "Enter the server hostname",
    "options": [
        {"id": "opt1", "label": "Check [VAR:hostname]", "next_node_id": "action1"},
    ],
    "children": [
        {
            "id": "action1",
            "type": "action",
            "title": "Ping [VAR:hostname]",
            "description": "Run diagnostics on [VAR:hostname].\n\n[SAVE_AS:test_results]",
            "commands": ["ping [VAR:hostname]"],
            "expected_outcome": "Replies from [VAR:hostname]",
            "next_node_id": "solution1",
            "children": [
                {
                    "id": "solution1",
                    "type": "solution",
                    "title": "Resolved",
                    "description": "Issue on [VAR:hostname] resolved.",
                    "resolution_steps": [
                        "Document results for [VAR:hostname]",
                        "Save as [SAVE_AS:final_result]"
                    ],
                    "solution": "Resolved",
                }
            ],
        }
    ],
}

TREE_WITHOUT_VARIABLES = {
    "id": "root",
    "type": "solution",
    "title": "Simple Fix",
    "description": "Just restart it.",
    "solution": "Restart",
}


class TestExtractVariables:
    def test_extracts_user_input(self):
        variables = extract_variables(TREE_WITH_VARIABLES)
        user_inputs = [v for v in variables if v.kind == "user_input"]
        assert len(user_inputs) == 1
        assert user_inputs[0].name == "hostname"
        assert user_inputs[0].node_id == "root"

    def test_extracts_var_references(self):
        variables = extract_variables(TREE_WITH_VARIABLES)
        refs = [v for v in variables if v.kind == "reference"]
        assert len(refs) >= 4  # hostname used in multiple places

    def test_extracts_save_as(self):
        variables = extract_variables(TREE_WITH_VARIABLES)
        saves = [v for v in variables if v.kind == "save_as"]
        assert len(saves) == 2
        names = {v.name for v in saves}
        assert "test_results" in names
        assert "final_result" in names

    def test_no_variables(self):
        variables = extract_variables(TREE_WITHOUT_VARIABLES)
        assert len(variables) == 0

    def test_extracts_from_commands(self):
        variables = extract_variables(TREE_WITH_VARIABLES)
        cmd_vars = [v for v in variables if v.node_id == "action1" and v.kind == "reference"]
        # hostname in title, description, commands, expected_outcome
        assert len(cmd_vars) >= 3


class TestResolveVariables:
    def test_resolves_var_reference(self):
        text = "Ping [VAR:hostname] now"
        result = resolve_variables(text, {"hostname": "server01"})
        assert result == "Ping server01 now"

    def test_resolves_user_input(self):
        text = "Server: [USER_INPUT:hostname]"
        result = resolve_variables(text, {"hostname": "server01"})
        assert result == "Server: server01"

    def test_removes_save_as(self):
        text = "Done [SAVE_AS:result] here"
        result = resolve_variables(text, {})
        assert result == "Done  here"

    def test_unresolved_var_preserved(self):
        text = "Server: [VAR:unknown_var]"
        result = resolve_variables(text, {})
        assert result == "Server: [VAR:unknown_var]"

    def test_multiple_variables(self):
        text = "[VAR:hostname] ([VAR:ip]) - [USER_INPUT:ticket]"
        result = resolve_variables(text, {
            "hostname": "server01",
            "ip": "10.0.0.1",
            "ticket": "INC001",
        })
        assert result == "server01 (10.0.0.1) - INC001"

    def test_empty_variables_dict(self):
        text = "No vars here"
        result = resolve_variables(text, {})
        assert result == "No vars here"

    def test_empty_text(self):
        result = resolve_variables("", {"hostname": "server01"})
        assert result == ""
