"""Tests for vr get commands."""

import pytest
from unittest.mock import patch, Mock

from typer.testing import CliRunner

from vr_cli.cli import app
from vr_cli.entities.agent import Agent
from vr_cli.entities.agent_function import AgentFunction
from vr_cli.entities.agent_environment import AgentEnvironment
from vr_cli.entities.agent_secret import AgentSecret
from vr_cli.entities.organization_phone_number import OrganizationPhoneNumber
from vr_cli.entities.organization_secret import OrganizationSecret
from vr_cli.entities.organization_telephony import OrganizationTelephony
from vr_cli.entities.agent_template import AgentTemplate
from vr_cli.entities.user import User


runner = CliRunner()


# ============================================================================
# Get Agents Tests
# ============================================================================


class TestGetAgents:
    """Tests for get agents command."""

    def test_get_agents_lists_all(self, mock_agents_list):
        """Should list all agents in a table."""
        with patch("vr_cli.commands.get.AgentRepository") as mock_repo_class:
            mock_repo = Mock()
            mock_repo.get.return_value = mock_agents_list
            mock_repo_class.return_value = mock_repo

            result = runner.invoke(app, ["get", "agents"])

        assert result.exit_code == 0
        assert "Agent One" in result.output
        assert "Agent Two" in result.output
        assert "agent-1" in result.output
        assert "agent-2" in result.output

    def test_get_agents_empty(self):
        """Should show message when no agents found."""
        with patch("vr_cli.commands.get.AgentRepository") as mock_repo_class:
            mock_repo = Mock()
            mock_repo.get.return_value = []
            mock_repo_class.return_value = mock_repo

            result = runner.invoke(app, ["get", "agents"])

        assert result.exit_code == 0
        assert "No agents found" in result.output

    def test_get_agents_handles_none_values(self):
        """Should handle agents with None values."""
        agents = [
            Agent(
                id="agent-1",
                name=None,
                description=None,
                default_voice_name=None,
                transport=None,
            )
        ]

        with patch("vr_cli.commands.get.AgentRepository") as mock_repo_class:
            mock_repo = Mock()
            mock_repo.get.return_value = agents
            mock_repo_class.return_value = mock_repo

            result = runner.invoke(app, ["get", "agents"])

        assert result.exit_code == 0
        assert "N/A" in result.output

    def test_get_agents_truncates_description(self):
        """Should truncate long descriptions."""
        agents = [
            Agent(
                id="agent-1",
                name="Test Agent",
                description="A" * 50,  # Long description
                default_voice_name="voice",
                transport="websocket",
            )
        ]

        with patch("vr_cli.commands.get.AgentRepository") as mock_repo_class:
            mock_repo = Mock()
            mock_repo.get.return_value = agents
            mock_repo_class.return_value = mock_repo

            result = runner.invoke(app, ["get", "agents"])

        assert result.exit_code == 0
        # Rich uses Unicode ellipsis character or "..." for truncation
        assert "..." in result.output or "\u2026" in result.output


# ============================================================================
# Get Functions Tests
# ============================================================================


