openapi: 3.0.3
info:
  title: ShuffledDeck API
  description: |
    A stateless API for managing shuffled card decks. The deck state is encoded as a compact string
    containing the BitSet states and counters, allowing complete stateless operation without external storage.
  version: 1.0.0
  contact:
    name: Cards API
    email: dalen.kambur@gmail.com
servers:
  - url: https://deck-api.api.kambur.ie/deck-api
    description: Test
paths:
  /deck/create:
    post:
      summary: Create a new shuffled deck
      description: |
        Creates a new shuffled deck with the specified deck type and optional random seed.
        Returns the initial deck state as an encoded string.
      operationId: createDeck
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              required:
                - deckType
              properties:
                deckType:
                  type: string
                  enum: [standard52, uno]
                  description: Type of deck to create
                  example: standard52
            examples:
              standard_deck:
                summary: Standard 52-card deck
                value:
                  deckType: standard52
              uno_deck:
                summary: Uno deck
                value:
                  deckType: uno
      responses:
        '200':
          description: Deck created successfully
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/DeckState'
        '400':
          description: Invalid deck type or parameters
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'

  /deck/draw:
    patch:
      summary: Draw the next card from the deck
      description: |
        Draws the next card from the shuffled deck using the iterator's next() method.
        Automatically handles swapping between used and returned cards when needed.
      operationId: drawCard
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/DeckState'
            examples:
              pull_standard_52:
                summary: Pull a card from standard 52 card deck.
                value:
                  deckType: standard52
                  deckState: "rO0ABXcUAApzdGFuZGFyZDUyAAAAMwAAAAB1cgACW0p4IAS1ErF1kwIAAHhwAAAAAQAAAAACAAAAdXEAfgAAAAAAAQAP////////"
              pull_uno:
                summary: Pull an uno card.
                value:
                  deckType: uno
                  deckState: "rO0ABXcNAAN1bm8AAABsAAAAAHVyAAJbSnggBLUSsXWTAgAAeHAAAAAAdXEAfgAAAAAAAv//////////AAAP//////8="


      responses:
        '200':
          description: Card drawn successfully
          content:
            application/json:
              schema:
                type: object
                properties:
                  card:
                    $ref: '#/components/schemas/CardSchema'
                  deck:
                    $ref: '#/components/schemas/DeckState'
        '400':
          description: Invalid deck state
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'

        '404':
          description: Deck is empty (no more cards available)
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'


  /deck/return:
    put:
      summary: Return a card to the deck
      description: |
        Returns a card to the deck's return pile. The card must not already be in the return pile.
        Uses inverse logic with returnedCards BitSet.
      operationId: returnCard
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              required:
                - deckState
                - card
              properties:
                deck:
                  $ref: '#/components/schemas/DeckState'
                card:
                  $ref: '#/components/schemas/CardSchema'
            examples:
              return_standard_52:
                summary: Return a card to standard 52 card deck.
                value:
                  deck:
                    deckType: standard52
                    deckState: "rO0ABXcUAApzdGFuZGFyZDUyAAAAMwAAAAB1cgACW0p4IAS1ErF1kwIAAHhwAAAAAQAAAAACAAAAdXEAfgAAAAAAAQAP////////"
                  card:
                    rank: KING
                    suit: CLUBS
              return_uno:
                summary: Return an uno card.
                value:
                  deck:
                    deckType: uno
                    deckState: "rO0ABXcNAAN1bm8AAABrAAAAAHVyAAJbSnggBLUSsXWTAgAAeHAAAAABAAAAAAAAQAB1cQB+AAAAAAAC//////////8AAA///////w=="
                  card:
                    colour: RED
                    rank: SEVEN
                    ordinal: 14
      responses:
        '200':
          description: Card returned successfully
          content:
            application/json:
              schema:
                type: object
                properties:
                  deck:
                    $ref: '#/components/schemas/DeckState'
                required:
                  - deck
        '400':
          description: Invalid deck state or card
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
        '409':
          description: Card already returned
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'


components:
  schemas:
    DeckState:
      type: object
      properties:
        deckState:
          type: string
          description: |
            Base64 encoded JSON containing the complete deck state:
            - usedCards: Base64 encoded BitSet
            - returnedCards: Base64 encoded BitSet  
            - cardsLeft: integer
            - cardsReturned: integer
            - deckType: string identifying the deck type
          example: "eyJ1c2VkQ2FyZHMiOiJBQUFBQUFBPSIsInJldHVybmVkQ2FyZHMiOiJBQUFBQUFBPSIsImNhcmRzTGVmdCI6NTIsImNhcmRzUmV0dXJuZWQiOjAsImRlY2tUeXBlIjoic3RhbmRhcmQ1MiJ9"
        deckType:
          type: string
          description: Type of deck created
          example: "standard52"
      required:
        - deckState
        - deckType

    CardSchema:
    #  oneOf:
    #    - type: object
    #      properties:
    #        suit:
    #          type: string
    #          enum: [hearts, diamonds, clubs, spades]
    #          description: Card suit (for standard playing cards)
    #          example: "hearts"
    #        rank:
    #          type: string
    #          enum: [A, "2", "3", "4", "5", "6", "7", "8", "9", "10", J, Q, K]
    #          description: Card rank (for standard playing cards)
    #          example: "K"
    #      required:
    #        - suit
    #        - rank
      type: object
      properties:
        any:
          x-jackson-type: com.fasterxml.jackson.databind.JsonNode
      additionalProperties: false
      description: |
          Placeholder for non-standard cards (e.g. Uno, Tarot, custom decks).
          Structure not specified yet.


    Error:
      type: object
      properties:
        error:
          type: string
          description: Error code
          example: "INVALID_DECK_STATE"
        message:
          type: string
          description: Human-readable error message
          example: "The provided deck state is invalid or corrupted"
        details:
          type: object
          additionalProperties: true
          description: Additional error details
      required:
        - error
        - message

  securitySchemes:
    ApiKeyAuth:
      type: apiKey
      in: header
      name: X-API-Key
      description: API key for authentication

security:
  - ApiKeyAuth: []