# 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