class TestGetFunctions:
    """Tests for get functions command."""

    def test_get_functions_lists_all(self, mock_agent, mock_functions_list):
        """Should list all functions for an agent."""
        with patch("vr_cli.commands.get.AgentRepository") as mock_agent_repo_class, \
             patch("vr_cli.commands.get.AgentFunctionRepository") as mock_func_repo_class:

            mock_agent_repo = Mock()
            mock_agent_repo.get_by_name_or_id.return_value = mock_agent
            mock_agent_repo_class.return_value = mock_agent_repo

            mock_func_repo = Mock()
            mock_func_repo.get.return_value = mock_functions_list
            mock_func_repo_class.return_value = mock_func_repo

            result = runner.invoke(app, ["get", "functions", "Test Agent"])

        assert result.exit_code == 0
        assert "Function One" in result.output
        assert "Function Two" in result.output
        assert "function-1" in result.output
        assert "function-2" in result.output
        assert "python" in result.output
        assert "javascript" in result.output

    def test_get_functions_agent_not_found(self):
        """Should fail when agent not found."""
        with patch("vr_cli.commands.get.AgentRepository") as mock_agent_repo_class:
            mock_agent_repo = Mock()
            mock_agent_repo.get_by_name_or_id.return_value = None
            mock_agent_repo_class.return_value = mock_agent_repo

            result = runner.invoke(app, ["get", "functions", "nonexistent"])

        assert result.exit_code != 0
        assert "Agent not found" in result.output

    def test_get_functions_empty(self, mock_agent):
        """Should show message when no functions found."""
        with patch("vr_cli.commands.get.AgentRepository") as mock_agent_repo_class, \
             patch("vr_cli.commands.get.AgentFunctionRepository") as mock_func_repo_class:

            mock_agent_repo = Mock()
            mock_agent_repo.get_by_name_or_id.return_value = mock_agent
            mock_agent_repo_class.return_value = mock_agent_repo

            mock_func_repo = Mock()
            mock_func_repo.get.return_value = []
            mock_func_repo_class.return_value = mock_func_repo

            result = runner.invoke(app, ["get", "functions", "Test Agent"])

        assert result.exit_code == 0
        assert "No functions found" in result.output

    def test_get_functions_by_agent_id(self, mock_agent, mock_functions_list):
        """Should resolve agent by ID."""
        with patch("vr_cli.commands.get.AgentRepository") as mock_agent_repo_class, \
             patch("vr_cli.commands.get.AgentFunctionRepository") as mock_func_repo_class:

            mock_agent_repo = Mock()
            mock_agent_repo.get_by_name_or_id.return_value = mock_agent
            mock_agent_repo_class.return_value = mock_agent_repo

            mock_func_repo = Mock()
            mock_func_repo.get.return_value = mock_functions_list
            mock_func_repo_class.return_value = mock_func_repo

            result = runner.invoke(app, ["get", "functions", "test-agent-id-123"])

        assert result.exit_code == 0
        mock_agent_repo.get_by_name_or_id.assert_called_once_with("test-agent-id-123")

    def test_get_functions_shows_display_name(self, mock_agent):
        """Should show display_name when available."""
        functions = [
            AgentFunction(
                id="func-1",
                agent_id="agent-1",
                name="internal_name",
                display_name="User Friendly Name",
                language="python",
                strategy="cascade",
                is_multifile=False,
            )
        ]

        with patch("vr_cli.commands.get.AgentRepository") as mock_agent_repo_class, \
             patch("vr_cli.commands.get.AgentFunctionRepository") as mock_func_repo_class:

            mock_agent_repo = Mock()
            mock_agent_repo.get_by_name_or_id.return_value = mock_agent
            mock_agent_repo_class.return_value = mock_agent_repo

            mock_func_repo = Mock()
            mock_func_repo.get.return_value = functions
            mock_func_repo_class.return_value = mock_func_repo

            result = runner.invoke(app, ["get", "functions", "Test Agent"])

        assert result.exit_code == 0
        # Rich may wrap long text across lines, so check for parts
        assert "User Friendly" in result.output
        assert "internal_name" in result.output


# ============================================================================
# Get Environments Tests
# ============================================================================


