openapi: 3.0.3
info:
  title: PUP - Challenge API v1
  description: >
    PUP is the universal player profile for padel. This API provides challenge management functionality.
  version: 1.0.0

servers:
  - url: https://api.gopup.app
    description: Development server

x-tagGroups:
  - name: Challenge
    tags:
      - challenges

tags:
  - name: challenges
    x-displayName: "Challenges"
    description: Operations related to challenge management

paths:
  /challenge/v1/new:
    post:
      tags:
        - challenges
      summary: Create a new challenge
      description: Creates a new challenge with the provided information
      operationId: createChallenge
      security:
        - OAuth2:
            - urn:pup:challenge:manage
        - PAT: []
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/CreateChallengeRequest'
      responses:
        '201':
          description: Challenge created successfully
          content:
            application/json:
              schema:
                type: object
                required:
                  - id
                properties:
                  id:
                    type: string
                    example: "550e8400-e29b-41d4-a716-446655440000"
        '400':
          description: Bad request
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
        '401':
          description: Unauthorized
        '403':
          description: Forbidden
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
        '422':
          description: Unprocessable entity
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
        default:
          description: Generic error
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Error"

  /challenge/v1/search:
    get:
      tags:
        - challenges
      summary: Search challenges
      description: Search for challenges with optional filters
      operationId: searchChallenges
      parameters:
        - in: query
          name: term
          example: Summer challenge
          schema:
            type: string
        - in: query
          name: club_id
          example: 550e8400-e29b-41d4-a716-446655440000
          description: Filter by club ID
          schema:
            type: string
        - in: query
          name: active_only
          example: true
          description: Filter to only active challenges
          schema:
            type: boolean
        - in: query
          name: offset
          example: 0
          description: Results offset (useful for pagination)
          schema:
            type: integer
            format: int32
            minimum: 0
            default: 0
        - in: query
          name: limit
          example: 20
          description: Results limit (useful for pagination)
          schema:
            type: integer
            format: int32
            minimum: 1
            maximum: 100
            default: 20
      security:
        - OAuth2:
            - urn:pup:challenge:read
        - OAuth2:
            - urn:pup:challenge:manage
        - PAT: []
      responses:
        '200':
          description: The search results
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/SearchChallengesResponse'
        '401':
          description: Unauthorized
        default:
          description: Generic error
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Error"

  /challenge/v1/challenge/{id}:
    get:
      tags:
        - challenges
      summary: Get challenge by ID
      description: Returns the details of a challenge
      operationId: getChallengeById
      parameters:
        - in: path
          name: id
          description: Challenge identifier
          example: 550e8400-e29b-41d4-a716-446655440000
          required: true
          schema:
            type: string
      security:
        - OAuth2:
            - urn:pup:challenge:read
        - OAuth2:
            - urn:pup:challenge:manage
        - PAT: []
      responses:
        '200':
          description: The requested challenge details
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ChallengeResponse'
        '404':
          description: Challenge not found
          content:
            application/json:
              schema:
                type: object
                required:
                  - error
                properties:
                  error:
                    type: string
                    example: "Challenge not found"
        '401':
          description: Unauthorized
        default:
          description: Generic error
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Error"

    patch:
      tags:
        - challenges
      summary: Update challenge
      description: Updates an existing challenge with the provided information
      operationId: updateChallenge
      parameters:
        - in: path
          name: id
          description: Challenge identifier
          example: 550e8400-e29b-41d4-a716-446655440000
          required: true
          schema:
            type: string
      security:
        - OAuth2:
            - urn:pup:challenge:manage
        - PAT: []
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/UpdateChallengeRequest'
      responses:
        '204':
          description: Challenge updated successfully
        '400':
          description: Bad request
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
        '404':
          description: Challenge not found
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
        '401':
          description: Unauthorized
        '403':
          description: Forbidden
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
        '422':
          description: Unprocessable entity
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
        default:
          description: Generic error
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Error"

    delete:
      tags:
        - challenges
      summary: Deactivate challenge
      description: Deactivates a challenge (soft delete)
      operationId: deactivateChallenge
      parameters:
        - in: path
          name: id
          description: Challenge identifier
          example: 550e8400-e29b-41d4-a716-446655440000
          required: true
          schema:
            type: string
      security:
        - OAuth2:
            - urn:pup:challenge:manage
        - PAT: []
      responses:
        '204':
          description: Challenge deactivated successfully
        '404':
          description: Challenge not found
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
        '401':
          description: Unauthorized
        '403':
          description: Forbidden
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
        default:
          description: Generic error
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Error"

