"""
Unit tests for tenant resolution logic.

Tests TNNT-02: Inbound messages are resolved to the correct tenant via
channel metadata.

These tests verify the resolution logic in isolation — no live database needed.
The production resolver queries channel_connections; here we mock that lookup.
"""

from __future__ import annotations

import uuid
from typing import Optional

import pytest

from shared.models.message import ChannelType


# ---------------------------------------------------------------------------
# Minimal in-process tenant resolver for unit testing
# ---------------------------------------------------------------------------

class ChannelConnectionRecord:
    """Represents a row from the channel_connections table."""

    def __init__(self, tenant_id: uuid.UUID, channel_type: ChannelType, workspace_id: str) -> None:
        self.tenant_id = tenant_id
        self.channel_type = channel_type
        self.workspace_id = workspace_id


def resolve_tenant(
    workspace_id: str,
    channel_type: ChannelType,
    connections: list[ChannelConnectionRecord],
) -> Optional[uuid.UUID]:
    """
    Resolve a (workspace_id, channel_type) pair to a tenant_id.

    This mirrors the logic in packages/router/tenant.py.
    Returns None if no matching connection is found.
    """
    for conn in connections:
        if conn.workspace_id == workspace_id and conn.channel_type == channel_type:
            return conn.tenant_id
    return None


# ---------------------------------------------------------------------------
# Test fixtures
# ---------------------------------------------------------------------------

@pytest.fixture
def tenant_a_id() -> uuid.UUID:
    return uuid.UUID("aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa")


@pytest.fixture
def tenant_b_id() -> uuid.UUID:
    return uuid.UUID("bbbbbbbb-bbbb-bbbb-bbbb-bbbbbbbbbbbb")


@pytest.fixture
def connections(tenant_a_id: uuid.UUID, tenant_b_id: uuid.UUID) -> list[ChannelConnectionRecord]:
    return [
        ChannelConnectionRecord(tenant_a_id, ChannelType.SLACK, "T-WORKSPACE-A"),
        ChannelConnectionRecord(tenant_b_id, ChannelType.SLACK, "T-WORKSPACE-B"),
        ChannelConnectionRecord(tenant_b_id, ChannelType.TELEGRAM, "tg-chat-12345"),
    ]


# ---------------------------------------------------------------------------
# Tests
# ---------------------------------------------------------------------------

class TestTenantResolution:
    """Tests for tenant resolution from channel workspace IDs."""

    def test_slack_workspace_resolves_to_correct_tenant(
        self,
        connections: list[ChannelConnectionRecord],
        tenant_a_id: uuid.UUID,
    ) -> None:
        """Known Slack workspace_id must resolve to the correct tenant."""
        result = resolve_tenant("T-WORKSPACE-A", ChannelType.SLACK, connections)
        assert result == tenant_a_id

    def test_second_slack_workspace_resolves_independently(
        self,
        connections: list[ChannelConnectionRecord],
        tenant_b_id: uuid.UUID,
    ) -> None:
        """Two different Slack workspaces must resolve to their respective tenants."""
        result = resolve_tenant("T-WORKSPACE-B", ChannelType.SLACK, connections)
        assert result == tenant_b_id

    def test_unknown_workspace_id_returns_none(
        self,
        connections: list[ChannelConnectionRecord],
    ) -> None:
        """Unknown workspace_id must return None — not raise, not return wrong tenant."""
        result = resolve_tenant("T-UNKNOWN", ChannelType.SLACK, connections)
        assert result is None

    def test_wrong_channel_type_does_not_match(
        self,
        connections: list[ChannelConnectionRecord],
    ) -> None:
        """Workspace ID from wrong channel type must not match."""
        # T-WORKSPACE-A is registered as SLACK — should not match TELEGRAM
        result = resolve_tenant("T-WORKSPACE-A", ChannelType.TELEGRAM, connections)
        assert result is None

    def test_telegram_workspace_resolves_correctly(
        self,
        connections: list[ChannelConnectionRecord],
        tenant_b_id: uuid.UUID,
    ) -> None:
        """Telegram channel connections resolve independently from Slack."""
        result = resolve_tenant("tg-chat-12345", ChannelType.TELEGRAM, connections)
        assert result == tenant_b_id

    def test_empty_connections_returns_none(self) -> None:
        """Empty connection list must return None for any workspace."""
        result = resolve_tenant("T-ANY", ChannelType.SLACK, [])
        assert result is None

    def test_resolution_is_channel_type_specific(
        self,
        connections: list[ChannelConnectionRecord],
    ) -> None:
        """
        The same workspace_id string registered on two different channel types
        must only match the correct channel type.

        This prevents a Slack workspace ID from accidentally matching a
        Mattermost workspace with the same string value.
        """
        same_id_connections = [
            ChannelConnectionRecord(
                uuid.UUID("cccccccc-cccc-cccc-cccc-cccccccccccc"),
                ChannelType.SLACK,
                "SHARED-ID",
            ),
            ChannelConnectionRecord(
                uuid.UUID("dddddddd-dddd-dddd-dddd-dddddddddddd"),
                ChannelType.MATTERMOST,
                "SHARED-ID",
            ),
        ]
        slack_tenant = resolve_tenant("SHARED-ID", ChannelType.SLACK, same_id_connections)
        mm_tenant = resolve_tenant("SHARED-ID", ChannelType.MATTERMOST, same_id_connections)

        assert slack_tenant != mm_tenant
        assert str(slack_tenant) == "cccccccc-cccc-cccc-cccc-cccccccccccc"
        assert str(mm_tenant) == "dddddddd-dddd-dddd-dddd-dddddddddddd"