class TestGetEnvironments:
    """Tests for get environments command."""

    def test_get_environments_lists_all(self, mock_agent):
        """Should list all environments for an agent."""
        environments = [
            AgentEnvironment(
                id="env-1",
                agent_id="agent-1",
                name="production",
                phone_number="+1234567890",
                stt_model="nova-3",
                recording_enabled=True,
                is_debug=False,
            ),
            AgentEnvironment(
                id="env-2",
                agent_id="agent-1",
                name="debug",
                phone_number=None,
                stt_model="nova-3",
                recording_enabled=False,
                is_debug=True,
            ),
        ]

        with patch("vr_cli.commands.get.AgentRepository") as mock_agent_repo_class, \
             patch("vr_cli.commands.get.AgentEnvironmentRepository") as mock_env_repo_class:

            mock_agent_repo = Mock()
            mock_agent_repo.get_by_name_or_id.return_value = mock_agent
            mock_agent_repo_class.return_value = mock_agent_repo

            mock_env_repo = Mock()
            mock_env_repo.get.return_value = environments
            mock_env_repo_class.return_value = mock_env_repo

            result = runner.invoke(app, ["get", "environments", "Test Agent"])

        assert result.exit_code == 0
        assert "production" in result.output
        assert "debug" in result.output
        assert "env-1" in result.output
        assert "env-2" in result.output
        assert "+1234567890" in result.output
        assert "nova-3" in result.output

    def test_get_environments_agent_not_found(self):
        """Should fail when agent not found."""
        with patch("vr_cli.commands.get.AgentRepository") as mock_agent_repo_class:
            mock_agent_repo = Mock()
            mock_agent_repo.get_by_name_or_id.return_value = None
            mock_agent_repo_class.return_value = mock_agent_repo

            result = runner.invoke(app, ["get", "environments", "nonexistent"])

        assert result.exit_code != 0
        assert "Agent not found" in result.output

    def test_get_environments_empty(self, mock_agent):
        """Should show message when no environments found."""
        with patch("vr_cli.commands.get.AgentRepository") as mock_agent_repo_class, \
             patch("vr_cli.commands.get.AgentEnvironmentRepository") as mock_env_repo_class:

            mock_agent_repo = Mock()
            mock_agent_repo.get_by_name_or_id.return_value = mock_agent
            mock_agent_repo_class.return_value = mock_agent_repo

            mock_env_repo = Mock()
            mock_env_repo.get.return_value = []
            mock_env_repo_class.return_value = mock_env_repo

            result = runner.invoke(app, ["get", "environments", "Test Agent"])

        assert result.exit_code == 0
        assert "No environments found" in result.output

    def test_get_environments_shows_recording_status(self, mock_agent):
        """Should show recording enabled status."""
        environments = [
            AgentEnvironment(
                id="env-1",
                agent_id="agent-1",
                name="recording-on",
                stt_model="nova-3",
                recording_enabled=True,
                is_debug=False,
            ),
            AgentEnvironment(
                id="env-2",
                agent_id="agent-1",
                name="recording-off",
                stt_model="nova-3",
                recording_enabled=False,
                is_debug=False,
            ),
        ]

        with patch("vr_cli.commands.get.AgentRepository") as mock_agent_repo_class, \
             patch("vr_cli.commands.get.AgentEnvironmentRepository") as mock_env_repo_class:

            mock_agent_repo = Mock()
            mock_agent_repo.get_by_name_or_id.return_value = mock_agent
            mock_agent_repo_class.return_value = mock_agent_repo

            mock_env_repo = Mock()
            mock_env_repo.get.return_value = environments
            mock_env_repo_class.return_value = mock_env_repo

            result = runner.invoke(app, ["get", "environments", "Test Agent"])

        assert result.exit_code == 0
        assert "Yes" in result.output
        assert "No" in result.output


# ============================================================================
# Get Secrets Tests
# ============================================================================


