import { geliosProviderPackageV3 } from "../v3/package.mjs";

export const GELIOS_PROVIDER_PACKAGE_ID = "gelios.provider.v4";
export const GELIOS_PROVIDER_PACKAGE_VERSION = "4.0.0";
export const GELIOS_POSITIONS_DATA_PRODUCT_ID = "fleet.positions.current.v3";
export const GELIOS_POSITIONS_DATA_PRODUCT_VERSION = "3.0.0";
export const GELIOS_POSITIONS_ONTOLOGY_REVISION = "ontology.map.moving_object.v3";
export const GELIOS_UNIT_SOURCE_ID_PREFIX = "gelios-unit-";

const UNIT_CAPABILITY_ID = "gelios.units.current.read";
const MONITORING_CONFIG_CAPABILITY_ID = "gelios.monitoring_config.current.read";
const FIELD_POLICY_ID = "gelios.positions.current.fields.v3";
const REALTIME_PROFILE_ID = "gelios.positions.current.realtime.v4";
const MANUAL_PROFILE_ID = "gelios.positions.current.manual.v4";
const MAPPING_ID = "gelios.units.to.fleet.positions.current.v4";
const TEMPLATE_ID = "gelios.positions.current.l2.v4";

const targetFields = Object.freeze([
  "course_degrees",
  "display_name",
  "elevation_meters",
  "geometry",
  "hdop",
  "horizontal_accuracy_meters",
  "movement_state",
  "object_kind",
  "position_source",
  "satellite_count",
  "signal_state",
  "speed_kph",
]);

const value = structuredClone(geliosProviderPackageV3);
const unitCapability = value.capabilities.find((capability) => capability.id === UNIT_CAPABILITY_ID);
const baseMapping = value.mappingContracts[0];
const baseAttributes = baseMapping.fact.attributes;
const authModeId = value.authModes[0].id;

