# app/modules/billing/tests/unit/test_store_platform_sync.py
"""Unit tests for StorePlatformSync service."""

from datetime import UTC, datetime, timedelta

import pytest

from app.modules.billing.models import (
    MerchantSubscription,
    SubscriptionStatus,
    SubscriptionTier,
)
from app.modules.billing.services.store_platform_sync_service import StorePlatformSync
from app.modules.tenancy.models import StorePlatform


@pytest.mark.unit
@pytest.mark.billing
class TestStorePlatformSyncCreate:
    """Tests for creating StorePlatform entries via sync."""

    def setup_method(self):
        self.service = StorePlatformSync()

    def test_sync_creates_store_platform(self, db, test_store, test_platform):
        """Sync with is_active=True creates a new StorePlatform entry."""
        self.service.sync_store_platforms_for_merchant(
            db, test_store.merchant_id, test_platform.id, is_active=True
        )

        sp = (
            db.query(StorePlatform)
            .filter(
                StorePlatform.store_id == test_store.id,
                StorePlatform.platform_id == test_platform.id,
            )
            .first()
        )
        assert sp is not None
        assert sp.is_active is True

    def test_sync_sets_tier_id(self, db, test_store, test_platform, sync_tier):
        """Sync passes tier_id to newly created StorePlatform."""
        self.service.sync_store_platforms_for_merchant(
            db, test_store.merchant_id, test_platform.id,
            is_active=True, tier_id=sync_tier.id,
        )

        sp = (
            db.query(StorePlatform)
            .filter(
                StorePlatform.store_id == test_store.id,
                StorePlatform.platform_id == test_platform.id,
            )
            .first()
        )
        assert sp.tier_id == sync_tier.id


@pytest.mark.unit
@pytest.mark.billing
class TestStorePlatformSyncUpdate:
    """Tests for updating existing StorePlatform entries via sync."""

    def setup_method(self):
        self.service = StorePlatformSync()

    def test_sync_updates_existing_is_active(self, db, test_store, test_platform):
        """Sync updates is_active on existing StorePlatform."""
        # Create initial entry
        sp = StorePlatform(
            store_id=test_store.id,
            platform_id=test_platform.id,
            is_active=True,
        )
        db.add(sp)
        db.flush()

        # Deactivate via sync
        self.service.sync_store_platforms_for_merchant(
            db, test_store.merchant_id, test_platform.id, is_active=False
        )

        db.refresh(sp)
        assert sp.is_active is False

    def test_sync_updates_tier_id(self, db, test_store, test_platform, sync_tier):
        """Sync updates tier_id on existing StorePlatform."""
        sp = StorePlatform(
            store_id=test_store.id,
            platform_id=test_platform.id,
            is_active=True,
        )
        db.add(sp)
        db.flush()

        self.service.sync_store_platforms_for_merchant(
            db, test_store.merchant_id, test_platform.id,
            is_active=True, tier_id=sync_tier.id,
        )

        db.refresh(sp)
        assert sp.tier_id == sync_tier.id


@pytest.mark.unit
@pytest.mark.billing
class TestStorePlatformSyncEdgeCases:
    """Tests for edge cases in sync."""

    def setup_method(self):
        self.service = StorePlatformSync()

    def test_sync_noop_inactive_missing(self, db, test_store, test_platform):
        """Sync with is_active=False for non-existent entry is a no-op."""
        self.service.sync_store_platforms_for_merchant(
            db, test_store.merchant_id, test_platform.id, is_active=False
        )

        sp = (
            db.query(StorePlatform)
            .filter(
                StorePlatform.store_id == test_store.id,
                StorePlatform.platform_id == test_platform.id,
            )
            .first()
        )
        assert sp is None

    def test_sync_no_stores(self, db, test_platform):
        """Sync with no stores for merchant is a no-op (no error)."""
        self.service.sync_store_platforms_for_merchant(
            db, 99999, test_platform.id, is_active=True
        )
        # No assertion needed — just verifying no exception

    def test_sync_multiple_stores(self, db, test_merchant, test_platform):
        """Sync creates entries for all stores of a merchant."""
        from app.modules.tenancy.models import Store

        store1 = Store(
            merchant_id=test_merchant.id,
            store_code="SYNC_TEST_1",
            name="Sync Store 1",
            subdomain="sync-test-1",
            is_active=True,
            is_verified=True,
            created_at=datetime.now(UTC),
            updated_at=datetime.now(UTC),
        )
        store2 = Store(
            merchant_id=test_merchant.id,
            store_code="SYNC_TEST_2",
            name="Sync Store 2",
            subdomain="sync-test-2",
            is_active=True,
            is_verified=True,
            created_at=datetime.now(UTC),
            updated_at=datetime.now(UTC),
        )
        db.add_all([store1, store2])
        db.flush()

        self.service.sync_store_platforms_for_merchant(
            db, test_merchant.id, test_platform.id, is_active=True
        )

        count = (
            db.query(StorePlatform)
            .filter(
                StorePlatform.platform_id == test_platform.id,
                StorePlatform.store_id.in_([store1.id, store2.id]),
            )
            .count()
        )
        assert count == 2


# ============================================================================
# Fixtures
# ============================================================================


@pytest.fixture
def sync_tier(db, test_platform):
    """Create a tier for sync tests."""
    tier = SubscriptionTier(
        platform_id=test_platform.id,
        code="essential",
        name="Essential",
        price_monthly_cents=2900,
        display_order=1,
        is_active=True,
        is_public=True,
    )
    db.add(tier)
    db.commit()
    db.refresh(tier)
    return tier