class TestGetSecrets:
    """Tests for get secrets command."""

    # Authentication tests

    def test_get_secrets_no_user(self):
        """Should fail when user is not authenticated."""
        with patch("vr_cli.commands.get.get_effective_organization_id") as mock_get_org:
            mock_get_org.return_value = None

            result = runner.invoke(app, ["get", "secrets"])

        assert result.exit_code != 0
        assert "Unable to determine organization" in result.output

    def test_get_secrets_no_organization(self):
        """Should fail when user has no organization."""
        with patch("vr_cli.commands.get.get_effective_organization_id") as mock_get_org:
            mock_get_org.return_value = None

            result = runner.invoke(app, ["get", "secrets"])

        assert result.exit_code != 0
        assert "Unable to determine organization" in result.output

    # Organization secrets only (no agent.lock, no --agent flag)

    def test_get_org_secrets_only(self, mock_user, mock_organization_secrets_list):
        """Should list only organization secrets when not in voicerun project."""
        with patch("vr_cli.commands.get.get_effective_organization_id") as mock_get_org, \
             patch("vr_cli.commands.get.OrganizationSecretRepository") as mock_org_repo_class, \
             patch("vr_cli.commands.get.Path") as mock_path:

            mock_get_org.return_value = mock_user.organization_id

            # Simulate no .voicerun directory
            mock_voicerun_dir = Mock()
            mock_voicerun_dir.exists.return_value = False
            mock_path.cwd.return_value.__truediv__.return_value = mock_voicerun_dir

            mock_org_repo = Mock()
            mock_org_repo.get.return_value = mock_organization_secrets_list
            mock_org_repo_class.return_value = mock_org_repo

            result = runner.invoke(app, ["get", "secrets"])

        assert result.exit_code == 0
        assert "Organization Secrets" in result.output
        assert "ORG_DATABASE_URL" in result.output
        assert "ORG_API_KEY" in result.output

    def test_get_org_secrets_empty(self, mock_user):
        """Should show message when no organization secrets found."""
        with patch("vr_cli.commands.get.get_effective_organization_id") as mock_get_org, \
             patch("vr_cli.commands.get.OrganizationSecretRepository") as mock_org_repo_class, \
             patch("vr_cli.commands.get.Path") as mock_path:

            mock_get_org.return_value = mock_user.organization_id

            mock_voicerun_dir = Mock()
            mock_voicerun_dir.exists.return_value = False
            mock_path.cwd.return_value.__truediv__.return_value = mock_voicerun_dir

            mock_org_repo = Mock()
            mock_org_repo.get.return_value = []
            mock_org_repo_class.return_value = mock_org_repo

            result = runner.invoke(app, ["get", "secrets"])

        assert result.exit_code == 0
        assert "No organization secrets found" in result.output

    # With --agent flag (shows both org and agent secrets)

    def test_get_secrets_with_agent_flag(self, mock_user, mock_agent, mock_organization_secrets_list, mock_secrets_list):
        """Should list both org and agent secrets when --agent is provided."""
        with patch("vr_cli.commands.get.get_effective_organization_id") as mock_get_org, \
             patch("vr_cli.commands.get.OrganizationSecretRepository") as mock_org_repo_class, \
             patch("vr_cli.commands.get.AgentRepository") as mock_agent_repo_class, \
             patch("vr_cli.commands.get.AgentSecretRepository") as mock_agent_secret_repo_class:

            mock_get_org.return_value = mock_user.organization_id

            mock_org_repo = Mock()
            mock_org_repo.get.return_value = mock_organization_secrets_list
            mock_org_repo_class.return_value = mock_org_repo

            mock_agent_repo = Mock()
            mock_agent_repo.get_by_name_or_id.return_value = mock_agent
            mock_agent_repo_class.return_value = mock_agent_repo

            mock_agent_secret_repo = Mock()
            mock_agent_secret_repo.get.return_value = mock_secrets_list
            mock_agent_secret_repo_class.return_value = mock_agent_secret_repo

            result = runner.invoke(app, ["get", "secrets", "--agent", "Test Agent"])

        assert result.exit_code == 0
        # Org secrets
        assert "Organization Secrets" in result.output
        assert "ORG_DATABASE_URL" in result.output
        # Agent secrets
        assert "Secrets for Agent" in result.output
        assert "DATABASE_URL" in result.output
        assert "API_KEY" in result.output

    def test_get_secrets_agent_not_found(self, mock_user):
        """Should fail when agent not found."""
        with patch("vr_cli.commands.get.get_effective_organization_id") as mock_get_org, \
             patch("vr_cli.commands.get.AgentRepository") as mock_agent_repo_class:

            mock_get_org.return_value = mock_user.organization_id

            mock_agent_repo = Mock()
            mock_agent_repo.get_by_name_or_id.return_value = None
            mock_agent_repo_class.return_value = mock_agent_repo

            result = runner.invoke(app, ["get", "secrets", "--agent", "nonexistent"])

        assert result.exit_code != 0
        assert "Agent not found" in result.output

    def test_get_secrets_with_agent_flag_short(self, mock_user, mock_agent, mock_organization_secrets_list, mock_secrets_list):
        """Should work with -a short flag."""
        with patch("vr_cli.commands.get.get_effective_organization_id") as mock_get_org, \
             patch("vr_cli.commands.get.OrganizationSecretRepository") as mock_org_repo_class, \
             patch("vr_cli.commands.get.AgentRepository") as mock_agent_repo_class, \
             patch("vr_cli.commands.get.AgentSecretRepository") as mock_agent_secret_repo_class:

            mock_get_org.return_value = mock_user.organization_id

            mock_org_repo = Mock()
            mock_org_repo.get.return_value = mock_organization_secrets_list
            mock_org_repo_class.return_value = mock_org_repo

            mock_agent_repo = Mock()
            mock_agent_repo.get_by_name_or_id.return_value = mock_agent
            mock_agent_repo_class.return_value = mock_agent_repo

            mock_agent_secret_repo = Mock()
            mock_agent_secret_repo.get.return_value = mock_secrets_list
            mock_agent_secret_repo_class.return_value = mock_agent_secret_repo

            result = runner.invoke(app, ["get", "secrets", "-a", "test-agent-id-123"])

        assert result.exit_code == 0
        mock_agent_repo.get_by_name_or_id.assert_called_once_with("test-agent-id-123")

    # With agent.lock file (auto-detect agent)

    def test_get_secrets_with_agent_lock(self, mock_user, mock_agent, mock_organization_secrets_list, mock_secrets_list):
        """Should list both org and agent secrets when agent.lock exists."""
        with patch("vr_cli.commands.get.get_effective_organization_id") as mock_get_org, \
             patch("vr_cli.commands.get.OrganizationSecretRepository") as mock_org_repo_class, \
             patch("vr_cli.commands.get.AgentRepository") as mock_agent_repo_class, \
             patch("vr_cli.commands.get.AgentSecretRepository") as mock_agent_secret_repo_class, \
             patch("vr_cli.commands.get.Path") as mock_path, \
             patch("vr_cli.commands.get.load_agent_lock") as mock_load_lock:

            mock_get_org.return_value = mock_user.organization_id

            # Simulate .voicerun directory exists
            mock_voicerun_dir = Mock()
            mock_voicerun_dir.exists.return_value = True
            mock_path.cwd.return_value.__truediv__.return_value = mock_voicerun_dir

            # Simulate agent.lock with agent ID
            mock_load_lock.return_value = {"id": "test-agent-id-123", "functionId": "func-id"}

            mock_org_repo = Mock()
            mock_org_repo.get.return_value = mock_organization_secrets_list
            mock_org_repo_class.return_value = mock_org_repo

            mock_agent_repo = Mock()
            mock_agent_repo.get_by_id.return_value = mock_agent
            mock_agent_repo_class.return_value = mock_agent_repo

            mock_agent_secret_repo = Mock()
            mock_agent_secret_repo.get.return_value = mock_secrets_list
            mock_agent_secret_repo_class.return_value = mock_agent_secret_repo

            result = runner.invoke(app, ["get", "secrets"])

        assert result.exit_code == 0
        # Org secrets
        assert "Organization Secrets" in result.output
        assert "ORG_DATABASE_URL" in result.output
        # Agent secrets
        assert "Secrets for Agent" in result.output
        assert "DATABASE_URL" in result.output

    def test_get_secrets_with_agent_lock_no_agent_secrets(self, mock_user, mock_agent, mock_organization_secrets_list):
        """Should show message when agent has no secrets."""
        with patch("vr_cli.commands.get.get_effective_organization_id") as mock_get_org, \
             patch("vr_cli.commands.get.OrganizationSecretRepository") as mock_org_repo_class, \
             patch("vr_cli.commands.get.AgentRepository") as mock_agent_repo_class, \
             patch("vr_cli.commands.get.AgentSecretRepository") as mock_agent_secret_repo_class, \
             patch("vr_cli.commands.get.Path") as mock_path, \
             patch("vr_cli.commands.get.load_agent_lock") as mock_load_lock:

            mock_get_org.return_value = mock_user.organization_id

            mock_voicerun_dir = Mock()
            mock_voicerun_dir.exists.return_value = True
            mock_path.cwd.return_value.__truediv__.return_value = mock_voicerun_dir

            mock_load_lock.return_value = {"id": "test-agent-id-123"}

            mock_org_repo = Mock()
            mock_org_repo.get.return_value = mock_organization_secrets_list
            mock_org_repo_class.return_value = mock_org_repo

            mock_agent_repo = Mock()
            mock_agent_repo.get_by_id.return_value = mock_agent
            mock_agent_repo_class.return_value = mock_agent_repo

            mock_agent_secret_repo = Mock()
            mock_agent_secret_repo.get.return_value = []
            mock_agent_secret_repo_class.return_value = mock_agent_secret_repo

            result = runner.invoke(app, ["get", "secrets"])

        assert result.exit_code == 0
        assert "Organization Secrets" in result.output
        assert "No secrets found for agent" in result.output


