// A shop's products on Typesense: a collection, a JSONL import with each line's result read, a
// search with a filter and facets, and a scoped key that keeps one shop's browser to its products.
//
//   TYPESENSE_API_URL=http://localhost:8108 TYPESENSE_API_KEY=... TYPESENSE_SEARCH_KEY=... quillo run typesense.qwe
//   then open /setup, /import, /search?q=mug&brand=Acme, Inc, /all, /scoped, /broken and /remove

use "typesense.qwer"

route GET /setup = {
    made: typesense_create_collection({
        name: "products",
        fields: [
            { name: "name", type: "string" },
            { name: "brand", type: "string", facet: true },
            { name: "shop_id", type: "int32", facet: true },
            { name: "price", type: "float" },
        ],
        default_sorting_field: "price",
    })?,
    again: typesense_create_collection({ name: "products", fields: [] })?,
    count: typesense_collection("products")?.num_documents,
    none: typesense_collection("nothing")?,
}

// Line 2 has a price that is no number: that line is named and the rest go in.
route GET /import = typesense_import("products", [
    { id: "1", name: "Blue mug", brand: "Acme, Inc", shop_id: 7, price: 9.5 },
    { id: "2", name: "Red mug", brand: "Plain", shop_id: 7, price: "cheap" },
    { id: "3", name: "Green mug", brand: "Acme, Inc", shop_id: 9, price: 12.0 },
    { id: "4", name: "Tall mug", brand: "Plain", shop_id: 7, price: 11.0 },
    { id: "5", name: "Wide mug", brand: "Plain", shop_id: 9, price: 3.0 },
], "upsert")?

route GET /search ? { q: str, brand: str } {
    let filter = "brand:=" + typesense_filter_value(brand)?
    let r = typesense_search("products", { q: q, query_by: ["name"], filter_by: filter, sort_by: "price:asc", facet_by: "brand" })?
    { filter: filter, found: r.found, names: r.hits | map((h) => h.name), facet: r.facets[0].counts }
}

route GET /all {
    let r = typesense_search_all("products", { q: "*", query_by: "name", sort_by: "price:asc", per_page: 2 }, 100)?
    { found: r.found, ids: r.hits | map((h) => h.id), complete: r.complete, limited: typesense_search_all("products", { q: "*", query_by: "name", per_page: 2 }, 3)?.complete }
}

// Made on this server; the browser may add to the search but cannot widen `filter_by`.
route GET /scoped {
    let key = typesense_scoped_key({ filter_by: "shop_id:=7", expires_at: 1906000000 })?
    {
        names: typesense_search_as(key, "products", { q: "mug", query_by: "name", sort_by: "price:asc" })?.hits | map((h) => h.name),
        forged: typesense_search_as("AAAA" + key, "products", { q: "mug", query_by: "name" }).error,
    }
}

route GET /broken = {
    bad_field: typesense_search("products", { q: "x", query_by: "nope" }).error,
    no_q: typesense_search("products", { query_by: "name" }).error,
    gone: typesense_get("products", "404")?,
    backtick: typesense_filter_value("a`b").error,
}

route GET /remove = { removed: typesense_delete_where("products", "shop_id:=9")?, left: typesense_collection("products")?.num_documents }
