{
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "$id": "https://opendeviceio.org/schema/v0.1/bundle.schema.json",
  "title": "OpenDeviceIO Bundle",
  "description": "A kit or assembly: one orderable part number that contains multiple component devices, nested sub-assemblies, factory-terminated cables, and non-I/O accessories. Component devices remain full ODIO devices (rendered as separate blocks); they may be embedded inline or referenced.",
  "type": "object",
  "required": ["odioVersion", "kind", "id", "bundle", "components"],
  "properties": {
    "$schema": { "type": "string" },
    "odioVersion": { "type": "string", "pattern": "^\\d+\\.\\d+\\.\\d+(?:-[0-9A-Za-z.-]+)?$" },
    "kind": { "const": "bundle", "description": "Document discriminator. Device documents have no 'kind'; bundles and cables do." },
    "id": {
      "type": "string",
      "pattern": "^[a-z0-9][a-z0-9-]*\\/[a-z0-9][a-z0-9._-]*(?:@[a-z0-9][a-z0-9._-]*)?$"
    },
    "bundle": { "$ref": "#/$defs/bundleIdentity" },
    "components": {
      "type": "array",
      "description": "The kit contents. Each component is a device, a nested bundle, a cable, or an accessory.",
      "minItems": 1,
      "items": { "$ref": "#/$defs/component" }
    },
    "standards": {
      "type": "array",
      "items": { "$ref": "https://opendeviceio.org/schema/v0.1/device.schema.json#/$defs/standard" }
    },
    "parameters": { "$ref": "https://opendeviceio.org/schema/v0.1/device.schema.json#/$defs/parameters" },
    "provenance": { "$ref": "https://opendeviceio.org/schema/v0.1/device.schema.json#/$defs/provenance" }
  },
  "patternProperties": { "^x-": {} },
  "additionalProperties": false,

  "$defs": {
    "bundleIdentity": {
      "type": "object",
      "description": "Kit/assembly identity. 'model' is the orderable part number.",
      "required": ["manufacturer", "model"],
      "properties": {
        "manufacturer": { "type": "string", "minLength": 1 },
        "model": { "type": "string", "minLength": 1, "description": "Kit/assembly part number." },
        "revision": { "type": "string" },
        "category": { "type": "string", "pattern": "^[a-z0-9]+(?:/[a-z0-9-]+)*$" },
        "productLine": { "type": "string" },
        "sku": { "type": "string" },
        "gtin": { "type": "string", "pattern": "^\\d{8,14}$" },
        "productUrl": { "type": "string", "format": "uri" },
        "datasheetUrl": { "type": "string", "format": "uri" },
        "description": { "type": "string" }
      },
      "patternProperties": { "^x-": {} },
      "additionalProperties": false
    },

    "component": {
      "type": "object",
      "description": "One kit component. 'type' discriminates the shape.",
      "required": ["type"],
      "oneOf": [
        { "$ref": "#/$defs/deviceComponent" },
        { "$ref": "#/$defs/bundleComponent" },
        { "$ref": "#/$defs/cableComponent" },
        { "$ref": "#/$defs/accessoryComponent" }
      ]
    },

    "deviceComponent": {
      "type": "object",
      "description": "A component device. Provide it inline (device + ports [+ power/physical/...]) OR reference an external device document.",
      "required": ["type"],
      "properties": {
        "type": { "const": "device" },
        "quantity": { "type": "integer", "minimum": 1, "default": 1 },
        "designator": { "type": "string", "description": "Role/label within the kit, e.g. 'Touch Screen', 'Presentation Transmitter'." },
        "id": { "type": "string", "pattern": "^[a-z0-9][a-z0-9._-]*$", "description": "Optional component-local id." },
        "device": { "$ref": "https://opendeviceio.org/schema/v0.1/device.schema.json#/$defs/device" },
        "ports": { "type": "array", "items": { "$ref": "https://opendeviceio.org/schema/v0.1/device.schema.json#/$defs/port" } },
        "power": { "$ref": "https://opendeviceio.org/schema/v0.1/device.schema.json#/$defs/power" },
        "physical": { "$ref": "https://opendeviceio.org/schema/v0.1/device.schema.json#/$defs/physical" },
        "standards": { "type": "array", "items": { "$ref": "https://opendeviceio.org/schema/v0.1/device.schema.json#/$defs/standard" } },
        "parameters": { "$ref": "https://opendeviceio.org/schema/v0.1/device.schema.json#/$defs/parameters" },
        "ref": { "$ref": "#/$defs/ref" }
      },
      "patternProperties": { "^x-": {} },
      "additionalProperties": false,
      "oneOf": [
        { "required": ["device", "ports"] },
        { "required": ["ref"] }
      ]
    },

    "bundleComponent": {
      "type": "object",
      "description": "A nested sub-assembly (a bundle within a bundle). Provide it inline (bundle + components) OR reference an external bundle.",
      "required": ["type"],
      "properties": {
        "type": { "const": "bundle" },
        "quantity": { "type": "integer", "minimum": 1, "default": 1 },
        "designator": { "type": "string" },
        "id": { "type": "string", "pattern": "^[a-z0-9][a-z0-9._-]*$" },
        "bundle": { "$ref": "#/$defs/bundleIdentity" },
        "components": { "type": "array", "minItems": 1, "items": { "$ref": "#/$defs/component" } },
        "ref": { "$ref": "#/$defs/ref" }
      },
      "patternProperties": { "^x-": {} },
      "additionalProperties": false,
      "oneOf": [
        { "required": ["bundle", "components"] },
        { "required": ["ref"] }
      ]
    },

    "cableComponent": {
      "type": "object",
      "description": "A cable in the kit. Provide it inline OR reference an external cable document.",
      "required": ["type"],
      "properties": {
        "type": { "const": "cable" },
        "quantity": { "type": "integer", "minimum": 1, "default": 1 },
        "designator": { "type": "string", "description": "Role, e.g. 'Primary display', 'UC Engine LAN'." },
        "id": { "type": "string", "pattern": "^[a-z0-9][a-z0-9._-]*$" },
        "cable": { "$ref": "https://opendeviceio.org/schema/v0.1/cable.schema.json#/$defs/cable" },
        "ref": { "$ref": "#/$defs/ref" }
      },
      "patternProperties": { "^x-": {} },
      "additionalProperties": false,
      "oneOf": [
        { "required": ["cable"] },
        { "required": ["ref"] }
      ]
    },

    "accessoryComponent": {
      "type": "object",
      "description": "A non-I/O accessory (mounting hardware, brackets, etc.) — a BOM line item with no ports.",
      "required": ["type", "name"],
      "properties": {
        "type": { "const": "accessory" },
        "quantity": { "type": "integer", "minimum": 1, "default": 1 },
        "designator": { "type": "string" },
        "name": { "type": "string", "minLength": 1 },
        "model": { "type": "string", "description": "Part number, if any." },
        "manufacturer": { "type": "string" },
        "description": { "type": "string" }
      },
      "patternProperties": { "^x-": {} },
      "additionalProperties": false
    },

    "ref": {
      "type": "object",
      "description": "A reference to an external device/bundle/cable document by id and/or URL.",
      "properties": {
        "id": { "type": "string", "description": "Document id, e.g. 'crestron/tsw-1070-b-s-t-v'." },
        "url": { "type": "string", "format": "uri" }
      },
      "patternProperties": { "^x-": {} },
      "additionalProperties": false,
      "anyOf": [ { "required": ["id"] }, { "required": ["url"] } ]
    }
  }
}