# ============================================================================
# Help Output Tests
# ============================================================================


class TestGetHelp:
    """Tests for get command help output."""

    def test_get_help(self):
        """Should show help for get command."""
        result = runner.invoke(app, ["get", "--help"])

        assert result.exit_code == 0
        assert "agents" in result.output
        assert "functions" in result.output
        assert "environments" in result.output
        assert "secrets" in result.output

    def test_get_agents_help(self):
        """Should show help for get agents command."""
        result = runner.invoke(app, ["get", "agents", "--help"])

        assert result.exit_code == 0
        assert "List all agents" in result.output

    def test_get_functions_help(self):
        """Should show help for get functions command."""
        result = runner.invoke(app, ["get", "functions", "--help"])

        assert result.exit_code == 0
        assert "Agent name or ID" in result.output

    def test_get_environments_help(self):
        """Should show help for get environments command."""
        result = runner.invoke(app, ["get", "environments", "--help"])

        assert result.exit_code == 0
        assert "Agent name or ID" in result.output

    def test_get_secrets_help(self):
        """Should show help for get secrets command."""
        result = runner.invoke(app, ["get", "secrets", "--help"])

        assert result.exit_code == 0
        assert "Agent name or ID" in result.output

    def test_get_phonenumbers_help(self):
        """Should show help for get phonenumbers command."""
        result = runner.invoke(app, ["get", "phonenumbers", "--help"])

        assert result.exit_code == 0
        assert "List organization phone numbers" in result.output

    def test_get_telephony_help(self):
        """Should show help for get telephony command."""
        result = runner.invoke(app, ["get", "telephony", "--help"])

        assert result.exit_code == 0
        assert "List organization telephony providers" in result.output


