# app/modules/loyalty/tests/unit/test_loyalty_onboarding_service.py
"""Unit tests for LoyaltyOnboardingProvider."""

import uuid

import pytest

from app.modules.loyalty.models.loyalty_program import LoyaltyProgram, LoyaltyType
from app.modules.loyalty.services.loyalty_onboarding_service import (
    LoyaltyOnboardingProvider,
)
from app.modules.tenancy.models import Merchant, Store, User


@pytest.fixture
def loy_owner(db):
    """Create a store owner for loyalty onboarding tests."""
    from middleware.auth import AuthManager

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


@pytest.fixture
def loy_merchant(db, loy_owner):
    """Create a merchant for loyalty onboarding tests."""
    merchant = Merchant(
        name="Loyalty Onboarding Merchant",
        owner_user_id=loy_owner.id,
        contact_email=loy_owner.email,
        is_active=True,
        is_verified=True,
    )
    db.add(merchant)
    db.commit()
    db.refresh(merchant)
    return merchant


@pytest.fixture
def loy_store(db, loy_merchant):
    """Create a store (no loyalty program) for loyalty onboarding tests."""
    uid = uuid.uuid4().hex[:8]
    store = Store(
        merchant_id=loy_merchant.id,
        store_code=f"LOYONB_{uid.upper()}",
        subdomain=f"loyonb{uid.lower()}",
        name="Loyalty Onboarding Store",
        is_active=True,
        is_verified=True,
    )
    db.add(store)
    db.commit()
    db.refresh(store)
    return store


@pytest.mark.unit
@pytest.mark.loyalty
class TestLoyaltyOnboardingProvider:
    """Tests for LoyaltyOnboardingProvider."""

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

    def test_category(self):
        """Returns 'loyalty' as the onboarding category."""
        assert self.provider.onboarding_category == "loyalty"

    def test_get_onboarding_steps_returns_one_step(self):
        """Returns exactly one step: create_program."""
        steps = self.provider.get_onboarding_steps()
        assert len(steps) == 1
        assert steps[0].key == "loyalty.create_program"
        assert steps[0].order == 300

    def test_incomplete_without_program(self, db, loy_store):
        """Step is incomplete when merchant has no loyalty programs."""
        result = self.provider.is_step_completed(
            db, loy_store.id, "loyalty.create_program"
        )
        assert result is False

    def test_complete_with_program(self, db, loy_store, loy_merchant):
        """Step is complete when merchant has at least one loyalty program."""
        program = LoyaltyProgram(
            merchant_id=loy_merchant.id,
            loyalty_type=LoyaltyType.STAMPS.value,
            stamps_target=10,
            cooldown_minutes=0,
            max_daily_stamps=10,
            require_staff_pin=False,
            card_name="Test Card",
            card_color="#FF0000",
            is_active=True,
        )
        db.add(program)
        db.commit()

        result = self.provider.is_step_completed(
            db, loy_store.id, "loyalty.create_program"
        )
        assert result is True

    def test_nonexistent_store_returns_false(self, db):
        """Returns False for a store ID that doesn't exist."""
        result = self.provider.is_step_completed(
            db, 999999, "loyalty.create_program"
        )
        assert result is False

    def test_unknown_step_key_returns_false(self, db, loy_store):
        """Returns False for an unrecognized step key."""
        result = self.provider.is_step_completed(
            db, loy_store.id, "loyalty.unknown_step"
        )
        assert result is False
