---
openapi: 3.1.1
info:
  title: Basket Service API
  description: |
    Manages the lifecycle of customer shopping baskets in the BookWorm
    e-commerce system
  contact:
    name: Nhan Nguyen
    url: https://github.com/foxminchan
    email: nguyenxuannhan407@gmail.com
  license:
    name: MIT
    url: https://opensource.org/licenses/MIT
  version: "1.0"
externalDocs:
  description: Documentation
  url: https://github.com/foxminchan/BookWorm
servers:
  - url: "{protocol}://{environment}.basket.bookworm.com"
    description: Before deploying to production, ensure the environment is set correctly
    variables:
      protocol:
        enum:
          - https
          - http
          - grpc
        default: https
      environment:
        enum:
          - dev
          - stg
          - qa
        default: dev
  - url: "{protocol}://basket.bookworm.com"
    description: Production environment
    variables:
      protocol:
        enum:
          - https
          - grpc
        default: https
security:
  - OAuth:
      - basket
paths:
  /api/v1/baskets:
    put:
      tags:
        - Basket
      summary: Update Basket
      description: Update a basket by its unique identifier
      x-eventcatalog-message-type: command
      operationId: UpdateBasketEndpoint
      security:
        - OAuth:
            - basket
      requestBody:
        description: The command to update the basket with new items
        content:
          application/json:
            schema:
              "$ref": "#/components/schemas/UpdateBasketCommand"
            examples:
              single-item:
                summary: Update basket with a single item
                value:
                  items:
                    - id: "019622a3-a3ae-7705-a11b-a08f2a2ca621"
                      quantity: 2
              multiple-items:
                summary: Update basket with multiple items
                value:
                  items:
                    - id: "019622a3-a3ae-7705-a11b-a08f2a2ca621"
                      quantity: 2
                    - id: "019622a4-a3ae-7705-a11b-a08f2a2ca622"
                      quantity: 1
        required: true
      responses:
        "204":
          description: No Content
        "400":
          description: Bad Request
          content:
            application/problem+json:
              schema:
                "$ref": "#/components/schemas/HttpValidationProblemDetails"
              examples:
                invalid-quantity:
                  summary: Invalid quantity provided
                  value:
                    type: "https://tools.ietf.org/html/rfc9110#section-15.5.1"
                    title: "Validation failed"
                    status: 400
                    detail: "One or more validation errors has occurred"
                    errors:
                      - propertyName: "Quantity"
                        errorMessage: "'Quantity' must be greater than 0."
                        severity: 0
                empty-item-id:
                  summary: Invalid item ID format
                  value:
                    type: "https://tools.ietf.org/html/rfc9110#section-15.5.1"
                    title: "Validation failed"
                    status: 400
                    detail: "One or more validation errors has occurred"
                    errors:
                      - propertyName: "Id"
                        errorMessage: "'Id' must not be empty."
                        severity: 0
        "401":
          description: Unauthorized - Access token is missing or invalid.
    get:
      tags:
        - Basket
      summary: Get Basket
      description: Get a basket by user
      x-eventcatalog-message-type: query
      operationId: GetBasketEndpoint
      responses:
        "200":
          description: OK
          content:
            application/json:
              schema:
                "$ref": "#/components/schemas/CustomerBasketDto"
              examples:
                empty-basket:
                  summary: Empty basket response
                  value:
                    id: "019622af-19dd-73dd-9420-9e9d401ad85b"
                    items: []
                basket-with-items:
                  summary: Basket with multiple items
                  value:
                    id: "019622af-19dd-73dd-9420-9e9d401ad85b"
                    items:
                      - id: "019622a3-a3ae-7705-a11b-a08f2a2ca621"
                        quantity: 2
                        name: "Designing Data-Intensive Applications"
                        price: 46.67
                        priceSale: 41.89
                      - id: "019622a4-a3ae-7705-a11b-a08f2a2ca622"
                        quantity: 1
                        name: "Clean Code"
                        price: 39.99
                        priceSale: 35.99
        "401":
          description: Unauthorized - Access token is missing or invalid.
        "404":
          description: Not Found
          content:
            application/problem+json:
              schema:
                "$ref": "#/components/schemas/ProblemDetails"
              example:
                basket-not-found:
                  summary: Basket not found
                  value:
                    type: "https://tools.ietf.org/html/rfc9110#section-15.5.5"
                    title: "Not Found"
                    status: 404
                    detail: "Basket with id 01962e92-02ed-7b23-8af6-95b267a97e44 not found."
    delete:
      tags:
        - Basket
      summary: Delete Basket
      description: Delete a basket by its unique identifier
      x-eventcatalog-message-type: command
      operationId: DeleteBasketEndpoint
      security:
        - OAuth:
            - basket
      responses:
        "204":
          description: No Content
        "401":
          description: Unauthorized - Access token is missing or invalid.
        "404":
          description: Not Found
          content:
            application/problem+json:
              schema:
                "$ref": "#/components/schemas/ProblemDetails"
              example:
                basket-not-found:
                  summary: Basket not found
                  value:
                    type: "https://tools.ietf.org/html/rfc9110#section-15.5.5"
                    title: "Not Found"
                    status: 404
                    detail: "Basket with id 01962e92-02ed-7b23-8af6-95b267a97e44 not found."
    post:
      tags:
        - Basket
      summary: Create Basket
      description: Create a new basket for a user
      x-eventcatalog-message-type: command
      operationId: CreateBasketEndpoint
      security:
        - OAuth:
            - basket
      requestBody:
        description: A command to create a basket with the specified items
        content:
          application/json:
            schema:
              "$ref": "#/components/schemas/CreateBasketCommand"
            examples:
              single-item:
                summary: Create basket with a single item
                value:
                  items:
                    - id: "019622a3-a3ae-7705-a11b-a08f2a2ca621"
                      quantity: 2
              multiple-items:
                summary: Create basket with multiple items
                value:
                  items:
                    - id: "019622a3-a3ae-7705-a11b-a08f2a2ca621"
                      quantity: 2
                    - id: "019622a4-a3ae-7705-a11b-a08f2a2ca622"
                      quantity: 1
        required: true
      responses:
        "201":
          description: Created
          content:
            application/json:
              schema:
                type: string
                description: The unique identifier of the basket
                example: "019622af-19dd-73dd-9420-9e9d401ad85b"
        "400":
          description: Bad Request
          content:
            application/problem+json:
              schema:
                "$ref": "#/components/schemas/HttpValidationProblemDetails"
              examples:
                invalid-quantity:
                  summary: Invalid quantity provided
                  value:
                    type: "https://tools.ietf.org/html/rfc9110#section-15.5.1"
                    title: "Validation failed"
                    status: 400
                    detail: "One or more validation errors has occurred"
                    errors:
                      - propertyName: "Quantity"
                        errorMessage: "'Quantity' must be greater than 0."
                        severity: 0
                empty-item-id:
                  summary: Invalid item ID format
                  value:
                    type: "https://tools.ietf.org/html/rfc9110#section-15.5.1"
                    title: "Validation failed"
                    status: 400
                    detail: "One or more validation errors has occurred"
                    errors:
                      - propertyName: "Id"
                        errorMessage: "'Id' must not be empty."
                        severity: 0
        "401":
          description: Unauthorized - Access token is missing or invalid.
  /grpc/v1/baskets:
    get:
      tags:
        - Basket
      summary: Get Basket (gRPC)
      description: Retrieve a basket using gRPC
      x-eventcatalog-message-type: query
      x-grpc-service: BasketGrpcService
      x-grpc-method: GetBasket
      security:
        - OAuth:
            - basket
      operationId: GetBasketGrpcEndpoint
      responses:
        "200":
          description: OK
          content:
            application/grpc:
              schema:
                "$ref": "#/components/schemas/BasketResponse"
              examples:
                empty-basket:
                  summary: Empty basket response
                  value:
                    id: "019622af-19dd-73dd-9420-9e9d401ad85b"
                    items: []
                basket-with-items:
                  summary: Basket with multiple items
                  value:
                    id: "019622af-19dd-73dd-9420-9e9d401ad85b"
                    items:
                      - id: "019622a3-a3ae-7705-a11b-a08f2a2ca621"
                        quantity: 2
                      - id: "019622a4-a3ae-7705-a11b-a08f2a2ca622"
                        quantity: 1
        "401":
          description: Unauthorized - Access token is missing or invalid.
        "404":
          description: Not Found
          content:
            application/problem+json:
              schema:
                "$ref": "#/components/schemas/ProblemDetails"
              example:
                basket-not-found:
                  summary: Basket not found
                  value:
                    type: "https://tools.ietf.org/html/rfc9110#section-15.5.5"
                    title: "Not Found"
                    status: 404
                    detail: "Basket with id 01962e92-02ed-7b23-8af6-95b267a97e44 not found."
