"""Tests for analytics tools."""

import pytest
import respx
from httpx import Response

from platform_2step_mcp.tools.analytics import ANALYTICS_TOOLS, handle_analytics_tool


class TestAnalyticsToolDefinitions:
    """Test tool definitions."""

    def test_has_three_tools(self):
        assert len(ANALYTICS_TOOLS) == 3

    def test_query_tool_exists(self):
        tool_names = [t.name for t in ANALYTICS_TOOLS]
        assert "query_analytics_db" in tool_names

    def test_status_tool_exists(self):
        tool_names = [t.name for t in ANALYTICS_TOOLS]
        assert "get_analytics_status" in tool_names

    def test_refresh_tool_exists(self):
        tool_names = [t.name for t in ANALYTICS_TOOLS]
        assert "refresh_analytics_data" in tool_names

    def test_query_tool_requires_company_id_and_sql(self):
        query_tool = next(t for t in ANALYTICS_TOOLS if t.name == "query_analytics_db")
        required = query_tool.inputSchema["required"]
        assert "company_id" in required
        assert "sql" in required

    def test_refresh_tool_requires_company_id(self):
        refresh_tool = next(t for t in ANALYTICS_TOOLS if t.name == "refresh_analytics_data")
        required = refresh_tool.inputSchema["required"]
        assert "company_id" in required

    def test_query_tool_description_includes_tables(self):
        query_tool = next(t for t in ANALYTICS_TOOLS if t.name == "query_analytics_db")
        desc = query_tool.description
        assert "bookings" in desc
        assert "services" in desc
        assert "categories" in desc
        assert "providers" in desc
        assert "locations" in desc
        assert "transactions" in desc
        assert "clients" in desc

    def test_query_tool_description_includes_examples(self):
        query_tool = next(t for t in ANALYTICS_TOOLS if t.name == "query_analytics_db")
        desc = query_tool.description
        assert "no_show" in desc.lower()
        assert "revenue" in desc.lower()


class TestQueryAnalyticsHandler:
    """Test query_analytics_db handler."""

    @pytest.mark.asyncio
    async def test_returns_markdown_table(self, client, mock_api):
        mock_api.post("/api/v1/analytics/query").mock(
            return_value=Response(
                200,
                json={
                    "columns": ["name", "count"],
                    "rows": [["Corte", 42], ["Barba", 18]],
                    "row_count": 2,
                    "truncated": False,
                    "data_as_of": "2026-02-10T15:30:00Z",
                    "sync_lag_seconds": 420,
                    "snapshot_version": "v1707577800",
                    "is_partial": False,
                },
            )
        )

        result = await handle_analytics_tool(
            "query_analytics_db",
            {"company_id": 1238, "sql": "SELECT name, count FROM services"},
            client,
        )

        assert len(result) == 1
        text = result[0].text
        assert "| name | count |" in text
        assert "| Corte | 42 |" in text
        assert "| Barba | 18 |" in text
        assert "Rows: 2" in text
        assert "v1707577800" in text

    @pytest.mark.asyncio
    async def test_warming_up_response(self, client, mock_api):
        mock_api.post("/api/v1/analytics/query").mock(
            return_value=Response(
                202,
                json={
                    "error": "warming_up",
                    "message": "Data sync in progress",
                    "estimated_wait_seconds": 12,
                },
            )
        )

        result = await handle_analytics_tool(
            "query_analytics_db",
            {"company_id": 1238, "sql": "SELECT * FROM bookings"},
            client,
        )

        assert len(result) == 1
        text = result[0].text
        assert "being prepared" in text
        assert "retry" in text.lower()

    @pytest.mark.asyncio
    async def test_empty_results(self, client, mock_api):
        mock_api.post("/api/v1/analytics/query").mock(
            return_value=Response(
                200,
                json={
                    "columns": [],
                    "rows": [],
                    "row_count": 0,
                    "truncated": False,
                    "data_as_of": "2026-02-10T15:30:00Z",
                    "sync_lag_seconds": 60,
                    "snapshot_version": "v1707577800",
                    "is_partial": False,
                },
            )
        )

        result = await handle_analytics_tool(
            "query_analytics_db",
            {"company_id": 1238, "sql": "SELECT * FROM bookings WHERE 1=0"},
            client,
        )

        assert "_No results_" in result[0].text


class TestGetAnalyticsStatusHandler:
    """Test get_analytics_status handler."""

    @pytest.mark.asyncio
    async def test_returns_json_status(self, client, mock_api):
        mock_api.get("/api/v1/analytics/status/1238").mock(
            return_value=Response(
                200,
                json={
                    "company_id": 1238,
                    "state": "READY",
                    "snapshot_version": "v1707577800",
                    "last_sync_at": "2026-02-10T15:30:00Z",
                    "sync_in_progress": False,
                    "tables_synced": ["bookings", "services"],
                    "schema_version": 2,
                },
            )
        )

        result = await handle_analytics_tool(
            "get_analytics_status",
            {"company_id": 1238},
            client,
        )

        assert len(result) == 1
        assert '"READY"' in result[0].text
        assert '"company_id": 1238' in result[0].text


class TestRefreshAnalyticsHandler:
    """Test refresh_analytics_data handler."""

    @pytest.mark.asyncio
    async def test_returns_success_message(self, client, mock_api):
        mock_api.post("/api/v1/analytics/refresh/1238").mock(
            return_value=Response(
                202,
                json={"message": "Sync enqueued successfully"},
            )
        )

        result = await handle_analytics_tool(
            "refresh_analytics_data",
            {"company_id": 1238},
            client,
        )

        assert len(result) == 1
        text = result[0].text
        assert "refresh triggered" in text.lower()
        assert "get_analytics_status" in text

    @pytest.mark.asyncio
    async def test_handles_sync_already_in_progress(self, client, mock_api):
        mock_api.post("/api/v1/analytics/refresh/1238").mock(
            return_value=Response(
                202,
                json={"message": "Sync already in progress, data will be updated shortly"},
            )
        )

        result = await handle_analytics_tool(
            "refresh_analytics_data",
            {"company_id": 1238},
            client,
        )

        assert len(result) == 1
        text = result[0].text
        assert "refresh triggered" in text.lower()

    @pytest.mark.asyncio
    async def test_handles_cooldown_conflict(self, client, mock_api):
        mock_api.post("/api/v1/analytics/refresh/1238").mock(
            return_value=Response(
                409,
                json={
                    "error": "sync_cooldown",
                    "message": "Last sync failed recently, try again in 5 minutes",
                },
            )
        )

        result = await handle_analytics_tool(
            "refresh_analytics_data",
            {"company_id": 1238},
            client,
        )

        assert len(result) == 1
        text = result[0].text
        assert "cannot refresh" in text.lower()
        assert "try again" in text.lower()


class TestErrorHandling:
    """Test error handling."""

    @pytest.mark.asyncio
    async def test_unknown_tool_raises(self, client):
        with pytest.raises(ValueError, match="Unknown analytics tool"):
            await handle_analytics_tool("unknown_tool", {}, client)
