# Familiar - Self-Hosted AI Companion Platform
# Copyright (c) 2026 George Scott Foley
# ORCID: 0009-0006-4957-0540
# Email: Georgescottfoley@proton.me
# Licensed under the MIT License - see LICENSE file for details

"""Tests for the dashboard action router."""

import pytest

from familiar.dashboard.action_router import match_action


class TestNavigationPatterns:
    """Test that common navigation phrases route to the correct panel."""

    @pytest.mark.parametrize(
        "message,expected_panel",
        [
            # Email
            ("show my email", "email"),
            ("check email", "email"),
            ("open inbox", "email"),
            ("any new emails?", "email"),
            ("what's in my inbox?", "email"),
            ("email", "email"),
            # Calendar
            ("show my calendar", "calendar"),
            ("check schedule", "calendar"),
            ("what's on my calendar?", "calendar"),
            ("any meetings today?", "calendar"),
            ("calendar", "calendar"),
            ("what's coming up?", "calendar"),
            # Tasks
            ("show my tasks", "tasks"),
            ("check tasks", "tasks"),
            ("what's my to-do list?", "tasks"),
            ("tasks", "tasks"),
            # Workspace
            ("show my workspace", "workspace"),
            ("open command center", "workspace"),
            ("workspace", "workspace"),
            # Server
            ("show my server", "server"),
            ("server status?", "server"),
            ("what's running on my server?", "server"),
            ("check services", "server"),
            # Memory
            ("show my memory", "memory"),
            ("memory", "memory"),
            # Settings
            ("show my settings", "settings"),
            ("settings", "settings"),
            # Connect
            ("show my connections", "connect"),
            ("view connected services", "connect"),
            # Models
            ("show my models", "models"),
            ("what models are available?", "models"),
            ("models", "models"),
            # Skills
            ("show my skills", "skills"),
            ("what can you do?", "skills"),
            ("skills", "skills"),
            # Nodes
            ("show my nodes", "nodes"),
            ("nodes", "nodes"),
            # Messages
            ("check messages", "messages"),
            ("messages", "messages"),
            # Activity
            ("show my activity", "activity"),
            ("analytics", "activity"),
            # Briefing
            ("show my briefing", "briefing"),
            ("daily briefing", "briefing"),
            ("briefing", "briefing"),
            # Media
            ("show my media", "media"),
            ("media", "media"),
            # Gallery
            ("show my gallery", "gallery"),
            ("gallery", "gallery"),
            # Social
            ("show my social", "social"),
            ("social", "social"),
            # Training
            ("show my training", "training"),
            ("training", "training"),
            # Marketplace
            ("show my marketplace", "marketplace"),
            ("marketplace", "marketplace"),
        ],
    )
    def test_navigation(self, message, expected_panel):
        result = match_action(message)
        assert result is not None, f"No match for: {message!r}"
        assert result["type"] == "navigate"
        assert result["panel"] == expected_panel

    def test_case_insensitive(self):
        result = match_action("Show My Email")
        assert result is not None
        assert result["panel"] == "email"

    def test_case_insensitive_calendar(self):
        result = match_action("CHECK MY CALENDAR")
        assert result is not None
        assert result["panel"] == "calendar"


class TestDeployPatterns:
    """Test service deployment action matching."""

    @pytest.mark.parametrize(
        "message,expected_service",
        [
            ("deploy mealie", "mealie"),
            ("install gitea", "gitea"),
            ("set up nextcloud", "nextcloud"),
            ("provision jellyfin", "jellyfin"),
            ("start joplin", "joplin"),
            ("launch searxng", "searxng"),
            ("deploy pihole", "pihole"),
            ("spin up netdata", "netdata"),
        ],
    )
    def test_deploy_service(self, message, expected_service):
        result = match_action(message)
        assert result is not None, f"No match for: {message!r}"
        assert result["type"] == "provision"
        assert result["service"] == expected_service

    def test_deploy_by_alias(self):
        result = match_action("deploy recipes")
        assert result is not None
        assert result["service"] == "mealie"

    def test_deploy_all(self):
        result = match_action("deploy all services")
        assert result is not None
        assert result["type"] == "api_call"
        assert result["endpoint"] == "/api/server/full-setup"

    def test_auto_provision(self):
        result = match_action("auto deploy")
        assert result is not None
        assert result["type"] == "api_call"


class TestSearchPatterns:
    """Test web search action matching."""

    def test_search_for(self):
        result = match_action("search for python decorators")
        assert result is not None
        assert result["type"] == "search"
        assert result["query"] == "python decorators"

    def test_look_up(self):
        result = match_action("look up kubernetes networking")
        assert result is not None
        assert result["type"] == "search"
        assert result["query"] == "kubernetes networking"

    def test_google(self):
        result = match_action("google flask blueprints")
        assert result is not None
        assert result["type"] == "search"

    def test_find(self):
        result = match_action("find best pizza recipe")
        assert result is not None
        assert result["type"] == "search"


class TestStatusPatterns:
    """Test status/overview matching."""

    def test_status(self):
        result = match_action("status")
        assert result is not None
        assert result["type"] == "navigate"
        assert result["panel"] == "workspace"

    def test_how_is_everything(self):
        result = match_action("how's everything?")
        assert result is not None
        assert result["panel"] == "workspace"

    def test_system_status(self):
        result = match_action("system status")
        assert result is not None


class TestSetupPatterns:
    """Test setup wizard matching."""

    def test_setup_services(self):
        result = match_action("set up my services")
        assert result is not None
        assert result["type"] == "navigate"
        assert result["panel"] == "workspace"

    def test_what_needs_setup(self):
        result = match_action("what's not set up?")
        assert result is not None

    def test_configure_everything(self):
        result = match_action("configure my stuff")
        assert result is not None


class TestHelpPattern:
    """Test help text matching."""

    def test_help(self):
        result = match_action("help")
        assert result is not None
        assert result["type"] == "quick_reply"
        assert "Navigation" in result["response"]

    def test_what_can_you_do(self):
        result = match_action("what can you do?")
        assert result is not None
        # "what can you do?" matches skills nav — that's a valid response
        assert result["type"] in ("quick_reply", "navigate")


class TestNoMatch:
    """Test that complex/ambiguous messages fall through to LLM."""

    @pytest.mark.parametrize(
        "message",
        [
            "can you help me write a cover letter",
            "analyze this spreadsheet for trends",
            "what's the weather like",
            "create a menu for a dinner party for 8",
            "search my email for transpride updates",
            "draft an email to the board about Q2 results",
            "how do I configure nginx",
            "tell me about the history of the internet",
            "",
            "/connect stripe",
            "[Attached files — use read_document] my_file.pdf",
        ],
    )
    def test_no_match(self, message):
        result = match_action(message)
        assert result is None, f"Should not match: {message!r}, got: {result}"

    def test_none_input(self):
        result = match_action("")
        assert result is None

    def test_slash_commands_pass_through(self):
        """Slash commands should never match — handled by wizard system."""
        result = match_action("/start")
        assert result is None
        result = match_action("/connect github")
        assert result is None