components:
  schemas:
    BasketItemDto:
      type: object
      readOnly: true
      description: The basket item details
      properties:
        id:
          type:
            - string
          description: The unique identifier of the basket item
          example: "019622a3-a3ae-7705-a11b-a08f2a2ca621"
        quantity:
          type: integer
          format: int32
          description: The quantity of the basket item
          example: 16
        name:
          type: string
          description: The name of the basket item
          example: "Designing Data-Intensive Applications"
        price:
          type: number
          format: double
          description: The price of the basket item
          example: 46.67
        priceSale:
          type: number
          format: double
          description: The sale price of the basket item
          example: 41.89
    BasketItemRequest:
      required:
        - id
        - quantity
      type: object
      writeOnly: true
      description: The basket item request
      properties:
        id:
          type: string
          description: The unique identifier of the basket item
          example: "019622a3-a3ae-7705-a11b-a08f2a2ca621"
        quantity:
          type: integer
          format: int32
          description: The quantity of the basket item
          minimum: 1
          example: 16
    CreateBasketCommand:
      required:
        - items
      type: object
      writeOnly: true
      description: The command to create a basket
      properties:
        items:
          description: An array of basket items to be included in the basket
          example:
            - id: "019622a3-a3ae-7705-a11b-a08f2a2ca621"
              quantity: 2
            - id: "019622a4-a3ae-7705-a11b-a08f2a2ca622"
              quantity: 1
          type: array
          items:
            "$ref": "#/components/schemas/BasketItemRequest"
    UpdateBasketCommand:
      required:
        - items
      type: object
      writeOnly: true
      description: The command to update a basket
      properties:
        items:
          description: An array of basket items to update the basket with
          example:
            - id: "019622a3-a3ae-7705-a11b-a08f2a2ca621"
              quantity: 3
            - id: "019622a4-a3ae-7705-a11b-a08f2a2ca622"
              quantity: 1
          type: array
          items:
            "$ref": "#/components/schemas/BasketItemRequest"
    CustomerBasketDto:
      type: object
      readOnly: true
      description: The customer basket details
      example:
        id: "019622a3-a3ae-7705-a11b-a08f2a2ca621"
        items:
          - id: "019622a3-a3ae-7705-a11b-a08f2a2ca621"
            quantity: 2
            name: "Designing Data-Intensive Applications"
            price: 46.67
            priceSale: 41.89
          - id: "019622a4-a3ae-7705-a11b-a08f2a2ca622"
            quantity: 1
            name: "Clean Code"
            price: 39.99
            priceSale: 35.99
      properties:
        id:
          type:
            - string
          description: The unique identifier of the basket
          example: "019622a3-a3ae-7705-a11b-a08f2a2ca621"
        items:
          type: array
          items:
            "$ref": "#/components/schemas/BasketItemDto"
    HttpValidationProblemDetails:
      type: object
      readOnly: true
      x-scalar-ignore: true
      description: RFC 9110 (https://tools.ietf.org/html/rfc9110#section-15.5.1)
      properties:
        type:
          type: string
          description: The type of the problem
          example: "https://tools.ietf.org/html/rfc9110#section-15.5.1"
        title:
          type: string
          description: The title of the problem
          example: "Validation failed"
        status:
          type: integer
          format: int32
          description: The status code of the problem
          example: 400
        detail:
          type: string
          description: The detail of the problem
          example: "One or more validation errors has occurred"
        errors:
          type: array
          description: The validation errors
          example:
            - propertyName: "Quantity"
              errorMessage: "'Quantity' must be greater than 0."
              severity: 0
          items:
            type: object
            properties:
              propertyName:
                type: string
                description: The name of the property that failed validation
                example: "Quantity"
              errorMessage:
                type: string
                description: The error message describing the validation failure
                example: "'Quantity' must be greater than 0."
              attemptedValue:
                type: object
                description: The value that was attempted
                example: {} # Corrected: example is an empty object
              customState:
                type: object
                description: Custom state information
                example: {} # Corrected: example is an empty object
              severity:
                type: integer
                format: int32
                description: The severity level of the error
                example: 0
              errorCode:
                type:
                  - "string"
                  - "null"
                description: The error code
                example: null
              formattedMessagePlaceholderValues:
                type: object
                description: Placeholder values for the formatted message
                example: {}
    ProblemDetails:
      type: object
      readOnly: true
      x-scalar-ignore: true
      description: RFC 9110 (https://tools.ietf.org/html/rfc9110)
      properties:
        type:
          type: string
          description: The type of the problem
          example: "https://tools.ietf.org/html/rfc9110#section-15.5.5"
        title:
          type: string
          description: The title of the problem
          example: "Not Found"
        status:
          type: integer
          format: int32
          description: The status code of the problem
          example: 404
        detail:
          type: string
          description: The detail of the problem
          example: "Basket with id 01962e92-02ed-7b23-8af6-95b267a97e44 not found."
    BasketResponse:
      type: object
      readOnly: true
      description: |
        gRPC BasketResponse model (from basket.proto)
        This aligns with REST CustomerBasketDto but contains only core fields
      properties:
        id:
          type: string
          description: The unique identifier of the basket
          example: "019622a3-a3ae-7705-a11b-a08f2a2ca621"
        items:
          type: array
          description: Array of basket items
          items:
            "$ref": "#/components/schemas/Item"
    Item:
      type: object
      readOnly: true
      description: |
        gRPC Item model (from basket.proto)
        This aligns with REST BasketItemDto but contains only core fields
      properties:
        id:
          type: string
          description: The unique identifier of the item
          example: "019622a3-a3ae-7705-a11b-a08f2a2ca621"
        quantity:
          type: integer
          format: int32
          description: The quantity of the item
          example: 2
  securitySchemes:
    OAuth:
      type: oauth2
      description: OAuth2 security scheme for the BookWorm API
      flows:
        authorizationCode:
          authorizationUrl: "https://auth.bookworm.com/realms/bookworm/protocol/openid-connect/auth"
          tokenUrl: "https://auth.bookworm.com/realms/bookworm/protocol/openid-connect/token"
          scopes:
            basket: "Basket API"
          x-usePkce: "SHA-256"
          x-scalar-client-id: "basket"
          x-scalar-security-body:
            audience: "account"
tags:
  - name: Basket
    description: Manages shopping baskets for customers, allowing them to add, update, and remove items before checkout