value.id = GELIOS_PROVIDER_PACKAGE_ID;
value.version = GELIOS_PROVIDER_PACKAGE_VERSION;
value.manifest = {
  ...value.manifest,
  id: "gelios.provider.manifest.v4",
  version: GELIOS_PROVIDER_PACKAGE_VERSION,
  ontology: {
    packageId: "gelios",
    revision: "ontology.gelios.v1_1",
  },
  capabilityIds: [MONITORING_CONFIG_CAPABILITY_ID, UNIT_CAPABILITY_ID],
  fieldPolicyIds: [FIELD_POLICY_ID],
  collectionProfileIds: [REALTIME_PROFILE_ID, MANUAL_PROFILE_ID],
  dataProductIds: [GELIOS_POSITIONS_DATA_PRODUCT_ID],
  mappingContractIds: [MAPPING_ID],
  l2TemplateIds: [TEMPLATE_ID],
};
value.capabilities = [{
  id: MONITORING_CONFIG_CAPABILITY_ID,
  classification: "read",
  status: "implemented",
  authModeId,
  request: {
    method: "GET",
    baseUrl: "https://api.geliospro.com",
    path: "/api/v1/users/me/monitoring-config",
    query: {},
    response: {
      collectionPaths: ["$", "data"],
      pagination: "single_bounded_response",
    },
  },
  entityScope: {
    mode: "all_visible_to_credential",
    refresh: "each_collection_run",
    businessEntityFilter: "forbidden",
  },
}, {
  ...unitCapability,
  request: {
    ...unitCapability.request,
    query: { incltrip: "true" },
  },
}];
value.fieldPolicies = [{
  ...value.fieldPolicies[0],
  id: FIELD_POLICY_ID,
  version: GELIOS_POSITIONS_DATA_PRODUCT_VERSION,
  dataProductId: GELIOS_POSITIONS_DATA_PRODUCT_ID,
  targetFields: [...targetFields],
}];
value.collectionProfiles = value.collectionProfiles.map((profile, index) => ({
  ...profile,
  id: index === 0 ? REALTIME_PROFILE_ID : MANUAL_PROFILE_ID,
  version: GELIOS_PROVIDER_PACKAGE_VERSION,
  capabilityIds: [MONITORING_CONFIG_CAPABILITY_ID, UNIT_CAPABILITY_ID],
  dataProductId: GELIOS_POSITIONS_DATA_PRODUCT_ID,
  mappingContractId: MAPPING_ID,
  fieldPolicyId: FIELD_POLICY_ID,
  l2TemplateId: TEMPLATE_ID,
}));
value.dataProducts = [{
  id: GELIOS_POSITIONS_DATA_PRODUCT_ID,
  version: GELIOS_POSITIONS_DATA_PRODUCT_VERSION,
  ontologyRevision: GELIOS_POSITIONS_ONTOLOGY_REVISION,
  deliveryMode: "snapshot+patch",
  semanticTypes: ["map.moving_object"],
  fields: [...targetFields],
  history: {
    mode: "sampled",
    intervalMs: 60000,
    strategy: "latest-per-entity-per-bucket",
    retentionDays: 90,
  },
}];
value.mappingContracts = [{
  ...baseMapping,
  id: MAPPING_ID,
  version: GELIOS_PROVIDER_PACKAGE_VERSION,
  sourceCapabilityId: UNIT_CAPABILITY_ID,
  fieldPolicyId: FIELD_POLICY_ID,
  target: {
    ...baseMapping.target,
    dataProductId: GELIOS_POSITIONS_DATA_PRODUCT_ID,
    version: GELIOS_POSITIONS_DATA_PRODUCT_VERSION,
    ontologyRevision: GELIOS_POSITIONS_ONTOLOGY_REVISION,
  },
  derivations: {
    signal_state: {
      kind: "ordered_rules",
      rules: [
        "last_message_missing.inactive",
        "last_message_age_lt_resolved_monitoring_limit.active",
        "otherwise.inactive",
      ],
      default: "inactive",
      parameters: {
        monitoringConfigCapability: MONITORING_CONFIG_CAPABILITY_ID,
        activeDurationPath: "signalActiveDuration",
        somewhatInactiveDurationPath: "signalSomewhatInactiveDuration",
        inactiveDurationPath: "signalSomewhatInactiveDuration",
        collectionProfileFallbackSeconds: 120,
        thresholdResolution: "somewhatInactive_then_active_then_profileFallback",
        lastMessageTimePath: "lastMsg.time",
      },
    },
    movement_state: {
      kind: "ordered_rules",
      rules: [
        "integer_speed_gt_threshold.moving",
        "otherwise.stopped",
      ],
      default: "stopped",
      parameters: {
        speedPath: "lastMsg.speed",
        movingThresholdKph: 2,
      },
    },
  },
  fact: {
    ...baseMapping.fact,
    attributes: {
      course_degrees: baseAttributes.course_degrees,
      display_name: baseAttributes.display_name,
      elevation_meters: baseAttributes.elevation_meters,
      hdop: baseAttributes.hdop,
      horizontal_accuracy_meters: baseAttributes.horizontal_accuracy_meters,
      movement_state: { derive: "movement_state" },
      object_kind: baseAttributes.object_kind,
      position_source: baseAttributes.position_source,
      satellite_count: baseAttributes.satellite_count,
      signal_state: { derive: "signal_state" },
      speed_kph: baseAttributes.speed_kph,
    },
  },
}];
value.l2Templates = [{
  ...value.l2Templates[0],
  id: TEMPLATE_ID,
  version: GELIOS_PROVIDER_PACKAGE_VERSION,
  steps: [{
    id: "collection.trigger",
    kind: "collection_trigger",
    collectionProfileDriven: true,
  }, {
    id: "provider.fetch-monitoring-config",
    kind: "provider_request",
    capabilityId: MONITORING_CONFIG_CAPABILITY_ID,
  }, {
    id: "provider.fetch-units",
    kind: "provider_request",
    capabilityId: UNIT_CAPABILITY_ID,
  }, {
    id: "provider.extract-units",
    kind: "extract_items",
    capabilityId: UNIT_CAPABILITY_ID,
  }, {
    id: "ontology.map",
    kind: "semantic_mapping",
    mappingContractId: MAPPING_ID,
  }, {
    id: "data-product.publish",
    kind: "data_product_publish",
    dataProductId: GELIOS_POSITIONS_DATA_PRODUCT_ID,
    nodeType: "n8n-nodes-ndc.ndcDataProductPublish",
  }],
}];

export const geliosProviderPackageV4 = deepFreeze(value);

function deepFreeze(input) {
  if (!input || typeof input !== "object" || Object.isFrozen(input)) return input;
  Object.freeze(input);
  for (const child of Object.values(input)) deepFreeze(child);
  return input;
}
