import assert from "node:assert/strict";
import {
  assertReaderProduct,
  consumerReaderBindingRequestHash,
  createReaderToken,
  hashReaderToken,
  normalizeManagedConsumerReaderBindingRequest,
  normalizeManagedConsumerReaderPlanRequest,
  normalizeManagedReaderBindingRequest,
  normalizeReaderBindingRequest,
  readerBindingRequestHash,
  safeManagedConsumerReaderBinding,
  safeReaderBinding,
} from "../src/reader-binding.mjs";

const now = new Date("2026-07-15T12:00:00.000Z");
const policy = normalizeReaderBindingRequest({
  source: { tenantId: "tenant-01", connectionId: "connection-01", providerId: "example-provider" },
  allowedDataProductIds: ["fleet.positions.current.v1"],
  expiresAt: "2026-08-01T12:00:00.000Z",
}, { now });
const token = createReaderToken();
assert.match(token, /^ndc_edprb_[A-Za-z0-9_-]{40,}$/);
assert.equal(hashReaderToken(token), hashReaderToken(token));
assert.equal(assertReaderProduct({ ...policy, active: true }, "fleet.positions.current.v1", now), "fleet.positions.current.v1");
assert.throws(() => assertReaderProduct({ ...policy, active: true }, "other.product.v1", now), /reader_binding_data_product_forbidden/);
const safe = safeReaderBinding({ id: "reader-01", ...policy, active: true, token, tokenHash: hashReaderToken(token) });
assert.equal("token" in safe, false);
assert.equal("tokenHash" in safe, false);

const managed = normalizeManagedReaderBindingRequest({
  source: { tenantId: policy.tenantId, connectionId: policy.connectionId, providerId: policy.providerId },
  allowedDataProductIds: ["fleet.positions.current.v1"],
  expiresAt: null,
  generation: 2,
  capabilityDigest: hashReaderToken(token),
}, { now });
assert.equal(managed.generation, 2);
assert.match(readerBindingRequestHash(managed), /^[a-f0-9]{64}$/);
const safeManaged = safeReaderBinding({
  id: "reader-managed-01",
  bindingKey: "dprg-reader-managed",
  generation: 2,
  ...managed,
  active: true,
});
assert.equal(safeManaged.bindingKey, "dprg-reader-managed");
assert.equal(safeManaged.generation, 2);
assert.equal(safeManaged.expiresAt, null);
assert.equal(
  assertReaderProduct(safeManaged, "fleet.positions.current.v1", new Date("2036-07-15T12:00:00.000Z")),
  "fleet.positions.current.v1",
);
assert.equal(JSON.stringify(safeManaged).includes(managed.capabilityDigest), false);
assert.throws(() => normalizeManagedReaderBindingRequest({
  source: { tenantId: policy.tenantId, connectionId: policy.connectionId, providerId: policy.providerId },
  allowedDataProductIds: managed.allowedDataProductIds,
  expiresAt: managed.expiresAt,
  generation: managed.generation,
  capabilityDigest: managed.capabilityDigest,
  token: "forbidden",
}, { now }), /managed_reader_binding_secret_material_forbidden/);
assert.throws(() => normalizeManagedReaderBindingRequest({
  source: { tenantId: policy.tenantId, connectionId: policy.connectionId, providerId: policy.providerId },
  allowedDataProductIds: managed.allowedDataProductIds,
  expiresAt: policy.expiresAt,
  generation: managed.generation,
  capabilityDigest: managed.capabilityDigest,
}), /managed_reader_binding_must_be_durable/);

const consumerPlan = normalizeManagedConsumerReaderPlanRequest({
  allowedDataProductIds: ["fleet.positions.current.v1", "fleet.positions.current.v1"],
});
assert.deepEqual(consumerPlan.allowedDataProductIds, ["fleet.positions.current.v1"]);
const consumerManaged = normalizeManagedConsumerReaderBindingRequest({
  allowedDataProductIds: consumerPlan.allowedDataProductIds,
  expiresAt: null,
  generation: 1,
  capabilityDigest: hashReaderToken(token),
});
assert.match(consumerReaderBindingRequestHash(consumerManaged), /^[a-f0-9]{64}$/);
const safeConsumer = safeManagedConsumerReaderBinding({
  id: "reader-foundry-01",
  bindingKey: "fndrc-reader-managed",
  ...consumerManaged,
  active: true,
});
assert.equal(safeConsumer.sourceScope, "resolved-server-side");
assert.equal(JSON.stringify(safeConsumer).includes(consumerManaged.capabilityDigest), false);
assert.equal("tenantId" in safeConsumer, false);
assert.equal("connectionId" in safeConsumer, false);
assert.equal("providerId" in safeConsumer, false);
assert.throws(() => normalizeManagedConsumerReaderBindingRequest({
  ...consumerManaged,
  capability: "forbidden",
}), /managed_consumer_reader_binding_request_invalid/);

console.log("external-data-plane reader bindings: ok");
