"""Regression tests for the smehub_status_badge template tag.

Two layers:
  1. Snapshot of (kind, status) -> (variant, label) so colour/label drift is caught.
  2. Model-choices coverage — every choice on each badged field must resolve to a
     non-fallback entry in its table, so adding a new enum member without updating
     the badge map fails loudly.
"""
import pytest
from django.template import Context, Template

from apps.smehub.onboarding.templatetags.smehub_tags import (
    BUSINESS_VERIFICATION,
    CALL,
    CHALLENGE,
    COHORT_MEMBER,
    CONNECTION_REQUEST,
    DEAL_ROOM,
    DEMAND_RESPONSE,
    ENTREPRENEUR_VERIFICATION,
    EVALUATOR_ASSIGNMENT,
    EVENT,
    FUNDING_APPLICATION,
    INCUBATION_APPLICATION,
    INNOVATION_LIFECYCLE,
    MARKET_DEMAND,
    MOU,
    PRODUCT_AVAILABILITY,
    RECOMMENDATION,
    SALES_RECORD,
    SESSION,
    SHOWCASING_APPLICATION,
    VERIFICATION,
)


def _render(value, kind):
    tpl = Template("{% load smehub_tags %}{% smehub_status_badge value kind %}")
    return tpl.render(Context({"value": value, "kind": kind}))


# ── Layer 1: snapshot (a change here is a deliberate design decision) ───────

@pytest.mark.parametrize(
    "kind,status,variant,label",
    [
        ("incubation_application", "draft", "amber", "Draft"),
        ("incubation_application", "returned_for_info", "amber", "Returned for info"),
        ("incubation_application", "accepted", "green", "Accepted"),
        ("incubation_application", "rejected", "red", "Not selected"),
        ("funding_application", "submitted", "primary", "Submitted"),
        ("funding_application", "rejected", "red", "Rejected"),
        ("funding_call", "published", "green", "Published"),
        ("funding_call", "closed", "neutral", "Closed"),
        ("programme_public", "published", "green", "Open"),
        ("verification", "pending", "amber", "Pending"),
        ("verification", "verified", "green", "Verified"),
        ("verification", "deactivated", "neutral", "Deactivated"),
        ("business_verification", "pending_admin_review", "neutral", "Pending review"),
        ("business_verification", "revoked", "red", "Revoked"),
        ("entrepreneur_verification", "pending_more_info", "amber", "More info requested"),
        ("connection_request", "declined", "red", "Declined"),
        ("demand_response", "shortlisted", "primary", "Shortlisted"),
        ("demand_response", "awarded", "green", "Awarded"),
        ("market_demand", "awarded", "sky", "Awarded"),
        ("sales_record", "disputed", "red", "Disputed"),
        ("product_availability", "in_stock", "green", "In stock"),
        ("innovation_lifecycle", "under_vetting", "amber", "Under vetting"),
        ("showcasing_application", "confirmed", "green", "Confirmed"),
        ("showcasing_application", "rejected", "amber", "Rejected"),
        ("deal_room", "agreement_reached", "sky", "Agreement reached"),
        ("challenge", "announced", "green", "Winners announced"),
        ("event", "live", "green", "Live"),
        ("mou", "formalised", "green", "Formalised"),
        ("session", "cancelled", "red", "Cancelled"),
        ("recommendation", "adopted", "green", "Adopted"),
        ("evaluator_assignment", "completed", "green", "Completed"),
        ("cohort_member", "programme_complete", "green", "Complete"),
    ],
)
def test_status_badge_snapshot(kind, status, variant, label):
    rendered = _render(status, kind)
    assert f"badge-{variant}" in rendered, rendered
    assert f">{label}<" in rendered, rendered


def test_unknown_status_prettified_neutral():
    rendered = _render("never_seen_before", "incubation_application")
    assert "badge-neutral" in rendered
    assert "Never seen before" in rendered


def test_accepts_object_with_status_attr():
    class _Obj:
        status = "accepted"

    rendered = _render(_Obj(), "incubation_application")
    assert "badge-green" in rendered
    assert ">Accepted<" in rendered


def test_empty_value_renders_dash():
    assert "—" in _render("", "incubation_application")


# ── Layer 2: model-choices coverage ────────────────────────────────────────

def _choices(model_cls, field):
    return {v for v, _ in model_cls._meta.get_field(field).choices}


@pytest.mark.django_db
@pytest.mark.parametrize(
    "import_path,field,table",
    [
        ("apps.smehub.incubation.models.Application", "status", INCUBATION_APPLICATION),
        ("apps.smehub.investment.models.FundingApplication", "status", FUNDING_APPLICATION),
        ("apps.smehub.investment.models.FundingCall", "status", CALL),
        ("apps.smehub.incubation.models.Programme", "status", CALL),
        ("apps.smehub.investment.models.Investor", "verification_status", VERIFICATION),
        ("apps.smehub.marketplace.models.BuyerRegistryEntry", "verification_status", VERIFICATION),
        ("apps.smehub.onboarding.models.Business", "verification_status", BUSINESS_VERIFICATION),
        ("apps.smehub.onboarding.models.EntrepreneurProfile", "verification_status", ENTREPRENEUR_VERIFICATION),
        ("apps.smehub.linkage.models.ConnectionRequest", "status", CONNECTION_REQUEST),
        ("apps.smehub.investment.models.InvestorConnectionRequest", "status", CONNECTION_REQUEST),
        ("apps.smehub.marketplace.models.DemandResponse", "status", DEMAND_RESPONSE),
        ("apps.smehub.marketplace.models.MarketDemandListing", "status", MARKET_DEMAND),
        ("apps.smehub.marketplace.models.SalesRecord", "status", SALES_RECORD),
        ("apps.smehub.marketplace.models.ProductListing", "availability", PRODUCT_AVAILABILITY),
        ("apps.smehub.onboarding.models.Innovation", "lifecycle_status", INNOVATION_LIFECYCLE),
        ("apps.smehub.showcasing.models.ShowcaseApplication", "status", SHOWCASING_APPLICATION),
        ("apps.smehub.showcasing.models.DealRoom", "status", DEAL_ROOM),
        ("apps.smehub.showcasing.models.InnovationChallenge", "status", CHALLENGE),
        ("apps.smehub.showcasing.models.ShowcaseEvent", "status", EVENT),
        ("apps.smehub.linkage.models.MoU", "status", MOU),
        ("apps.smehub.linkage.models.AdvisorySession", "status", SESSION),
        ("apps.smehub.linkage.models.OrganisationRecommendation", "status", RECOMMENDATION),
        ("apps.smehub.onboarding.models.EvaluatorAssignment", "status", EVALUATOR_ASSIGNMENT),
        ("apps.smehub.incubation.models.CohortMember", "status", COHORT_MEMBER),
    ],
)
def test_model_choices_all_mapped(import_path, field, table):
    module_path, cls_name = import_path.rsplit(".", 1)
    import importlib

    model_cls = getattr(importlib.import_module(module_path), cls_name)
    missing = _choices(model_cls, field) - set(table)
    assert not missing, f"{cls_name}.{field} values missing from badge table: {missing}"