# ============================================================================
# Get Phone Numbers Tests
# ============================================================================


class TestGetPhoneNumbers:
    """Tests for get phonenumbers command."""

    def test_get_phonenumbers_lists_all(self, mock_user, mock_phone_numbers_list):
        """Should list all phone numbers."""
        with patch("vr_cli.commands.get.get_effective_organization_id") as mock_get_org, \
             patch("vr_cli.commands.get.OrganizationPhoneNumberRepository") as mock_repo_class:

            mock_get_org.return_value = mock_user.organization_id

            mock_repo = Mock()
            mock_repo.get.return_value = mock_phone_numbers_list
            mock_repo_class.return_value = mock_repo

            result = runner.invoke(app, ["get", "phonenumbers"])

        assert result.exit_code == 0
        assert "+15551111111" in result.output
        assert "+15552222222" in result.output
        assert "Sales" in result.output
        assert "Support" in result.output
        assert "pn-1" in result.output
        assert "pn-2" in result.output

    def test_get_phonenumbers_empty(self, mock_user):
        """Should show message when no phone numbers found."""
        with patch("vr_cli.commands.get.get_effective_organization_id") as mock_get_org, \
             patch("vr_cli.commands.get.OrganizationPhoneNumberRepository") as mock_repo_class:

            mock_get_org.return_value = mock_user.organization_id

            mock_repo = Mock()
            mock_repo.get.return_value = []
            mock_repo_class.return_value = mock_repo

            result = runner.invoke(app, ["get", "phonenumbers"])

        assert result.exit_code == 0
        assert "No phone numbers found" in result.output

    def test_get_phonenumbers_no_organization(self):
        """Should fail when unable to determine organization."""
        with patch("vr_cli.commands.get.get_effective_organization_id") as mock_get_org:
            mock_get_org.return_value = None

            result = runner.invoke(app, ["get", "phonenumbers"])

        assert result.exit_code != 0
        assert "Unable to determine organization" in result.output

    def test_get_phonenumbers_handles_none_values(self, mock_user):
        """Should handle phone numbers with None values."""
        phone_numbers = [
            OrganizationPhoneNumber(
                id="pn-1",
                phone_number="+15551111111",
                friendly_name=None,
                area_code=None,
                country_code=None,
            )
        ]

        with patch("vr_cli.commands.get.get_effective_organization_id") as mock_get_org, \
             patch("vr_cli.commands.get.OrganizationPhoneNumberRepository") as mock_repo_class:

            mock_get_org.return_value = mock_user.organization_id

            mock_repo = Mock()
            mock_repo.get.return_value = phone_numbers
            mock_repo_class.return_value = mock_repo

            result = runner.invoke(app, ["get", "phonenumbers"])

        assert result.exit_code == 0
        assert "N/A" in result.output

    def test_get_phonenumber_alias(self, mock_user):
        """Should work with singular phonenumber alias."""
        with patch("vr_cli.commands.get.get_effective_organization_id") as mock_get_org, \
             patch("vr_cli.commands.get.OrganizationPhoneNumberRepository") as mock_repo_class:

            mock_get_org.return_value = mock_user.organization_id

            mock_repo = Mock()
            mock_repo.get.return_value = []
            mock_repo_class.return_value = mock_repo

            result = runner.invoke(app, ["get", "phonenumber"])

        assert result.exit_code == 0


