"""Slice A · marketplace P0 hardening tests.

* A5 — ``publish_product`` re-checks business verification at publish time.
"""
from __future__ import annotations

import pytest
from django.contrib.auth import get_user_model

from apps.core.permissions.roles import UserRole
from apps.smehub.marketplace import services
from apps.smehub.marketplace.models import ProductListing
from apps.smehub.onboarding.models import Business, BusinessStage, EntrepreneurProfile

User = get_user_model()
pytestmark = pytest.mark.django_db


@pytest.fixture
def admin():
    return User.objects.create_user(
        email="adm-sa@example.com", password="x",
        is_superuser=True, is_staff=True, role=UserRole.SYSTEM_ADMIN,
    )


@pytest.fixture
def entrepreneur(admin):
    user = User.objects.create_user(email="ent-sa@example.com", password="x", role=UserRole.ENTREPRENEUR)
    profile = EntrepreneurProfile.objects.create(user=user, country="UG", organisation="Co")
    profile.verify(by_user=admin)
    profile.save()
    return profile


@pytest.fixture
def verified_business(entrepreneur, admin):
    biz = Business.objects.create(
        entrepreneur=entrepreneur,
        name="GrainCo",
        sector="Agriculture",
        business_stage=BusinessStage.MVP,
        country="UG",
    )
    biz.verify(by_user=admin)
    biz.save()
    return biz


def _listing(entrepreneur, business) -> ProductListing:
    return services.create_product_listing(
        entrepreneur=entrepreneur,
        business=business,
        name="Maize flour",
        description="High quality.",
        sector="Agriculture",
    )


def test_publish_product_succeeds_on_verified_business(entrepreneur, verified_business):
    listing = _listing(entrepreneur, verified_business)
    services.publish_product(listing, by_user=entrepreneur.user)
    listing.refresh_from_db()
    assert listing.status == ProductListing.Status.PUBLISHED


def test_publish_product_blocked_when_business_revoked(entrepreneur, verified_business, admin):
    listing = _listing(entrepreneur, verified_business)
    # Revoke the business after the listing was created — this is the
    # exact race the A5 fix guards against.
    verified_business.revoke(reason="Audit failure")
    verified_business.save()
    with pytest.raises(services.MarketplaceStateError):
        services.publish_product(listing, by_user=entrepreneur.user)
    listing.refresh_from_db()
    assert listing.status != ProductListing.Status.PUBLISHED


def test_publish_product_idempotent_on_already_published(entrepreneur, verified_business):
    listing = _listing(entrepreneur, verified_business)
    services.publish_product(listing, by_user=entrepreneur.user)
    # Second call short-circuits before the verification re-check.
    result = services.publish_product(listing, by_user=entrepreneur.user)
    assert result.status == ProductListing.Status.PUBLISHED
