# app/modules/tenancy/tests/unit/test_tenancy_metrics.py
"""Unit tests for TenancyMetricsProvider.get_merchant_metrics."""

import uuid

import pytest

from app.modules.tenancy.models import Merchant, Store, StoreUser, User
from app.modules.tenancy.services.tenancy_metrics import TenancyMetricsProvider


@pytest.fixture
def metrics_merchant(db):
    """Create a merchant owner and merchant for metrics tests."""
    from middleware.auth import AuthManager

    auth = AuthManager()
    user = User(
        email=f"metricsowner_{uuid.uuid4().hex[:8]}@test.com",
        username=f"metricsowner_{uuid.uuid4().hex[:8]}",
        hashed_password=auth.hash_password("pass123"),
        role="merchant_owner",
        is_active=True,
    )
    db.add(user)
    db.flush()

    merchant = Merchant(
        name="Metrics Test Merchant",
        owner_user_id=user.id,
        contact_email=user.email,
        is_active=True,
        is_verified=True,
    )
    db.add(merchant)
    db.commit()
    db.refresh(merchant)
    return merchant


@pytest.fixture
def metrics_stores(db, metrics_merchant):
    """Create 3 stores (2 active, 1 inactive) for the merchant."""
    stores = []
    for i, active in enumerate([True, True, False]):
        uid = uuid.uuid4().hex[:8].upper()
        store = Store(
            merchant_id=metrics_merchant.id,
            store_code=f"MSTORE_{uid}",
            subdomain=f"mstore{uid.lower()}",
            name=f"Metrics Store {i}",
            is_active=active,
            is_verified=True,
        )
        db.add(store)
        stores.append(store)
    db.commit()
    for s in stores:
        db.refresh(s)
    return stores


@pytest.fixture
def metrics_team_members(db, metrics_stores):
    """Create team members across merchant stores."""
    from middleware.auth import AuthManager

    auth = AuthManager()
    users = []
    for i in range(3):
        users.append(User(
            email=f"team_{uuid.uuid4().hex[:8]}@test.com",
            username=f"team_{uuid.uuid4().hex[:8]}",
            hashed_password=auth.hash_password("pass123"),
            role="store_user",
            is_active=True,
        ))
    db.add_all(users)
    db.flush()

    # User 0 on store 0 and store 1 (should be counted once)
    db.add(StoreUser(store_id=metrics_stores[0].id, user_id=users[0].id, is_active=True))
    db.add(StoreUser(store_id=metrics_stores[1].id, user_id=users[0].id, is_active=True))
    # User 1 on store 0 only
    db.add(StoreUser(store_id=metrics_stores[0].id, user_id=users[1].id, is_active=True))
    # User 2 on store 0 but inactive
    db.add(StoreUser(store_id=metrics_stores[0].id, user_id=users[2].id, is_active=False))
    db.commit()
    return users


@pytest.mark.unit
@pytest.mark.tenancy
class TestTenancyMetricsProviderMerchant:
    """Tests for TenancyMetricsProvider.get_merchant_metrics."""

    def setup_method(self):
        self.provider = TenancyMetricsProvider()

    def test_total_stores(self, db, metrics_merchant, metrics_stores):
        """Returns correct total store count for merchant."""
        metrics = self.provider.get_merchant_metrics(db, metrics_merchant.id)
        by_key = {m.key: m.value for m in metrics}
        assert by_key["tenancy.total_stores"] == 3

    def test_active_stores(self, db, metrics_merchant, metrics_stores):
        """Returns correct active store count (excludes inactive)."""
        metrics = self.provider.get_merchant_metrics(db, metrics_merchant.id)
        by_key = {m.key: m.value for m in metrics}
        assert by_key["tenancy.active_stores"] == 2

    def test_team_members_distinct(self, db, metrics_merchant, metrics_stores, metrics_team_members):
        """Counts distinct active team members across stores."""
        metrics = self.provider.get_merchant_metrics(db, metrics_merchant.id)
        by_key = {m.key: m.value for m in metrics}
        # 2 active distinct users (user 0 on 2 stores counted once, user 1, user 2 inactive)
        assert by_key["tenancy.team_members"] == 2

    def test_no_stores(self, db, metrics_merchant):
        """Returns zero counts when merchant has no stores."""
        metrics = self.provider.get_merchant_metrics(db, metrics_merchant.id)
        by_key = {m.key: m.value for m in metrics}
        assert by_key["tenancy.total_stores"] == 0
        assert by_key["tenancy.active_stores"] == 0
        assert by_key["tenancy.team_members"] == 0

    def test_nonexistent_merchant(self, db):
        """Returns zero counts for a non-existent merchant ID."""
        metrics = self.provider.get_merchant_metrics(db, 999999)
        by_key = {m.key: m.value for m in metrics}
        assert by_key["tenancy.total_stores"] == 0
