/**
 * @file conformance.mjs
 * @desc Standalone conformance runner for the SuperPenguin FOCUS AI Provider Profile.
 * @author Cursor AI
 * @created 2026-07-28
 * @updated 2026-07-28
 */

const PROFILE_VERSION = "0.1";
const FOCUS_VERSION = "1.4";
const TEST_PAGE_LIMIT = 1;
const MAX_PAGES = 100;
const DECIMAL_PATTERN = /^-?(0|[1-9][0-9]*)(\.[0-9]+)?$/;
const CORE_USAGE_UNITS = Object.freeze({
  input_tokens: "tokens",
  output_tokens: "tokens",
  cache_read_tokens: "tokens",
  cache_write_5m_tokens: "tokens",
  cache_write_1h_tokens: "tokens",
  input_audio_tokens: "tokens",
  output_audio_tokens: "tokens",
  requests: "requests",
  audio_seconds: "seconds",
  characters: "characters",
  events: "events",
  session_minutes: "minutes",
  credits: "credits",
});

function fail(message) {
  throw new Error(message);
}

function assert(condition, message) {
  if (!condition) fail(message);
}

function parseArguments(argv) {
  const values = new Map();
  for (let index = 0; index < argv.length; index += 2) {
    const key = argv[index];
    const value = argv[index + 1];
    if (!key?.startsWith("--") || value == null) {
      fail(`Invalid argument sequence near "${key ?? ""}"`);
    }
    values.set(key.slice(2), value);
  }

  const baseUrl = values.get("base-url");
  const token = values.get("token");
  const start = values.get("start");
  const end = values.get("end");
  if (!baseUrl || !token || !start || !end) {
    fail(
      "Usage: node conformance.mjs --base-url <url> --token <token> " +
        "--start <RFC3339> --end <RFC3339>",
    );
  }

  const startMs = Date.parse(start);
  const endMs = Date.parse(end);
  assert(Number.isFinite(startMs), "--start must be an RFC3339 timestamp");
  assert(Number.isFinite(endMs), "--end must be an RFC3339 timestamp");
  assert(startMs < endMs, "--start must be before --end");

  return {
    baseUrl: baseUrl.replace(/\/+$/, ""),
    token,
    start,
    end,
  };
}

function isObject(value) {
  return value !== null && typeof value === "object" && !Array.isArray(value);
}

function assertString(value, path) {
  assert(typeof value === "string" && value.length > 0, `${path} must be a non-empty string`);
}

function assertNullableString(value, path) {
  assert(value === null || typeof value === "string", `${path} must be a string or null`);
}

function assertTimestamp(value, path) {
  assertString(value, path);
  assert(Number.isFinite(Date.parse(value)), `${path} must be an RFC3339 timestamp`);
}

function assertDecimal(value, path) {
  assertString(value, path);
  assert(DECIMAL_PATTERN.test(value), `${path} must be a JSON decimal string`);
}

function assertCommonRecord(record, path) {
  assert(isObject(record), `${path} must be an object`);
  assertString(record.x_RecordId, `${path}.x_RecordId`);
  assertTimestamp(record.x_RecordUpdatedAt, `${path}.x_RecordUpdatedAt`);
  assert(["1h", "1d"].includes(record.x_Granularity), `${path}.x_Granularity is unsupported`);
  assertTimestamp(record.ChargePeriodStart, `${path}.ChargePeriodStart`);
  assertTimestamp(record.ChargePeriodEnd, `${path}.ChargePeriodEnd`);
  assert(
    Date.parse(record.ChargePeriodStart) < Date.parse(record.ChargePeriodEnd),
    `${path} must have a positive half-open charge period`,
  );
  assertString(record.ServiceProviderName, `${path}.ServiceProviderName`);
  assert(
    record.ServiceCategory === "AI and Machine Learning",
    `${path}.ServiceCategory must be "AI and Machine Learning"`,
  );
  assertString(record.ServiceName, `${path}.ServiceName`);

  for (const field of [
    "x_ModelId",
    "x_ProjectId",
    "x_WorkspaceId",
    "x_ApiKeyId",
    "x_ServiceTier",
    "x_WorkloadType",
    "x_UpstreamProvider",
  ]) {
    if (field in record) assertNullableString(record[field], `${path}.${field}`);
  }
}

