{
  "$schema": "https://json-schema.org/draft-07/schema",
  "$id": "https://kyle-pierce.github.io/temper-docs/program-import/schema.json",
  "title": "Temper Program Import Format v1.0",
  "description": "Schema for importing workout programs into the Temper mobile app.",
  "type": "object",
  "required": ["name", "context", "description"],
  "additionalProperties": false,
  "oneOf": [
    { "required": ["workouts", "cycle"], "not": { "required": ["phases"] } },
    { "required": ["phases"], "not": { "required": ["workouts", "cycle"] } }
  ],
  "properties": {
    "name": {
      "type": "string",
      "minLength": 1,
      "description": "Display name of the program."
    },
    "context": {
      "type": "string",
      "minLength": 1,
      "description": "Short, human-readable description"
    },
    "description": {
      "type": "string",
      "minLength": 1,
      "description": "Short description shown to the user."
    },
    "cycle": {
      "type": "array",
      "minItems": 1,
      "description": "Ordered list of cycle slots. Each slot is a workout name (string) or a rest day ({ \"type\": \"rest\" }).",
      "items": {
        "oneOf": [
          {
            "type": "string",
            "minLength": 1
          },
          {
            "type": "object",
            "required": ["type"],
            "additionalProperties": false,
            "properties": {
              "type": { "type": "string", "const": "rest" }
            }
          }
        ]
      }
    },
    "workouts": {
      "type": "array",
      "minItems": 1,
      "description": "List of workouts. Names must be unique.",
      "items": {
        "type": "object",
        "required": ["name", "exercises"],
        "additionalProperties": false,
        "properties": {
          "name": {
            "type": "string",
            "minLength": 1,
            "description": "Display name. Must be unique across all workouts and must match cycle slot strings."
          },
          "focus": {
            "type": "string",
            "enum": ["push", "pull", "legs", "upper", "lower", "full_body", "core"],
            "description": "Optional workout focus category."
          },
          "exercises": {
            "type": "array",
            "minItems": 1,
            "description": "Ordered list of exercises.",
            "items": {
              "type": "object",
              "required": ["exerciseRef", "sets", "rest"],
              "additionalProperties": false,
              "oneOf": [
                {
                  "required": ["reps"],
                  "not": { "required": ["durationSeconds"] }
                },
                {
                  "required": ["durationSeconds"],
                  "not": { "required": ["reps"] }
                }
              ],
              "properties": {
                "exerciseRef": {
                  "type": "string",
                  "minLength": 1,
                  "description": "Temper exercise catalog ID."
                },
                "sets": {
                  "type": "integer",
                  "minimum": 1,
                  "description": "Total number of sets."
                },
                "reps": {
                  "type": "object",
                  "required": ["min", "max"],
                  "additionalProperties": false,
                  "description": "Target rep range for catalog exercises with trackingType \"reps\". min must be <= max.",
                  "properties": {
                    "min": { "type": "integer", "minimum": 1 },
                    "max": { "type": "integer", "minimum": 1 }
                  }
                },
                "durationSeconds": {
                  "type": "integer",
                  "minimum": 1,
                  "description": "Target duration, in seconds, for catalog exercises with trackingType \"duration\"."
                },
                "rest": {
                  "type": "object",
                  "required": ["workSeconds"],
                  "additionalProperties": false,
                  "description": "Rest duration configuration.",
                  "properties": {
                    "workSeconds": {
                      "type": "integer",
                      "minimum": 1,
                      "description": "Rest after work sets, in seconds."
                    },
                    "warmupSeconds": {
                      "type": "integer",
                      "minimum": 0,
                      "description": "Rest after warmup sets, in seconds. Defaults to 0."
                    }
                  }
                },
                "setTypes": {
                  "type": "array",
                  "description": "Per-set type labels. Length must equal sets. Omit to default all sets to \"work\".",
                  "items": {
                    "type": "string",
                    "enum": ["work", "warmup", "drop", "failure"]
                  }
                },
                "notes": {
                  "type": "string",
                  "description": "Optional notes shown to the user for this exercise."
                }
              }
            }
          },
          "supersets": {
            "type": "array",
            "description": "Optional superset groups. Each group lists adjacent exercise names to superset together.",
            "items": {
              "type": "array",
              "minItems": 2,
              "items": {
                "type": "string",
                "minLength": 1
              }
            }
          }
        }
      }
    },
    "phases": {
      "type": "array",
      "minItems": 2,
      "description": "Ordered list of program phases for periodized programs. Use instead of top-level workouts and cycle.",
      "items": {
        "type": "object",
        "required": ["name", "cycleRepetitions", "workouts", "cycle"],
        "additionalProperties": false,
        "properties": {
          "name": {
            "type": "string",
            "minLength": 1,
            "description": "Display name of the phase (e.g. \"Hypertrophy Block\")."
          },
          "cycleRepetitions": {
            "type": "integer",
            "minimum": 1,
            "description": "How many times to complete this phase's cycle before advancing to the next phase."
          },
          "workouts": {
            "type": "array",
            "minItems": 1,
            "description": "Phase-specific workouts. Names must be unique within the phase.",
            "items": { "$ref": "#/properties/workouts/items" }
          },
          "cycle": {
            "type": "array",
            "minItems": 1,
            "description": "Phase-specific cycle. Workout name strings must match a workout name within this phase.",
            "items": { "$ref": "#/properties/cycle/items" }
          }
        }
      }
    },
    "trainingGuidelines": {
      "type": "object",
      "required": ["progressionPolicy", "missedTargetPolicy", "deloadPolicy"],
      "additionalProperties": false,
      "description": "Optional auto-progression, missed-target, and deload policies.",
      "properties": {
        "progressionPolicy": {
          "description": "How weight progresses between sessions.",
          "oneOf": [
            {
              "type": "object",
              "required": ["type"],
              "additionalProperties": false,
              "properties": { "type": { "type": "string", "const": "manual" } }
            },
            {
              "type": "object",
              "required": ["type", "upperBodyIncrement", "lowerBodyIncrement"],
              "additionalProperties": false,
              "properties": {
                "type": { "type": "string", "const": "linear" },
                "upperBodyIncrement": { "type": "number", "exclusiveMinimum": 0 },
                "lowerBodyIncrement": { "type": "number", "exclusiveMinimum": 0 },
                "requireAllWorkSetsCompleted": { "type": "boolean" }
              }
            },
            {
              "type": "object",
              "required": ["type", "defaultIncrement"],
              "additionalProperties": false,
              "properties": {
                "type": { "type": "string", "const": "double_progression" },
                "defaultIncrement": { "type": "number", "exclusiveMinimum": 0 }
              }
            }
          ]
        },
        "missedTargetPolicy": {
          "description": "What happens when the user misses the rep target.",
          "oneOf": [
            {
              "type": "object",
              "required": ["type"],
              "additionalProperties": false,
              "properties": { "type": { "type": "string", "const": "manual" } }
            },
            {
              "type": "object",
              "required": ["type", "missesBeforeReduction", "reductionPercent"],
              "additionalProperties": false,
              "properties": {
                "type": { "type": "string", "const": "repeat_then_reduce" },
                "missesBeforeReduction": { "type": "integer", "minimum": 1 },
                "reductionPercent": { "type": "number", "minimum": 1, "maximum": 100 }
              }
            }
          ]
        },
        "deloadPolicy": {
          "description": "When and how to deload.",
          "oneOf": [
            {
              "type": "object",
              "required": ["type"],
              "additionalProperties": false,
              "properties": { "type": { "type": "string", "const": "manual" } }
            },
            {
              "type": "object",
              "required": ["type", "everyNWeeks", "loadPercent"],
              "additionalProperties": false,
              "properties": {
                "type": { "type": "string", "const": "every_n_weeks" },
                "everyNWeeks": { "type": "integer", "minimum": 1 },
                "loadPercent": { "type": "number", "minimum": 1, "maximum": 100 }
              }
            }
          ]
        }
      }
    }
  }
}
