// A shop's customers in HubSpot: a contact and a deal linked, searches past one page, a batch of
// sign-ups upserted by email with its partial failures read, and a webhook checked before use.
//
//   HUBSPOT_TOKEN=... HUBSPOT_CLIENT_SECRET=... quillo run hubspot.qwe
//   then open http://localhost:8080/contact, /deal, /list, /search, /upsert, /hook-check and /failures
//
// The token is a private app's, with the crm.objects scopes. HUBSPOT_API_URL reaches a test server.

use "hubspot.qwer"

route GET /contact {
    let c = hubspot_create("contacts", { email: "ada@example.com", firstname: "Ada" }, {})?
    hubspot_update("contacts", c.id, { lifecyclestage: "customer" }, {})?
    let read = hubspot_get("contacts", "ada@example.com", { id_property: "email", properties: ["firstname", "lifecyclestage"] })?
    let taken = hubspot_create("contacts", { email: "ada@example.com" }, {}).error
    { id: c.id, name: read.properties.firstname, stage: read.properties.lifecyclestage, taken: taken, archived: hubspot_archive("contacts", c.id, {})? }
}

route GET /deal {
    let contact = hubspot_create("contacts", { email: "grace@example.com" }, {})?
    let deal = hubspot_create("deals", { dealname: "Annual plan", amount: "1200", dealstage: "appointmentscheduled", pipeline: "default" }, {})?
    let linked = hubspot_associate("deals", deal.id, "contacts", contact.id, {})?
    { name: deal.properties.dealname, linked: linked, contacts: hubspot_associations("deals", deal.id, "contacts", {})? == [contact.id] }
}

route GET /list {
    let all = hubspot_list("companies", { properties: ["name"] })?
    { total: len(all), first: all[0].properties.name, capped: len(hubspot_list("companies", { max_items: 130 })?) }
}

route GET /search {
    let open = hubspot_search("companies", [hubspot_filter("state", "EQ", "open")], { properties: ["name"] })?
    let either = hubspot_search("companies", [[hubspot_filter("state", "EQ", "open")], [hubspot_filter("state", "EQ", "closed")]], { max_items: 10 })?
    {
        total: open.total, got: len(open.results), any: len(either.results),
        inside: hubspot_filter("region", "IN", ["eu", "uk"]),
        too_many: hubspot_search("companies", map(range(0, 7), (i) => hubspot_filter("n", "EQ", i)), {}).error,
    }
}

route GET /upsert {
    let rows = map(range(0, 250), (i) => { email: `Person${i}@Example.com`, firstname: `P${i}` })
    let first = hubspot_batch_upsert("contacts", "email", rows, {})?
    let again = hubspot_batch_upsert("contacts", "email", [{ email: "person0@example.com", firstname: "New" }, { email: "bad-address", firstname: "X" }], {})?
    { created: first.created, updated: first.updated, second_updated: again.updated, failed: len(again.errors), why: again.errors[0].message, missing: hubspot_batch_upsert("contacts", "email", [{ firstname: "x" }], {}).error }
}

// A signature made outside this plugin, for a URI with an encoded part that must stay encoded.
route GET /hook-check {
    let body = "[{\"objectId\":1}]"
    let uri = "https://example.com/hubspot/hook?a=1&b=é"
    let sig = "IncyOhHYlrsQm0mI9mkSsB6zd9iJLR0yYd6nLum+ZzY="
    {
        good: hubspot_signature_check("POST", uri, body, "1790000000000", sig, "hub-secret", -1)?,
        encoded_colon: hubspot_signature_check("post", "https%3A%2F%2Fexample.com/hubspot/hook%3Fa=1&b=é", body, "1790000000000", sig, "hub-secret", -1)?,
        tampered: hubspot_signature_check("POST", uri, body + " ", "1790000000000", sig, "hub-secret", -1).error,
        too_old: hubspot_signature_check("POST", uri, body, "1790000000000", sig, "hub-secret", 0).error,
    }
}

route GET /failures = {
    bad_token: hubspot_get("contacts", "1", { token: "wrong" }).error,
    missing: hubspot_get("contacts", "999999", {}).error,
    invalid: hubspot_create("contacts", { email: "not an email" }, {}).error,
    waited: hubspot_create("contacts", { email: "rate@example.com" }, {})?.properties.email,
    daily: hubspot_get("deals", "daily", {}).error,
}