# ============================================================================
# Get Telephony Tests
# ============================================================================


class TestGetTelephony:
    """Tests for get telephony command."""

    def test_get_telephony_lists_all(self, mock_user, mock_telephony_list):
        """Should list all telephony providers."""
        with patch("vr_cli.commands.get.get_effective_organization_id") as mock_get_org, \
             patch("vr_cli.commands.get.OrganizationTelephonyRepository") as mock_repo_class:

            mock_get_org.return_value = mock_user.organization_id

            mock_repo = Mock()
            mock_repo.get.return_value = mock_telephony_list
            mock_repo_class.return_value = mock_repo

            result = runner.invoke(app, ["get", "telephony"])

        assert result.exit_code == 0
        assert "Twilio Prod" in result.output
        assert "Telnyx Dev" in result.output
        assert "tel-1" in result.output
        assert "tel-2" in result.output
        assert "twilio" in result.output
        assert "telnyx" in result.output

    def test_get_telephony_empty(self, mock_user):
        """Should show message when no telephony providers found."""
        with patch("vr_cli.commands.get.get_effective_organization_id") as mock_get_org, \
             patch("vr_cli.commands.get.OrganizationTelephonyRepository") as mock_repo_class:

            mock_get_org.return_value = mock_user.organization_id

            mock_repo = Mock()
            mock_repo.get.return_value = []
            mock_repo_class.return_value = mock_repo

            result = runner.invoke(app, ["get", "telephony"])

        assert result.exit_code == 0
        assert "No telephony providers found" in result.output

    def test_get_telephony_no_organization(self):
        """Should fail when unable to determine organization."""
        with patch("vr_cli.commands.get.get_effective_organization_id") as mock_get_org:
            mock_get_org.return_value = None

            result = runner.invoke(app, ["get", "telephony"])

        assert result.exit_code != 0
        assert "Unable to determine organization" in result.output

    def test_get_telephony_handles_none_values(self, mock_user):
        """Should handle telephony providers with None values."""
        providers = [
            OrganizationTelephony(
                id="tel-1",
                name=None,
                provider_type=None,
            )
        ]

        with patch("vr_cli.commands.get.get_effective_organization_id") as mock_get_org, \
             patch("vr_cli.commands.get.OrganizationTelephonyRepository") as mock_repo_class:

            mock_get_org.return_value = mock_user.organization_id

            mock_repo = Mock()
            mock_repo.get.return_value = providers
            mock_repo_class.return_value = mock_repo

            result = runner.invoke(app, ["get", "telephony"])

        assert result.exit_code == 0
        assert "N/A" in result.output

    def test_get_telephonies_alias(self, mock_user):
        """Should work with telephonies alias."""
        with patch("vr_cli.commands.get.get_effective_organization_id") as mock_get_org, \
             patch("vr_cli.commands.get.OrganizationTelephonyRepository") as mock_repo_class:

            mock_get_org.return_value = mock_user.organization_id

            mock_repo = Mock()
            mock_repo.get.return_value = []
            mock_repo_class.return_value = mock_repo

            result = runner.invoke(app, ["get", "telephonies"])

        assert result.exit_code == 0