function assertUsageRecord(record, path) {
  assertCommonRecord(record, path);
  assertString(record.SkuId, `${path}.SkuId`);
  assertString(record.SkuMeter, `${path}.SkuMeter`);
  assertDecimal(record.ConsumedQuantity, `${path}.ConsumedQuantity`);
  assertString(record.ConsumedUnit, `${path}.ConsumedUnit`);
  assertString(record.x_UsageType, `${path}.x_UsageType`);

  const expectedUnit = CORE_USAGE_UNITS[record.x_UsageType];
  if (expectedUnit) {
    assert(
      record.ConsumedUnit === expectedUnit,
      `${path}.ConsumedUnit must be "${expectedUnit}" for ${record.x_UsageType}`,
    );
  } else {
    assert(
      record.x_UsageType.startsWith("x_"),
      `${path}.x_UsageType must use a core value or the x_ extension prefix`,
    );
  }
}

function assertCostRecord(record, path) {
  assertCommonRecord(record, path);
  assertTimestamp(record.BillingPeriodStart, `${path}.BillingPeriodStart`);
  assertTimestamp(record.BillingPeriodEnd, `${path}.BillingPeriodEnd`);
  assertString(record.InvoiceIssuerName, `${path}.InvoiceIssuerName`);
  assert(
    ["Usage", "Purchase", "Tax", "Credit", "Adjustment"].includes(record.ChargeCategory),
    `${path}.ChargeCategory is unsupported`,
  );
  assert(typeof record.ChargeDescription === "string", `${path}.ChargeDescription must be a string`);
  assert(
    typeof record.BillingCurrency === "string" && /^[A-Z]{3}$/.test(record.BillingCurrency),
    `${path}.BillingCurrency must be an uppercase ISO 4217 code`,
  );
  assertDecimal(record.BilledCost, `${path}.BilledCost`);
  assertDecimal(record.EffectiveCost, `${path}.EffectiveCost`);
  assert(
    ["provisional", "final"].includes(record.x_CostStatus),
    `${path}.x_CostStatus must be provisional or final`,
  );

  if (record.BillingCurrency !== "USD") {
    assert(
      record.PricingCurrency === "USD" &&
        typeof record.PricingCurrencyBilledCost === "string",
      `${path} must provide an explicit USD pricing-currency amount for non-USD billing`,
    );
    assertDecimal(record.PricingCurrencyBilledCost, `${path}.PricingCurrencyBilledCost`);
  }
}

async function requestJson(url, token) {
  const response = await fetch(url, {
    headers: { Authorization: `Bearer ${token}`, Accept: "application/json" },
  });
  if (!response.ok) {
    const body = await response.text();
    fail(`${response.status} ${response.statusText} from ${url}: ${body.slice(0, 500)}`);
  }
  const contentType = response.headers.get("content-type") ?? "";
  assert(contentType.includes("application/json"), `${url} must return application/json`);
  return response.json();
}

async function assertAuthenticationRequired(baseUrl) {
  const response = await fetch(`${baseUrl}/v1/finops/capabilities`);
  assert(response.status === 401, "capabilities must return 401 without a credential");
  console.log("PASS authentication is required");
}

function assertCapabilities(value) {
  assert(isObject(value), "capabilities must be an object");
  assert(value.profile_version === PROFILE_VERSION, `profile_version must be ${PROFILE_VERSION}`);
  assert(value.focus_version === FOCUS_VERSION, `focus_version must be ${FOCUS_VERSION}`);
  assertString(value.provider, "capabilities.provider");
  assert(Array.isArray(value.authorization_methods), "authorization_methods must be an array");
  assert(
    value.authorization_methods.includes("scoped_bearer_token"),
    "Core conformance requires scoped_bearer_token",
  );
  assert(isObject(value.datasets), "capabilities.datasets must be an object");
  assert(isObject(value.datasets.usage), "capabilities.datasets.usage is required");

  for (const [name, dataset] of Object.entries(value.datasets)) {
    assert(isObject(dataset), `capabilities.datasets.${name} must be an object`);
    assertString(dataset.endpoint, `capabilities.datasets.${name}.endpoint`);
    assert(Array.isArray(dataset.granularities), `${name}.granularities must be an array`);
    assert(
      dataset.granularities.every((item) => ["1h", "1d"].includes(item)),
      `${name}.granularities contains an unsupported value`,
    );
    assert(
      Number.isInteger(dataset.retention_days) && dataset.retention_days > 0,
      `${name}.retention_days must be a positive integer`,
    );
    assert(
      Number.isInteger(dataset.maximum_window_days) && dataset.maximum_window_days > 0,
      `${name}.maximum_window_days must be a positive integer`,
    );
    assert(Array.isArray(dataset.dimensions), `${name}.dimensions must be an array`);
  }
}

