import assert from "node:assert/strict";
import {
  TELEMETRY_FIELD_PROJECTION_SCHEMA_VERSION,
  compileTelemetryFieldProjection,
  digestTelemetryFieldRegistry,
  validateTelemetryFieldRegistry,
} from "../src/index.mjs";
import {
  geliosTelemetryFieldRegistryV1,
} from "../providers/gelios/v8/index.mjs";
import {
  geliosTelemetryFieldRegistryV2,
} from "../providers/gelios/v9/index.mjs";

assert.deepEqual(validateTelemetryFieldRegistry(geliosTelemetryFieldRegistryV1), {
  ok: true,
  errors: [],
});
assert.match(digestTelemetryFieldRegistry(geliosTelemetryFieldRegistryV1), /^sha256:[a-f0-9]{64}$/);

const projection = compileTelemetryFieldProjection(geliosTelemetryFieldRegistryV1, {
  providerPackageId: "gelios.provider.v8",
  providerPackageVersion: "8.0.0",
  dataProductId: "fleet.positions.current.v5",
  surface: "data_product",
});
assert.equal(projection.schemaVersion, TELEMETRY_FIELD_PROJECTION_SCHEMA_VERSION);
assert.deepEqual(projection.entries.map((entry) => entry.sourceKey), ["in0", "in1"]);
assert.deepEqual(projection.entries.map((entry) => entry.reading.id), [
  "sensor.param.in0",
  "sensor.param.in1",
]);
assert.equal(projection.entries.some((entry) => entry.sourceKey === "in_0"), false);
assert.equal(Object.isFrozen(projection), true);
assert.equal(Object.isFrozen(projection.entries), true);

assert.deepEqual(validateTelemetryFieldRegistry(geliosTelemetryFieldRegistryV2), {
  ok: true,
  errors: [],
});
const expandedProjection = compileTelemetryFieldProjection(
  geliosTelemetryFieldRegistryV2,
  {
    providerPackageId: "gelios.provider.v9",
    providerPackageVersion: "9.0.0",
    dataProductId: "fleet.positions.current.v5",
    surface: "data_product",
  },
);
assert.deepEqual(
  expandedProjection.entries.map((entry) => entry.sourceKey),
  ["in_0", "in_1", "in0", "in1"],
);
assert.deepEqual(
  expandedProjection.entries.map((entry) => entry.reading.id),
  [
    "sensor.param.in_0",
    "sensor.param.in_1",
    "sensor.param.in0",
    "sensor.param.in1",
  ],
);
assert.notEqual(
  digestTelemetryFieldRegistry(geliosTelemetryFieldRegistryV2),
  digestTelemetryFieldRegistry(geliosTelemetryFieldRegistryV1),
);

const observedExposed = structuredClone(geliosTelemetryFieldRegistryV1);
observedExposed.entries.find((entry) => entry.sourceKey === "in_0").allowedSurfaces.push("foundry");
assert.equal(
  validateTelemetryFieldRegistry(observedExposed).errors.includes(
    "registry.entries[2].nonapproved_surface_must_be_audit_only",
  ),
  true,
);

const approvedUnclassified = structuredClone(geliosTelemetryFieldRegistryV1);
approvedUnclassified.entries[0].sensitivity = "unclassified";
assert.equal(
  validateTelemetryFieldRegistry(approvedUnclassified).errors.includes(
    "registry.entries[0].approved_must_be_operational",
  ),
  true,
);

const wildcardSource = structuredClone(geliosTelemetryFieldRegistryV1);
wildcardSource.entries[0].sourceKey = "*";
assert.equal(
  validateTelemetryFieldRegistry(wildcardSource).errors.includes(
    "registry.entries[0].sourceKey_invalid",
  ),
  true,
);

const duplicateReading = structuredClone(geliosTelemetryFieldRegistryV1);
duplicateReading.entries[1].semanticReading.id = duplicateReading.entries[0].semanticReading.id;
assert.equal(
  validateTelemetryFieldRegistry(duplicateReading).errors.includes(
    "registry.entries[1].semanticReading.id_must_be_unique",
  ),
  true,
);

assert.throws(() => compileTelemetryFieldProjection(geliosTelemetryFieldRegistryV1, {
  providerPackageId: "another.provider.v1",
  providerPackageVersion: "8.0.0",
  dataProductId: "fleet.positions.current.v5",
  surface: "data_product",
}), /providerPackageId_mismatch/);

const serialized = JSON.stringify(geliosTelemetryFieldRegistryV1);
for (const forbidden of ["phone", "imei", "commands", "access_token", "refresh_token"]) {
  assert.equal(serialized.toLowerCase().includes(forbidden), false);
}