# ============================================================================
# Get Templates Tests
# ============================================================================


class TestGetTemplates:
    """Tests for get templates command."""

    def test_get_templates_lists_all(self, mock_templates_list):
        """Should list all templates in a table."""
        with patch("vr_cli.commands.get.AgentTemplateRepository") as mock_repo_class:
            mock_repo = Mock()
            mock_repo.get.return_value = mock_templates_list
            mock_repo_class.return_value = mock_repo

            result = runner.invoke(app, ["get", "templates"])

        assert result.exit_code == 0
        assert "Template One" in result.output
        assert "Template Two" in result.output
        assert "tmpl-1" in result.output
        assert "tmpl-2" in result.output
        assert "support" in result.output
        assert "sales" in result.output

    def test_get_templates_empty(self):
        """Should show message when no templates found."""
        with patch("vr_cli.commands.get.AgentTemplateRepository") as mock_repo_class:
            mock_repo = Mock()
            mock_repo.get.return_value = []
            mock_repo_class.return_value = mock_repo

            result = runner.invoke(app, ["get", "templates"])

        assert result.exit_code == 0
        assert "No templates found" in result.output

    def test_get_templates_handles_none_values(self):
        """Should handle templates with None values."""
        templates = [
            AgentTemplate(
                id="tmpl-1",
                name="Test Template",
                description=None,
                category=None,
                is_public=True,
            )
        ]

        with patch("vr_cli.commands.get.AgentTemplateRepository") as mock_repo_class:
            mock_repo = Mock()
            mock_repo.get.return_value = templates
            mock_repo_class.return_value = mock_repo

            result = runner.invoke(app, ["get", "templates"])

        assert result.exit_code == 0
        assert "N/A" in result.output

    def test_get_templates_truncates_description(self):
        """Should truncate long descriptions."""
        templates = [
            AgentTemplate(
                id="tmpl-1",
                name="Test Template",
                description="A" * 50,
                category="test",
                is_public=True,
            )
        ]

        with patch("vr_cli.commands.get.AgentTemplateRepository") as mock_repo_class:
            mock_repo = Mock()
            mock_repo.get.return_value = templates
            mock_repo_class.return_value = mock_repo

            result = runner.invoke(app, ["get", "templates"])

        assert result.exit_code == 0
        assert "..." in result.output

    def test_get_templates_shows_public_status(self, mock_templates_list):
        """Should show public/private status."""
        with patch("vr_cli.commands.get.AgentTemplateRepository") as mock_repo_class:
            mock_repo = Mock()
            mock_repo.get.return_value = mock_templates_list
            mock_repo_class.return_value = mock_repo

            result = runner.invoke(app, ["get", "templates"])

        assert result.exit_code == 0
        assert "Yes" in result.output
        assert "No" in result.output

    def test_get_template_alias(self):
        """Should work with singular template alias."""
        with patch("vr_cli.commands.get.AgentTemplateRepository") as mock_repo_class:
            mock_repo = Mock()
            mock_repo.get.return_value = []
            mock_repo_class.return_value = mock_repo

            result = runner.invoke(app, ["get", "template"])

        assert result.exit_code == 0

    def test_get_templates_help(self):
        """Should show help for get templates command."""
        result = runner.invoke(app, ["get", "templates", "--help"])

        assert result.exit_code == 0
        assert "List available agent templates" in result.output