components:
  securitySchemes:
    OAuth2:
      type: oauth2
      description: OAuth2 authentication
      flows:
        authorizationCode:
          authorizationUrl: https://oauth2.gopup.app/oauth2/auth
          tokenUrl: https://oauth2.gopup.app/oauth2/token
          scopes:
            urn:pup:challenge:read: Read challenges
            urn:pup:challenge:manage: Manage challenges

    PAT:
      type: http
      scheme: bearer
      bearerFormat: PAT
      description: Personal Access Token
  schemas:
    CreateChallengeRequest:
      type: object
      required:
        - club_id
        - title
        - reward
        - start_date
        - end_date
        - max_attempts
        - max_participants
      properties:
        club_id:
          type: string
          description: ID of the club creating the challenge
          example: "550e8400-e29b-41d4-a716-446655440000"
        title:
          type: string
          minLength: 1
          maxLength: 200
          description: Challenge title
          example: "Summer Tennis Challenge"
        description:
          type: string
          maxLength: 500
          description: Short description of the challenge
          example: "Complete 3 matches during summer"
        details:
          type: string
          maxLength: 5000
          description: Detailed description with rules
          example: "Play 3 tennis matches between June and August"
        reward:
          type: integer
          format: int32
          minimum: 0
          description: Reward amount in credits
          example: 100
        start_date:
          type: string
          format: date-time
          description: When the challenge starts
          example: "2025-06-01T00:00:00Z"
        end_date:
          type: string
          format: date-time
          description: When the challenge ends
          example: "2025-08-31T23:59:59Z"
        max_attempts:
          type: integer
          format: int32
          minimum: 1
          description: Maximum number of attempts allowed
          example: 3
        max_participants:
          type: integer
          format: int32
          minimum: 1
          description: Maximum number of participants who can earn rewards
          example: 10

    UpdateChallengeRequest:
      type: object
      properties:
        title:
          type: string
          minLength: 1
          maxLength: 200
          example: "Updated Challenge Title"
        description:
          type: string
          maxLength: 500
          example: "Updated description"
        details:
          type: string
          maxLength: 5000
          example: "Updated detailed rules"
        reward:
          type: integer
          format: int32
          minimum: 0
          example: 150
        start_date:
          type: string
          format: date-time
          example: "2025-06-01T00:00:00Z"
        end_date:
          type: string
          format: date-time
          example: "2025-08-31T23:59:59Z"
        max_attempts:
          type: integer
          format: int32
          minimum: 1
          example: 5

    ChallengeResponse:
      type: object
      required:
        - challenge
      properties:
        challenge:
          $ref: '#/components/schemas/Challenge'

    SearchChallengesResponse:
      type: object
      required:
        - hits
        - meta
      properties:
        hits:
          type: array
          items:
            $ref: '#/components/schemas/Challenge'
        meta:
          $ref: '#/components/schemas/ResponseMetaMany'

    Challenge:
      type: object
      required:
        - id
        - club_id
        - title
        - reward
        - start_date
        - end_date
        - max_attempts
        - max_participants
        - active
      properties:
        id:
          type: string
          example: "550e8400-e29b-41d4-a716-446655440000"
        club_id:
          type: string
          example: "660e8400-e29b-41d4-a716-446655440000"
        title:
          type: string
          example: "Summer Tennis Challenge"
        description:
          type: string
          nullable: true
          example: "Complete 3 matches during summer"
        details:
          type: string
          nullable: true
          example: "Play 3 tennis matches between June and August"
        reward:
          type: integer
          format: int32
          description: Reward in credits
          example: 100
        start_date:
          type: string
          format: date-time
          example: "2025-06-01T00:00:00Z"
        end_date:
          type: string
          format: date-time
          example: "2025-08-31T23:59:59Z"
        max_attempts:
          type: integer
          format: int32
          example: 3
        max_participants:
          type: integer
          format: int32
          description: Maximum number of participants who can earn rewards
          example: 10
        active:
          type: boolean
          example: true

    ResponseMetaMany:
      type: object
      required:
        - pagination
      properties:
        pagination:
          $ref: '#/components/schemas/Pagination'

    Pagination:
      type: object
      required:
        - total
        - returned
        - offset
        - limit
      properties:
        total:
          type: integer
          format: int64
          description: Total number of results
          example: 145
        returned:
          type: integer
          format: int32
          description: Number of results in this response
          example: 20
        offset:
          type: integer
          format: int32
          description: Number of results skipped
          example: 0
        limit:
          type: integer
          format: int32
          description: Maximum results per page
          example: 20
        next:
          type: string
          nullable: true
          description: URL for next page
          example: "/challenge/v1/search?offset=20&limit=20"
        previous:
          type: string
          nullable: true
          description: URL for previous page
          example: null

    Error:
      type: object
      required:
        - error
      properties:
        error:
          type: string
          description: Error message
          example: "An error occurred"
