import assert from "node:assert/strict";
import { validateProviderCapabilityCatalog } from "../src/index.mjs";
import {
  geliosCapabilityCatalogV1,
  geliosCapabilityCatalogV2,
  geliosCapabilityCatalogV3,
  geliosProviderPackageV8,
} from "../providers/gelios/index.mjs";

assert.deepEqual(validateProviderCapabilityCatalog(geliosCapabilityCatalogV1), { ok: true, errors: [] });
assert.deepEqual(validateProviderCapabilityCatalog(geliosCapabilityCatalogV2), { ok: true, errors: [] });
assert.deepEqual(validateProviderCapabilityCatalog(geliosCapabilityCatalogV3), { ok: true, errors: [] });

const expectedUnitRoots = [
  "activatedAt", "availableToUsers", "blockTime", "commands", "counters", "createdAt",
  "creator", "currentUserAccess", "customFields", "driver", "extraInfo", "fuelParams",
  "hwDecryptKey", "hwManufacturer", "hwType", "id", "imei", "imeiIsVisible", "isBlock",
  "isFree", "lastMsg", "lastSensorsVal", "maintenancePlan", "name", "phone", "phone2",
  "phone2IsVisible", "phoneIsVisible", "preSetCommandGroup", "removed", "removedAt", "sensors",
  "stationaryLat", "stationaryLon", "storageInfo", "tripParams", "unblockTime", "unitType",
];
assert.deepEqual(geliosCapabilityCatalogV1.coverage.sourceRoots, expectedUnitRoots);

const expectedIncludeFlags = [
  "inclextra", "incltrip", "inclfuel", "inclcntrs", "inclcstmflds", "inclsnsrs",
  "inclcmmnds", "incldrvrs", "inclstinf", "inclusersav", "incllsv", "inclplan",
];
assert.deepEqual(geliosCapabilityCatalogV1.queryFlags.map(({ id }) => id), expectedIncludeFlags);

const unitCapability = geliosProviderPackageV8.capabilities.find(({ id }) => id === "gelios.units.current.read");
assert.ok(unitCapability);
for (const enabledFlag of Object.keys(unitCapability.request.query)) {
  assert.ok(expectedIncludeFlags.includes(enabledFlag), `provider query flag is missing from the capability catalog: ${enabledFlag}`);
}

assert.deepEqual(
  geliosCapabilityCatalogV1.capabilities.filter(({ status }) => status === "implemented").map(({ id }) => id),
  ["gelios.units.current.read", "gelios.geozones.current.read"],
);
assert.equal(
  geliosCapabilityCatalogV1.capabilities.filter(({ classification }) => classification === "control").every(({ status }) => status === "disabled"),
  true,
);
assert.deepEqual(
  ["gelios.unit.identity", "gelios.unit.equipment", "gelios.unit.trip_settings"].map((id) => {
    const family = geliosCapabilityCatalogV2.dataFamilies.find((item) => item.id === id);
    return { id, status: family.status, dataProductIds: family.dataProductIds };
  }),
  [
    { id: "gelios.unit.identity", status: "implemented", dataProductIds: ["fleet.units.profile.current.v1"] },
    { id: "gelios.unit.equipment", status: "implemented", dataProductIds: ["fleet.units.profile.current.v1"] },
    { id: "gelios.unit.trip_settings", status: "implemented", dataProductIds: ["fleet.units.profile.current.v1"] },
  ],
);
assert.equal(
  geliosCapabilityCatalogV2.dataFamilies.find(({ id }) => id === "gelios.unit.sensor_definitions").status,
  "planned",
);
for (const familyId of [
  "gelios.unit.device_identifiers",
  "gelios.unit.driver",
  "gelios.unit.asset_identifiers",
  "gelios.unit.custom_fields",
]) {
  const family = geliosCapabilityCatalogV3.dataFamilies.find(({ id }) => id === familyId);
  assert.equal(family.status, "implemented");
  assert.equal(family.dataProductIds.includes("fleet.units.identity.current.v1"), true);
}

const restrictedPublish = structuredClone(geliosCapabilityCatalogV1);
restrictedPublish.dataFamilies.find(({ id }) => id === "gelios.unit.device_identifiers").disposition = "publish";
restrictedPublish.dataFamilies.find(({ id }) => id === "gelios.unit.device_identifiers").dataProductIds = ["unsafe.identifiers.current.v1"];
assert.equal(validateProviderCapabilityCatalog(restrictedPublish).ok, false);

const missingCoverage = structuredClone(geliosCapabilityCatalogV1);
missingCoverage.dataFamilies.find(({ id }) => id === "gelios.unit.identity").sourcePaths = ["name", "unitType.id"];
assert.ok(validateProviderCapabilityCatalog(missingCoverage).errors.includes("coverage.source_root_unaccounted:id"));

const enabledControl = structuredClone(geliosCapabilityCatalogV1);
enabledControl.capabilities.find(({ id }) => id === "gelios.unit.command.send").status = "catalogued";
assert.equal(validateProviderCapabilityCatalog(enabledControl).ok, false);

console.log("Gelios provider capability catalog: ok");
