openapi: 3.0.3
info:
  title: NovaTrek Adventures - Gear Inventory Service
  description: |
    Manages rental equipment inventory, gear packages, guest assignments,
    maintenance tracking, and stock levels across NovaTrek Adventures locations.
    Supports the full lifecycle of outdoor recreation gear from procurement
    through retirement, including condition monitoring and scheduled maintenance.
  version: 2.4.0
  contact:
    name: NovaTrek Platform Engineering
    email: platform-eng@novatrek.example.com

servers:
  - url: https://api.novatrek.example.com/gear/v1
    description: Production
  - url: https://api-staging.novatrek.example.com/gear/v1
    description: Staging

tags:
  - name: Gear Items
    description: Individual inventory item management
  - name: Gear Packages
    description: Predefined gear bundles for trip types
  - name: Gear Assignments
    description: Assign and return gear for participants
  - name: Maintenance
    description: Maintenance event tracking and history
  - name: Inventory Levels
    description: Stock level reporting by location and category

paths:
  /gear-items:
    get:
      operationId: searchGearItems
      summary: Search gear inventory
      description: Returns a paginated list of gear items matching the provided filters.
      tags:
        - Gear Items
      parameters:
        - name: category
          in: query
          description: Filter by gear category
          schema:
            $ref: '#/components/schemas/GearCategory'
        - name: size
          in: query
          description: Filter by gear size
          schema:
            $ref: '#/components/schemas/GearSize'
        - name: condition
          in: query
          description: Filter by current condition
          schema:
            $ref: '#/components/schemas/GearCondition'
        - name: availability
          in: query
          description: Filter by availability status
          schema:
            type: string
            enum:
              - AVAILABLE
              - ASSIGNED
              - IN_MAINTENANCE
              - ALL
            default: ALL
        - name: location_id
          in: query
          description: Filter by storage location identifier
          schema:
            type: string
            format: uuid
        - name: page
          in: query
          description: Page number for pagination (1-based)
          schema:
            type: integer
            minimum: 1
            default: 1
        - name: page_size
          in: query
          description: Number of items per page
          schema:
            type: integer
            minimum: 1
            maximum: 100
            default: 25
      responses:
        '200':
          description: Paginated list of gear items
          content:
            application/json:
              schema:
                type: object
                properties:
                  items:
                    type: array
                    items:
                      $ref: '#/components/schemas/GearItem'
                  pagination:
                    $ref: '#/components/schemas/Pagination'
        '400':
          $ref: '#/components/responses/BadRequest'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '500':
          $ref: '#/components/responses/InternalError'
    post:
      operationId: addGearItem
      summary: Add new inventory item
      description: Registers a new piece of gear in the inventory system.
      tags:
        - Gear Items
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/GearItemCreate'
      responses:
        '201':
          description: Gear item created successfully
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/GearItem'
          headers:
            Location:
              description: URI of the newly created gear item
              schema:
                type: string
                format: uri
        '400':
          $ref: '#/components/responses/BadRequest'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '409':
          description: Duplicate serial number detected
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '500':
          $ref: '#/components/responses/InternalError'

  /gear-items/{item_id}:
    parameters:
      - $ref: '#/components/parameters/ItemId'
    get:
      operationId: getGearItem
      summary: Get gear item details
      description: Returns full details for a single gear item including current status and maintenance schedule.
      tags:
        - Gear Items
      responses:
        '200':
          description: Gear item details
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/GearItem'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '404':
          $ref: '#/components/responses/NotFound'
        '500':
          $ref: '#/components/responses/InternalError'
    patch:
      operationId: updateGearItem
      summary: Update gear item
      description: Partially updates a gear item record. Only provided fields are modified.
      tags:
        - Gear Items
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/GearItemUpdate'
      responses:
        '200':
          description: Gear item updated successfully
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/GearItem'
        '400':
          $ref: '#/components/responses/BadRequest'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '404':
          $ref: '#/components/responses/NotFound'
        '500':
          $ref: '#/components/responses/InternalError'

  /gear-packages:
    get:
      operationId: listGearPackages
      summary: List gear packages
      description: Returns all predefined gear bundles, optionally filtered by activity type.
      tags:
        - Gear Packages
      parameters:
        - name: activity_type
          in: query
          description: Filter packages by outdoor activity type
          schema:
            type: string
            enum:
              - ROCK_CLIMBING
              - KAYAKING
              - BACKPACKING
              - MOUNTAINEERING
              - CYCLING
              - MULTI_SPORT
      responses:
        '200':
          description: List of gear packages
          content:
            application/json:
              schema:
                type: object
                properties:
                  packages:
                    type: array
                    items:
                      $ref: '#/components/schemas/GearPackage'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '500':
          $ref: '#/components/responses/InternalError'

  /gear-packages/{package_id}:
    parameters:
      - name: package_id
        in: path
        required: true
        description: Unique identifier of the gear package
        schema:
          type: string
          format: uuid
    get:
      operationId: getGearPackage
      summary: Get gear package details
      description: Returns full details for a gear package including the list of included items and pricing.
      tags:
        - Gear Packages
      responses:
        '200':
          description: Gear package details
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/GearPackage'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '404':
          $ref: '#/components/responses/NotFound'
        '500':
          $ref: '#/components/responses/InternalError'

  /gear-assignments:
    post:
      operationId: createGearAssignment
      summary: Assign gear to a participant
      description: |
        Creates a gear assignment linking inventory items to a trip participant.
        References a reservation_id from the Reservations service (svc-reservations).
        Validates item availability before assignment.
      tags:
        - Gear Assignments
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/GearAssignmentCreate'
      responses:
        '201':
          description: Gear assignment created
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/GearAssignment'
          headers:
            Location:
              description: URI of the newly created assignment
              schema:
                type: string
                format: uri
        '400':
          $ref: '#/components/responses/BadRequest'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '409':
          description: One or more items are already assigned or unavailable
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '422':
          description: Referenced reservation not found or invalid participant
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '500':
          $ref: '#/components/responses/InternalError'

  /gear-assignments/{assignment_id}:
    parameters:
      - name: assignment_id
        in: path
        required: true
        description: Unique identifier of the gear assignment
        schema:
          type: string
          format: uuid
    get:
      operationId: getGearAssignment
      summary: Get gear assignment details
      description: Returns full details of a gear assignment including item list and return status.
      tags:
        - Gear Assignments
      responses:
        '200':
          description: Gear assignment details
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/GearAssignment'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '404':
          $ref: '#/components/responses/NotFound'
        '500':
          $ref: '#/components/responses/InternalError'
    delete:
      operationId: returnGearAssignment
      summary: Return gear (close assignment)
      description: |
        Marks gear as returned and closes the assignment. Accepts optional
        condition and damage notes in the request body for post-return inspection.
      tags:
        - Gear Assignments
      requestBody:
        required: false
        content:
          application/json:
            schema:
              type: object
              properties:
                condition_on_return:
                  $ref: '#/components/schemas/GearCondition'
                damage_notes:
                  type: string
                  maxLength: 2000
                  description: Free-text notes describing any damage observed on return
      responses:
        '200':
          description: Gear returned and assignment closed
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/GearAssignment'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '404':
          $ref: '#/components/responses/NotFound'
        '409':
          description: Assignment already returned
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '500':
          $ref: '#/components/responses/InternalError'

  /gear-items/{item_id}/maintenance:
    parameters:
      - $ref: '#/components/parameters/ItemId'
    put:
      operationId: logMaintenanceEvent
      summary: Log a maintenance event
      description: Records a maintenance event (inspection, repair, or part replacement) for a gear item and updates its condition and next-due date.
      tags:
        - Maintenance
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/MaintenanceRecordCreate'
      responses:
        '200':
          description: Maintenance event recorded
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/MaintenanceRecord'
        '400':
          $ref: '#/components/responses/BadRequest'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '404':
          $ref: '#/components/responses/NotFound'
        '500':
          $ref: '#/components/responses/InternalError'

  /gear-items/{item_id}/maintenance-history:
    parameters:
      - $ref: '#/components/parameters/ItemId'
    get:
      operationId: getMaintenanceHistory
      summary: Get maintenance history
      description: Returns the chronological maintenance history for a specific gear item.
      tags:
        - Maintenance
      parameters:
        - name: limit
          in: query
          description: Maximum number of records to return
          schema:
            type: integer
            minimum: 1
            maximum: 200
            default: 50
      responses:
        '200':
          description: Maintenance history records
          content:
            application/json:
              schema:
                type: object
                properties:
                  gear_item_id:
                    type: string
                    format: uuid
                  records:
                    type: array
                    items:
                      $ref: '#/components/schemas/MaintenanceRecord'
                  total_records:
                    type: integer
        '401':
          $ref: '#/components/responses/Unauthorized'
        '404':
          $ref: '#/components/responses/NotFound'
        '500':
          $ref: '#/components/responses/InternalError'

  /inventory-levels:
    get:
      operationId: getInventoryLevels
      summary: Get stock levels by location and category
      description: Returns current inventory counts broken down by location and gear category, including available, assigned, and in-maintenance tallies.
      tags:
        - Inventory Levels
      parameters:
        - name: location_id
          in: query
          description: Filter to a specific location
          schema:
            type: string
            format: uuid
        - name: category
          in: query
          description: Filter to a specific gear category
          schema:
            $ref: '#/components/schemas/GearCategory'
      responses:
        '200':
          description: Inventory level summary
          content:
            application/json:
              schema:
                type: object
                properties:
                  levels:
                    type: array
                    items:
                      $ref: '#/components/schemas/InventoryLevel'
                  generated_at:
                    type: string
                    format: date-time
                    description: Timestamp when the inventory snapshot was computed
        '401':
          $ref: '#/components/responses/Unauthorized'
        '500':
          $ref: '#/components/responses/InternalError'

