"""FRSME-MPL004 — service-offering facet, relevance ranking, unified search."""
from __future__ import annotations

import pytest
from django.contrib.auth import get_user_model
from django.urls import reverse

from apps.core.permissions.roles import UserRole
from apps.smehub.linkage import services
from apps.smehub.linkage.models import ServiceProviderEntry
from apps.smehub.marketplace.models import BuyerRegistryEntry
from apps.smehub.onboarding.models import EntrepreneurProfile

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


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


@pytest.fixture
def entrepreneur(admin):
    user = User.objects.create_user(
        email="ent-mpl4@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 user


def _provider(admin, *, name, offerings, description="A provider."):
    user = User.objects.create_user(
        email=f"prov-{name.lower().replace(' ', '')}@example.com", password="x",
        role=UserRole.SERVICE_PROVIDER,
    )
    entry = services.create_directory_entry(
        kind="service_provider", managed_by=user, organisation_name=name,
        org_type=ServiceProviderEntry.OrgType.CORPORATE, service_offerings=offerings,
        contact_email="x@x.example", description=description, areas_of_interest="x",
    )
    services.verify_directory_entry(entry, by_user=admin)
    return ServiceProviderEntry.objects.get(pk=entry.pk)


def test_service_offering_facet_filters(client, admin, entrepreneur):
    _provider(admin, name="Finance Pros", offerings=["finance"])
    _provider(admin, name="Legal Eagles", offerings=["legal"])
    client.force_login(entrepreneur)
    url = reverse("smehub_linkage:service_provider_list")
    resp = client.get(url, {"service_offering": "finance"})
    names = [e.organisation_name for e in resp.context["entries"]]
    assert "Finance Pros" in names
    assert "Legal Eagles" not in names


def test_relevance_ranks_name_hit_above_description_hit(client, admin, entrepreneur):
    # "Alpha" only in the description of a provider named Zeta Advisory…
    _provider(admin, name="Zeta Advisory", offerings=["legal"], description="We do Alpha work.")
    # …and in the name of another provider (should rank first for query "Alpha").
    _provider(admin, name="Alpha Consulting", offerings=["legal"], description="Generic.")
    client.force_login(entrepreneur)
    url = reverse("smehub_linkage:service_provider_list")
    resp = client.get(url, {"q": "Alpha"})
    entries = list(resp.context["entries"])
    assert len(entries) == 2
    assert entries[0].organisation_name == "Alpha Consulting"


def test_unified_search_spans_all_three_directories(client, admin, entrepreneur):
    _provider(admin, name="Nexus Providers", offerings=["finance"], description="Nexus services.")
    # A verified partner + buyer sharing the keyword.
    partner_user = User.objects.create_user(
        email="partner-mpl4@example.com", password="x", role=UserRole.PARTNER,
    )
    partner = services.create_directory_entry(
        kind="partner", managed_by=partner_user, organisation_name="Nexus Partner",
        org_type=ServiceProviderEntry.OrgType.CORPORATE, contact_email="p@p.example",
        description="x", areas_of_interest="x",
    )
    services.verify_directory_entry(partner, by_user=admin)
    buyer_user = User.objects.create_user(
        email="buyer-mpl4@example.com", password="x", role=UserRole.BUYER,
    )
    buyer = BuyerRegistryEntry.objects.create(
        user=buyer_user, organisation_name="Nexus Buyer",
        org_type=BuyerRegistryEntry.OrgType.WHOLESALE,
    )
    buyer.verify(by_user=admin)
    buyer.save()

    client.force_login(entrepreneur)
    resp = client.get(reverse("smehub_linkage:directory_search"), {"q": "Nexus"})
    assert resp.status_code == 200
    provider_names = [e.organisation_name for e in resp.context["providers"]]
    partner_names = [e.organisation_name for e in resp.context["partners"]]
    buyer_names = [e.organisation_name for e in resp.context["buyers"]]
    assert "Nexus Providers" in provider_names
    assert "Nexus Partner" in partner_names
    assert "Nexus Buyer" in buyer_names
    assert resp.context["total"] == 3
