"""Post-B2 GR-04: DiscoverySpec -> Planner semantic-loss fixes.

Each fix here recovers a case where the finalized DiscoverySpec still
contained enough information to infer the correct existing capability, but
the raw-text-tuned matcher missed Discovery's paraphrase of it. Full
classification ledger: docs/audits/fixtures/post_b2_discovery_semantic_loss.json

Every negative control below is corpus-witnessed (see the comment on each
test), not synthetic-only, per the residual-remediation brief.
"""

from src.domain.app_blocks.planner import (
    ProductIntent,
    _negated,
    _wants_appointment_booking,
    _wants_assignment,
    _wants_documents,
    _wants_product_catalog,
    _wants_task_management,
)


def test_assign_cases_without_trailing_to_selects_assignment():
    """13A-039 Discovery loss: 'Can assign cases and view all cases.'"""
    assert _wants_assignment("manager can assign cases and view all cases") is True


def test_operational_checklist_selects_task_management():
    """13A-040 Discovery loss: 'operational checklists' vs raw 'ops checklist'."""
    assert _wants_task_management("manage operational checklists for staff") is True


def test_task_entity_name_selects_task_management():
    """13A-079 Discovery loss: entity literally named 'Task', no tight phrase."""
    intent = ProductIntent(entity_names=["Business Record", "Task"])
    assert _wants_task_management("view task update status notify manager", intent) is True


def test_bare_task_word_without_entity_or_phrase_stays_narrow():
    """Generalization guard: bare 'task' prose alone must not select the block."""
    intent = ProductIntent(entity_names=["Business Record"])
    assert _wants_task_management("this is a big task for our team", intent) is False


def test_manage_documents_selects_documents():
    """13A-056 Discovery loss: 'manage documents' vs raw 'managed documents'."""
    assert _wants_documents("a platform for employees to manage documents") is True


def test_directory_of_items_without_the_selects_catalog():
    """13A-070 Discovery loss: 'directory of items' vs raw 'directory of the items'."""
    assert _wants_product_catalog("maintain a directory of items offered, sku included") is True


def test_item_in_the_catalog_with_sku_selects_catalog():
    """13A-108 Discovery loss: 'an item in the catalog' + sku, no other catalog phrase."""
    assert _wants_product_catalog("an item in the catalog with fields for name and sku") is True


def test_item_in_the_catalog_without_sku_stays_narrow():
    """Negative control: bare 'in the catalog' alone (no sku) must not select catalog."""
    assert _wants_product_catalog("this item is listed in the catalog somewhere") is False


def test_no_double_booking_does_not_suppress_appointment_booking():
    """13A-050 Discovery loss: 'ensuring no double bookings occur' over-negated booking."""
    text = "schedule an appointment for a named resource, ensuring no double bookings occur."
    assert _wants_appointment_booking(text) is True


def test_bare_no_booking_still_negates():
    """Negative control (section 13): genuine negation must still work."""
    assert _wants_appointment_booking("no booking needed for this site") is False


def test_no_duplicate_leads_does_not_suppress_negation_of_leads_itself():
    """The uniqueness-constraint carve-out is negation-marker-scoped, not term-scoped:
    'no duplicate leads' still permits lead language elsewhere in the same text."""
    text = "track leads for our sales team, with no duplicate leads allowed"
    assert not _negated(text, ("leads", "lead records", "prospects"))


def test_potential_clients_alone_does_not_select_lead_pipeline():
    """13A-013/013 Discovery loss root cause: generic audience language must not
    imply crm.lead. Section 12 style negative control."""
    from src.domain.app_blocks.planner import _wants_lead_pipeline

    text = "get in touch with our studio. potential clients visitors to the studio."
    assert _wants_lead_pipeline(text) is False


def test_potential_buyers_describing_a_list_still_selects_lead_pipeline():
    """13A-006 regression guard: 'potential buyers' describing list *contents*
    (not a form's audience) must keep selecting crm.lead."""
    from src.domain.app_blocks.planner import _wants_lead_pipeline

    text = "manage and update lists of existing customers and potential buyers by staff."
    assert _wants_lead_pipeline(text) is True