components:
  parameters:
    ItemId:
      name: item_id
      in: path
      required: true
      description: Unique identifier of the gear item
      schema:
        type: string
        format: uuid

  schemas:
    GearCategory:
      type: string
      enum:
        - HARNESS
        - HELMET
        - ROPE
        - CARABINER
        - KAYAK
        - PADDLE
        - LIFE_VEST
        - TENT
        - SLEEPING_BAG
        - BACKPACK
        - CLIMBING_SHOES
        - CRAMPON
        - ICE_AXE
        - BIKE

    GearCondition:
      type: string
      enum:
        - NEW
        - GOOD
        - FAIR
        - NEEDS_MAINTENANCE
        - RETIRED

    GearSize:
      type: string
      enum:
        - XS
        - S
        - M
        - L
        - XL
        - XXL
        - ONE_SIZE

    GearItem:
      type: object
      required:
        - id
        - name
        - category
        - size
        - condition
        - location_id
        - serial_number
        - purchase_date
        - status
      properties:
        id:
          type: string
          format: uuid
          description: Unique gear item identifier
        name:
          type: string
          maxLength: 200
          description: Human-readable name or model descriptor
          example: "Petzl Sitta Harness"
        category:
          $ref: '#/components/schemas/GearCategory'
        size:
          $ref: '#/components/schemas/GearSize'
        condition:
          $ref: '#/components/schemas/GearCondition'
        location_id:
          type: string
          format: uuid
          description: Storage location identifier
        serial_number:
          type: string
          maxLength: 100
          description: Manufacturer serial number (unique across inventory)
          example: "PTZ-2024-SIT-003921"
        purchase_date:
          type: string
          format: date
          description: Date the item was purchased or acquired
        last_maintenance:
          type: string
          format: date-time
          description: Timestamp of the most recent maintenance event
          nullable: true
        next_maintenance_due:
          type: string
          format: date
          description: Scheduled date for next maintenance
          nullable: true
        status:
          type: string
          enum:
            - AVAILABLE
            - ASSIGNED
            - IN_MAINTENANCE
            - RETIRED
          description: Current operational status

    GearItemCreate:
      type: object
      required:
        - name
        - category
        - size
        - location_id
        - serial_number
        - purchase_date
      properties:
        name:
          type: string
          maxLength: 200
        category:
          $ref: '#/components/schemas/GearCategory'
        size:
          $ref: '#/components/schemas/GearSize'
        condition:
          $ref: '#/components/schemas/GearCondition'
          default: NEW
        location_id:
          type: string
          format: uuid
        serial_number:
          type: string
          maxLength: 100
        purchase_date:
          type: string
          format: date
        next_maintenance_due:
          type: string
          format: date
          description: Optional initial maintenance schedule date

    GearItemUpdate:
      type: object
      description: Partial update payload. Only provided fields are modified.
      properties:
        name:
          type: string
          maxLength: 200
        size:
          $ref: '#/components/schemas/GearSize'
        condition:
          $ref: '#/components/schemas/GearCondition'
        location_id:
          type: string
          format: uuid
        status:
          type: string
          enum:
            - AVAILABLE
            - IN_MAINTENANCE
            - RETIRED
        next_maintenance_due:
          type: string
          format: date

    GearPackage:
      type: object
      required:
        - id
        - name
        - description
        - activity_type
        - items
        - rental_price_per_day
      properties:
        id:
          type: string
          format: uuid
          description: Unique package identifier
        name:
          type: string
          maxLength: 150
          example: "Summit Ready Kit"
        description:
          type: string
          maxLength: 1000
          example: "Complete climbing package for single-pitch sport routes"
        activity_type:
          type: string
          enum:
            - ROCK_CLIMBING
            - KAYAKING
            - BACKPACKING
            - MOUNTAINEERING
            - CYCLING
            - MULTI_SPORT
        items:
          type: array
          description: Categories and quantities included in this package
          items:
            type: object
            required:
              - category
              - quantity
            properties:
              category:
                $ref: '#/components/schemas/GearCategory'
              quantity:
                type: integer
                minimum: 1
              size_required:
                type: boolean
                default: true
                description: Whether the item must be size-matched to the participant
        rental_price_per_day:
          type: number
          format: double
          minimum: 0
          description: Daily rental price in USD
          example: 45.00

    GearAssignment:
      type: object
      required:
        - id
        - reservation_id
        - participant_guest_id
        - items
        - assigned_at
      properties:
        id:
          type: string
          format: uuid
          description: Unique assignment identifier
        reservation_id:
          type: string
          format: uuid
          description: Reference to the trip reservation in svc-reservations
        participant_guest_id:
          type: string
          format: uuid
          description: Guest profile identifier of the participant
        items:
          type: array
          description: List of gear items assigned
          items:
            type: object
            required:
              - gear_item_id
              - category
            properties:
              gear_item_id:
                type: string
                format: uuid
              category:
                $ref: '#/components/schemas/GearCategory'
              serial_number:
                type: string
              size:
                $ref: '#/components/schemas/GearSize'
        assigned_at:
          type: string
          format: date-time
          description: Timestamp when gear was checked out
        returned_at:
          type: string
          format: date-time
          nullable: true
          description: Timestamp when gear was checked back in
        condition_on_return:
          $ref: '#/components/schemas/GearCondition'
          nullable: true
        damage_notes:
          type: string
          maxLength: 2000
          nullable: true
          description: Free-text notes describing any damage observed on return

    GearAssignmentCreate:
      type: object
      required:
        - reservation_id
        - participant_guest_id
        - items
      properties:
        reservation_id:
          type: string
          format: uuid
          description: Reference to the trip reservation in svc-reservations
        participant_guest_id:
          type: string
          format: uuid
          description: Guest profile identifier of the participant
        items:
          type: array
          minItems: 1
          description: Gear items to assign
          items:
            type: object
            required:
              - gear_item_id
            properties:
              gear_item_id:
                type: string
                format: uuid

    MaintenanceRecord:
      type: object
      required:
        - id
        - gear_item_id
        - type
        - date
        - technician
      properties:
        id:
          type: string
          format: uuid
          description: Unique maintenance record identifier
        gear_item_id:
          type: string
          format: uuid
          description: The gear item this record belongs to
        type:
          type: string
          enum:
            - INSPECTION
            - REPAIR
            - REPLACEMENT
          description: Type of maintenance performed
        date:
          type: string
          format: date-time
          description: When the maintenance was performed
        technician:
          type: string
          maxLength: 150
          description: Name or identifier of the technician who performed the work
          example: "J. Rivera"
        notes:
          type: string
          maxLength: 2000
          nullable: true
          description: Detailed notes about work performed
          example: "Replaced worn belay loop stitching. Load tested to 22kN."
        cost:
          type: number
          format: double
          minimum: 0
          nullable: true
          description: Cost of the maintenance in USD
          example: 35.50
        next_due:
          type: string
          format: date
          nullable: true
          description: Recommended next maintenance date based on this event

    MaintenanceRecordCreate:
      type: object
      required:
        - type
        - date
        - technician
      properties:
        type:
          type: string
          enum:
            - INSPECTION
            - REPAIR
            - REPLACEMENT
        date:
          type: string
          format: date-time
        technician:
          type: string
          maxLength: 150
        notes:
          type: string
          maxLength: 2000
        cost:
          type: number
          format: double
          minimum: 0
        next_due:
          type: string
          format: date
        resulting_condition:
          $ref: '#/components/schemas/GearCondition'
          description: Condition of the item after maintenance

    InventoryLevel:
      type: object
      required:
        - location_id
        - category
        - total
        - available
        - assigned
        - in_maintenance
      properties:
        location_id:
          type: string
          format: uuid
          description: Storage location identifier
        location_name:
          type: string
          description: Human-readable location name
          example: "Boulder Base Camp Outfitters"
        category:
          $ref: '#/components/schemas/GearCategory'
        total:
          type: integer
          minimum: 0
          description: Total items of this category at this location
        available:
          type: integer
          minimum: 0
          description: Items currently available for assignment
        assigned:
          type: integer
          minimum: 0
          description: Items currently checked out to participants
        in_maintenance:
          type: integer
          minimum: 0
          description: Items currently undergoing maintenance

    Pagination:
      type: object
      properties:
        page:
          type: integer
          description: Current page number
        page_size:
          type: integer
          description: Number of items per page
        total_items:
          type: integer
          description: Total number of items matching the query
        total_pages:
          type: integer
          description: Total number of pages

    ErrorResponse:
      type: object
      required:
        - error_code
        - message
      properties:
        error_code:
          type: string
          description: Machine-readable error code
          example: "GEAR_ITEM_UNAVAILABLE"
        message:
          type: string
          description: Human-readable error description
          example: "Gear item abc-123 is currently assigned and cannot be reassigned."
        details:
          type: array
          items:
            type: object
            properties:
              field:
                type: string
              reason:
                type: string
          description: Field-level validation errors

  responses:
    BadRequest:
      description: Invalid request parameters or body
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/ErrorResponse'
    Unauthorized:
      description: Missing or invalid authentication credentials
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/ErrorResponse'
    NotFound:
      description: Requested resource not found
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/ErrorResponse'
    InternalError:
      description: Unexpected server error
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/ErrorResponse'

  securitySchemes:
    bearerAuth:
      type: http
      scheme: bearer
      bearerFormat: JWT
      description: JWT token issued by the NovaTrek identity provider

security:
  - bearerAuth: []
