"""Tests for the DSL parser — pattern matching without LLM."""

from __future__ import annotations

import pytest

from proxym.cli.dsl import DSLParser, ParsedCommand


@pytest.fixture
def parser() -> DSLParser:
    """DSL parser using bundled (default) patterns."""
    return DSLParser(dsl_path=None)


# ── Query matching ────────────────────────────────────────


class TestQueryMatching:
    """Test read-only query patterns (PL + EN)."""

    @pytest.mark.parametrize("text", [
        "status",
        "Status",
        "STATUS",
        "jak idzie",
        "co działa",
        "pokaż stan",
        "show status",
    ])
    def test_status_patterns(self, parser: DSLParser, text: str):
        cmd = parser.parse(text)
        assert cmd is not None
        assert cmd.action_type == "query"
        assert cmd.raw_pattern == "status"
        assert cmd.endpoint.startswith("GET /dashboard/")

    @pytest.mark.parametrize("text", [
        "pokaż VM-y",
        "vm list",
        "list vms",
        "show vms",
    ])
    def test_vms_patterns(self, parser: DSLParser, text: str):
        cmd = parser.parse(text)
        assert cmd is not None
        assert cmd.raw_pattern == "vms"
        assert cmd.action_type == "query"

    @pytest.mark.parametrize("text", [
        "ile wydałem",
        "koszty",
        "costs",
        "budget",
    ])
    def test_costs_patterns(self, parser: DSLParser, text: str):
        cmd = parser.parse(text)
        assert cmd is not None
        assert cmd.raw_pattern == "costs"

    @pytest.mark.parametrize("text", [
        "logi",
        "logs",
        "errors",
        "co się stało",
    ])
    def test_logs_patterns(self, parser: DSLParser, text: str):
        cmd = parser.parse(text)
        assert cmd is not None
        assert cmd.raw_pattern == "logs"

    @pytest.mark.parametrize("text", [
        "models",
        "jakie modele",
        "dostępne modele",
    ])
    def test_models_patterns(self, parser: DSLParser, text: str):
        cmd = parser.parse(text)
        assert cmd is not None
        assert cmd.raw_pattern == "models"


# ── Command matching with placeholders ────────────────────


class TestCommandMatching:
    """Test write commands with parameter extraction."""

    def test_vm_create_pl(self, parser: DSLParser):
        cmd = parser.parse("stwórz VM windsurf dla proxym")
        assert cmd is not None
        assert cmd.action_type == "command"
        assert cmd.raw_pattern == "vm_create"
        assert cmd.params["tool"] == "windsurf"
        assert cmd.params["project"] == "proxym"

    def test_vm_create_en(self, parser: DSLParser):
        cmd = parser.parse("create vm cursor for my-project")
        assert cmd is not None
        assert cmd.raw_pattern == "vm_create"
        assert cmd.params["tool"] == "cursor"
        assert cmd.params["project"] == "my-project"

    def test_vm_create_defaults(self, parser: DSLParser):
        cmd = parser.parse("create vm vscode for test-proj")
        assert cmd is not None
        assert cmd.params.get("account") == "cheapest_active"

    def test_vm_start_pl(self, parser: DSLParser):
        cmd = parser.parse("uruchom windsurf-work")
        assert cmd is not None
        assert cmd.raw_pattern == "vm_start"
        assert "windsurf-work" in cmd.endpoint

    def test_vm_start_en(self, parser: DSLParser):
        cmd = parser.parse("start cursor-oss")
        assert cmd is not None
        assert cmd.raw_pattern == "vm_start"
        assert "cursor-oss" in cmd.endpoint

    def test_vm_stop_pl(self, parser: DSLParser):
        cmd = parser.parse("zatrzymaj windsurf-work")
        assert cmd is not None
        assert cmd.raw_pattern == "vm_stop"

    def test_vm_stop_en(self, parser: DSLParser):
        cmd = parser.parse("stop vscode-beta")
        assert cmd is not None
        assert cmd.raw_pattern == "vm_stop"
        assert "vscode-beta" in cmd.endpoint

    def test_vm_snapshot_simple(self, parser: DSLParser):
        cmd = parser.parse("snapshot windsurf-work")
        assert cmd is not None
        assert cmd.raw_pattern == "vm_snapshot"
        assert "windsurf-work" in cmd.endpoint

    def test_vm_snapshot_named(self, parser: DSLParser):
        cmd = parser.parse("snapshot windsurf-work jako before-refactor")
        assert cmd is not None
        assert cmd.params["name"] == "before-refactor"

    def test_switch_project_pl(self, parser: DSLParser):
        cmd = parser.parse("przełącz windsurf-work na other-project")
        assert cmd is not None
        assert cmd.raw_pattern == "switch_project"
        assert cmd.params["vm_id"] == "windsurf-work"
        assert cmd.params["project"] == "other-project"

    def test_switch_project_en(self, parser: DSLParser):
        cmd = parser.parse("switch cursor-oss to new-app")
        assert cmd is not None
        assert cmd.raw_pattern == "switch_project"
        assert cmd.params["project"] == "new-app"


# ── No match → None (forward to LLM) ─────────────────────


class TestNoMatch:
    """Unrecognized phrases should return None."""

    @pytest.mark.parametrize("text", [
        "dlaczego windsurf zużywa więcej",
        "explain the architecture",
        "hello world",
        "",
        "   ",
    ])
    def test_no_match_returns_none(self, parser: DSLParser, text: str):
        assert parser.parse(text) is None


# ── ParsedCommand structure ───────────────────────────────


class TestParsedCommand:
    """Test the ParsedCommand dataclass."""

    def test_confidence_always_one(self, parser: DSLParser):
        cmd = parser.parse("status")
        assert cmd is not None
        assert cmd.confidence == pytest.approx(1.0)

    def test_format_field(self, parser: DSLParser):
        cmd = parser.parse("status")
        assert cmd is not None
        assert cmd.format == "table"

    def test_endpoint_substitution(self, parser: DSLParser):
        cmd = parser.parse("start my-vm")
        assert cmd is not None
        assert cmd.endpoint == "POST /dashboard/vms/my-vm/start"


# ── list_patterns ─────────────────────────────────────────


class TestListPatterns:
    """Test the list_patterns helper."""

    def test_returns_all_entries(self, parser: DSLParser):
        patterns = parser.list_patterns()
        names = {p["name"] for p in patterns}
        assert "status" in names
        assert "vms" in names
        assert "vm_create" in names
        assert "vm_start" in names

    def test_entries_have_required_fields(self, parser: DSLParser):
        for entry in parser.list_patterns():
            assert "name" in entry
            assert "type" in entry
            assert "patterns" in entry
            assert "action" in entry
            assert entry["type"] in ("query", "command")
