{
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "$id": "urn:locanda:schema:export:1",
  "title": "Locanda export file, schema version 1",
  "description": "Spellbooks exported for re-import (docs/spec/05-data-model.md, FR-6). Stores ids and enum keys only, never translated text. Any change bumps schemaVersion and adds a migration.",
  "type": "object",
  "additionalProperties": false,
  "required": ["format", "schemaVersion", "exportedAt", "appVersion", "dataVersion", "spellbooks"],
  "properties": {
    "format": { "const": "locanda" },
    "schemaVersion": { "const": 1 },
    "exportedAt": { "$ref": "#/$defs/dateTime" },
    "appVersion": {
      "type": "string",
      "maxLength": 64,
      "pattern": "^(0|[1-9]\\d*)\\.(0|[1-9]\\d*)\\.(0|[1-9]\\d*)(?:-[0-9A-Za-z.-]+)?(?:\\+[0-9A-Za-z.-]+)?$"
    },
    "dataVersion": { "type": "string", "pattern": "^[a-z0-9][a-z0-9.-]{0,63}$" },
    "spellbooks": {
      "description": "At least one, except in a file of custom spells only, which holds none, and in an \"Export all\" file (one with settings), which may hold none (checked after schema validation).",
      "type": "array",
      "maxItems": 500,
      "items": { "$ref": "#/$defs/spellbook" }
    },
    "customSpells": {
      "description": "The custom spells the file's spellbooks use (one spellbook) every custom spell (Export all), or every custom spell or those with one tag (Export custom spells). Each id appears once (checked after schema validation). Absent means none.",
      "type": "array",
      "maxItems": 1000,
      "items": { "$ref": "urn:locanda:schema:custom-spell" }
    },
    "settings": {
      "description": "The app settings, only in an \"Export all\" file (FR-6.7).",
      "type": "object",
      "additionalProperties": false,
      "required": ["theme", "locale", "activeSpellbook"],
      "properties": {
        "theme": { "enum": ["system", "light", "dark"] },
        "locale": { "enum": ["en", "it"] },
        "activeSpellbook": {
          "description": "A spellbook id, possibly not in the file; ignored on import when no such spellbook exists afterwards.",
          "anyOf": [{ "$ref": "#/$defs/uuid" }, { "type": "null" }]
        }
      }
    }
  },
  "$defs": {
    "spellbook": {
      "type": "object",
      "additionalProperties": false,
      "required": ["id", "name", "character", "mode", "limit", "notes", "spells", "createdAt", "updatedAt"],
      "properties": {
        "id": { "$ref": "#/$defs/uuid" },
        "name": { "$ref": "#/$defs/name" },
        "character": {
          "type": "object",
          "additionalProperties": false,
          "required": ["name", "classes", "level"],
          "properties": {
            "name": {
              "description": "Empty when not set.",
              "type": "string",
              "maxLength": 100,
              "pattern": "^[^\\u0000-\\u001F\\u007F]*$"
            },
            "classes": {
              "type": "array",
              "maxItems": 8,
              "uniqueItems": true,
              "items": { "$ref": "urn:locanda:schema:spell#/$defs/casterClass" }
            },
            "level": { "type": ["integer", "null"], "minimum": 1, "maximum": 20 }
          }
        },
        "mode": { "enum": ["spellbook", "known"] },
        "limit": {
          "description": "Max prepared (Spellbook mode) or max known (Known mode); a warning, never enforced.",
          "type": ["integer", "null"],
          "minimum": 1,
          "maximum": 1000
        },
        "notes": {
          "type": "string",
          "maxLength": 2000,
          "pattern": "^[^\\u0000-\\u0008\\u000B\\u000C\\u000E-\\u001F\\u007F]*$"
        },
        "spells": {
          "description": "Unknown spell ids are allowed and kept (FR-6.4). Each spellId appears once (checked after schema validation).",
          "type": "array",
          "maxItems": 1000,
          "items": {
            "type": "object",
            "additionalProperties": false,
            "required": ["spellId", "prepared", "addedAt"],
            "properties": {
              "spellId": {
                "description": "An SRD spell slug or a custom spell id (custom:<uuid>).",
                "anyOf": [
                  { "$ref": "urn:locanda:schema:spell#/$defs/spellId" },
                  { "$ref": "urn:locanda:schema:custom-spell#/$defs/customSpellId" }
                ]
              },
              "prepared": {
                "description": "Kept in Known mode too, so switching back to Spellbook mode restores it.",
                "type": "boolean"
              },
              "addedAt": { "$ref": "#/$defs/dateTime" }
            }
          }
        },
        "createdAt": { "$ref": "#/$defs/dateTime" },
        "updatedAt": { "$ref": "#/$defs/dateTime" }
      }
    },
    "name": {
      "type": "string",
      "minLength": 1,
      "maxLength": 100,
      "pattern": "^[^\\u0000-\\u001F\\u007F]+$"
    },
    "uuid": {
      "type": "string",
      "format": "uuid",
      "pattern": "^[0-9a-f]{8}-[0-9a-f]{4}-[1-8][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$"
    },
    "dateTime": {
      "description": "RFC 3339 date-time; the calendar date is also checked after schema validation.",
      "type": "string",
      "format": "date-time",
      "pattern": "^\\d{4}-(0[1-9]|1[0-2])-(0[1-9]|[12]\\d|3[01])T([01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(\\.\\d{1,9})?(Z|[+-]([01]\\d|2[0-3]):[0-5]\\d)$"
    }
  }
}
