@prefix : <https://ontology.inferal.com/modules/advertising-delivery-state/> .
@prefix ex: <https://example.com/advertising-delivery-state/> .
@prefix rdfs: <http://www.w3.org/2000/01/rdf-schema#> .

# Worked instances for the Advertising Delivery State module.
#
# Four scenarios, each a case the twelve-value status enumeration collapses:
#   A. Serving normally, nothing to explain.
#   B. Switched off by the advertiser: intent and serving agree.
#   C. Intending to run but held by a paused ancestor. The hold names which one.
#   D. Intending to run and held by two independent causes at once.


# --- Scenario A: serving -----------------------------------------------------

ex:ad-1-state
    a :DeliveryState ;
    rdfs:label "ad 1, delivering normally" ;
    :stateOf ex:ad-1 ;
    :intendedDelivery :intendToRun ;
    :observedServing :serving ;
    :lifecycleStanding :liveEntity .


# --- Scenario B: switched off by the advertiser ------------------------------
#
# Intent and observation agree, and there is nothing to fix. In a single-field
# model this is indistinguishable from scenario C.

ex:ad-2-state
    a :DeliveryState ;
    rdfs:label "ad 2, paused by the advertiser" ;
    :stateOf ex:ad-2 ;
    :intendedDelivery :intendToHold ;
    :observedServing :notServing ;
    :lifecycleStanding :liveEntity .


# --- Scenario C: held by an ancestor -----------------------------------------
#
# The advertiser wants ad 3 to run and nothing is wrong with it. Its ad group is
# paused, so it does not deliver. The provider enumeration would report this as
# the parent being paused without saying which parent, leaving an operator to
# walk the hierarchy. Here the hold names the ancestor.

ex:ad-3-state
    a :DeliveryState ;
    rdfs:label "ad 3, blocked by its ad group" ;
    :stateOf ex:ad-3 ;
    :intendedDelivery :intendToRun ;
    :observedServing :notServing ;
    :lifecycleStanding :liveEntity ;
    :heldBy ex:ad-3-ancestor-hold .

ex:ad-3-ancestor-hold
    a :ServingHold ;
    rdfs:label "held because the parent ad group is not delivering" ;
    :holdKind :ancestorHeldHold ;
    :originatingResource ex:adgroup-a .

ex:adgroup-a-state
    a :DeliveryState ;
    rdfs:label "ad group A, paused by the advertiser" ;
    :stateOf ex:adgroup-a ;
    :intendedDelivery :intendToHold ;
    :observedServing :notServing ;
    :lifecycleStanding :liveEntity .


# --- Scenario D: two independent holds ---------------------------------------
#
# A policy rejection on the ad itself and an unpaid account above it. Fixing
# either alone changes nothing, which is why a model reporting a single reason
# makes a correct fix look ineffective. The two holds carry different origins,
# so they are also different people's problems.

ex:ad-4-state
    a :DeliveryState ;
    rdfs:label "ad 4, rejected and unfunded" ;
    :stateOf ex:ad-4 ;
    :intendedDelivery :intendToRun ;
    :observedServing :notServing ;
    :lifecycleStanding :liveEntity ;
    :heldBy ex:ad-4-policy-hold , ex:ad-4-billing-hold .

ex:ad-4-policy-hold
    a :ServingHold ;
    rdfs:label "rejected under platform policy" ;
    rdfs:comment "Originates on the ad itself: the advertiser can amend or appeal." ;
    :holdKind :policyReviewHold ;
    :originatingResource ex:ad-4 .

ex:ad-4-billing-hold
    a :ServingHold ;
    rdfs:label "account has no valid payment method" ;
    rdfs:comment "Originates on the account: the remedy is not on this ad at all." ;
    :holdKind :billingHold ;
    :originatingResource ex:account-1 .


# --- An archived entity ------------------------------------------------------
#
# Archived is not paused. Its historical measurements remain valid, and a query
# for what the advertiser switched off must not return it.

ex:ad-5-state
    a :DeliveryState ;
    rdfs:label "ad 5, archived" ;
    :stateOf ex:ad-5 ;
    :intendedDelivery :intendToHold ;
    :observedServing :notServing ;
    :lifecycleStanding :archivedEntity .