async function collectPages({
  baseUrl,
  endpoint,
  token,
  start,
  end,
  granularity,
  validateRecord,
}) {
  const records = [];
  const ids = new Set();
  let cursor = null;
  let pageCount = 0;
  let snapshot = null;

  do {
    pageCount += 1;
    assert(pageCount <= MAX_PAGES, `pagination exceeded ${MAX_PAGES} pages`);
    const url = new URL(endpoint, baseUrl);
    url.searchParams.set("start", start);
    url.searchParams.set("end", end);
    url.searchParams.set("limit", String(TEST_PAGE_LIMIT));
    if (granularity) url.searchParams.set("granularity", granularity);
    if (cursor) url.searchParams.set("cursor", cursor);

    const page = await requestJson(url, token);
    assert(isObject(page), `page ${pageCount} must be an object`);
    assert(Array.isArray(page.data), `page ${pageCount}.data must be an array`);
    assertTimestamp(page.as_of, `page ${pageCount}.as_of`);
    assertTimestamp(page.available_through, `page ${pageCount}.available_through`);
    if (snapshot === null) snapshot = page.as_of;
    assert(page.as_of === snapshot, "as_of must remain stable during cursor pagination");

    for (let index = 0; index < page.data.length; index += 1) {
      const record = page.data[index];
      validateRecord(record, `page ${pageCount}.data[${index}]`);
      assert(!ids.has(record.x_RecordId), `duplicate record id ${record.x_RecordId} across pages`);
      ids.add(record.x_RecordId);
      records.push(record);
    }

    assert(
      page.next_cursor === null || typeof page.next_cursor === "string",
      `page ${pageCount}.next_cursor must be a string or null`,
    );
    cursor = page.next_cursor;
  } while (cursor !== null);

  return { records, pageCount };
}

async function main() {
  const options = parseArguments(process.argv.slice(2));
  await assertAuthenticationRequired(options.baseUrl);

  const capabilities = await requestJson(
    `${options.baseUrl}/v1/finops/capabilities`,
    options.token,
  );
  assertCapabilities(capabilities);
  console.log("PASS capability document");

  const usageGranularity = capabilities.datasets.usage.granularities.includes("1h")
    ? "1h"
    : capabilities.datasets.usage.granularities[0];
  const usage = await collectPages({
    ...options,
    endpoint: capabilities.datasets.usage.endpoint,
    granularity: usageGranularity,
    validateRecord: assertUsageRecord,
  });
  assert(usage.records.length > 0, "selected window must contain at least one usage record");
  console.log(
    `PASS usage export (${usage.records.length} records across ${usage.pageCount} pages)`,
  );

  if (capabilities.datasets.costs) {
    const costs = await collectPages({
      ...options,
      endpoint: capabilities.datasets.costs.endpoint,
      granularity: null,
      validateRecord: assertCostRecord,
    });
    assert(costs.records.length > 0, "selected window must contain at least one cost record");
    console.log(
      `PASS cost export (${costs.records.length} records across ${costs.pageCount} pages)`,
    );
  } else {
    console.log("SKIP cost export (Core profile without Billing capability)");
  }

  console.log("PASS SuperPenguin FOCUS AI Provider Profile v0.1");
}

main().catch((error) => {
  console.error(`FAIL ${error instanceof Error ? error.message : String(error)}`);
  process.exitCode = 1;
});
