openapi: 3.0.3
info:
  title: Flower Stateflow API
  version: 1.0.0
  description: >
    REST API for managing Stateflow states, processes, and business objects.
servers:
  - url: http://localhost:8000/api/v1
security:
  - BearerAuth: []
tags:
  - name: States
  - name: Processes
  - name: BusinessObjects

paths:
  /stateflow/states/:
    get:
      tags: [States]
      summary: List states
      parameters:
        - $ref: '#/components/parameters/Limit'
        - $ref: '#/components/parameters/Offset'
        - name: name
          in: query
          schema:
            type: string
          description: Filter by exact name
        - name: search
          in: query
          schema:
            type: string
          description: Full-text search across name and description
        - name: ordering
          in: query
          schema:
            type: string
            enum: [id, -id, name, -name, created_at, -created_at, updated_at, -updated_at]
          description: Order results by a field (prefix with "-" for descending)
      responses:
        '200':
          description: Paginated state list
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/PaginatedStateList'
    post:
      tags: [States]
      summary: Create state
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/StateCreateRequest'
      responses:
        '201':
          description: Created state
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/StateDetail'
  /stateflow/states/{id}/:
    parameters:
      - $ref: '#/components/parameters/StateId'
    get:
      tags: [States]
      summary: Retrieve state
      responses:
        '200':
          description: State detail
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/StateDetail'
    put:
      tags: [States]
      summary: Update state
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/StateCreateRequest'
      responses:
        '200':
          description: Updated state
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/StateDetail'
    patch:
      tags: [States]
      summary: Partially update state
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/StatePartialRequest'
      responses:
        '200':
          description: Updated state
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/StateDetail'
    delete:
      tags: [States]
      summary: Delete state
      responses:
        '204':
          description: Deleted

  /stateflow/processes/:
    get:
      tags: [Processes]
      summary: List processes
      parameters:
        - $ref: '#/components/parameters/Limit'
        - $ref: '#/components/parameters/Offset'
        - name: name
          in: query
          schema:
            type: string
          description: Filter by exact name
        - name: search
          in: query
          schema:
            type: string
          description: Full-text search across name and description
        - name: ordering
          in: query
          schema:
            type: string
            enum: [id, -id, name, -name, node_count, -node_count, created_at, -created_at, updated_at, -updated_at]
          description: Order results by a field (prefix with "-" for descending)
      responses:
        '200':
          description: Paginated process list
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/PaginatedProcessList'
    post:
      tags: [Processes]
      summary: Create process
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/ProcessCreateRequest'
      responses:
        '201':
          description: Created process
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ProcessDetail'
  /stateflow/processes/{id}/:
    parameters:
      - $ref: '#/components/parameters/ProcessId'
    get:
      tags: [Processes]
      summary: Retrieve process
      responses:
        '200':
          description: Process detail
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ProcessDetail'
    put:
      tags: [Processes]
      summary: Update process
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/ProcessCreateRequest'
      responses:
        '200':
          description: Updated process
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ProcessDetail'
    patch:
      tags: [Processes]
      summary: Partially update process
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/ProcessPartialRequest'
      responses:
        '200':
          description: Updated process
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ProcessDetail'
    delete:
      tags: [Processes]
      summary: Delete process
      responses:
        '204':
          description: Deleted

  /stateflow/business-objects/:
    get:
      tags: [BusinessObjects]
      summary: List business objects
      parameters:
        - $ref: '#/components/parameters/Limit'
        - $ref: '#/components/parameters/Offset'
        - name: name
          in: query
          schema:
            type: string
          description: Filter by name (case-insensitive, contains)
        - name: process
          in: query
          schema:
            type: integer
          description: Filter by process ID
        - name: process_name
          in: query
          schema:
            type: string
          description: Filter by process name (case-insensitive, contains)
        - name: overall_status
          in: query
          schema:
            type: string
            enum: [not_started, in_progress, completed]
          description: Filter by overall status
        - name: content_type_str
          in: query
          schema:
            type: string
          description: Filter by related object type (app_label.model)
        - name: has_content_object
          in: query
          schema:
            type: boolean
          description: true for only records linked to actual objects; false for unlinked
        - name: search
          in: query
          schema:
            type: string
          description: Full-text search across name and description
        - name: ordering
          in: query
          schema:
            type: string
            enum: [id, -id, name, -name, created_at, -created_at, updated_at, -updated_at]
          description: Order results by a field (prefix with "-" for descending)
      responses:
        '200':
          description: Paginated business object list
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/PaginatedBusinessObjectList'
    post:
      tags: [BusinessObjects]
      summary: Create business object
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/BusinessObjectCreateRequest'
      responses:
        '201':
          description: Created business object
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/BusinessObjectDetail'
  /stateflow/business-objects/{id}/:
    parameters:
      - $ref: '#/components/parameters/BusinessObjectId'
    get:
      tags: [BusinessObjects]
      summary: Retrieve business object
      responses:
        '200':
          description: Business object detail
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/BusinessObjectDetail'
    put:
      tags: [BusinessObjects]
      summary: Update business object
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/BusinessObjectCreateRequest'
      responses:
        '200':
          description: Updated business object
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/BusinessObjectDetail'
    patch:
      tags: [BusinessObjects]
      summary: Partially update business object
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/BusinessObjectPartialRequest'
      responses:
        '200':
          description: Updated business object
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/BusinessObjectDetail'
    delete:
      tags: [BusinessObjects]
      summary: Delete business object
      responses:
        '204':
          description: Deleted
  /stateflow/business-objects/{id}/advance/:
    parameters:
      - $ref: '#/components/parameters/BusinessObjectId'
    post:
      tags: [BusinessObjects]
      summary: Advance business object to next state
      responses:
        '200':
          description: Advanced successfully
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/BusinessObjectAdvanceResponse'
        '400':
          description: Cannot advance
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/BusinessObjectAdvanceResponse'
  /stateflow/business-objects/{id}/reset/:
    parameters:
      - $ref: '#/components/parameters/BusinessObjectId'
    post:
      tags: [BusinessObjects]
      summary: Reset progress (mark records as cancelled)
      responses:
        '200':
          description: Reset successful
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/BusinessObjectResetResponse'
  /stateflow/business-objects/{id}/timeline/:
    parameters:
      - $ref: '#/components/parameters/BusinessObjectId'
    get:
      tags: [BusinessObjects]
      summary: Get state timeline
      responses:
        '200':
          description: Timeline data
          content:
            application/json:
              schema:
                type: array
                items:
                  $ref: '#/components/schemas/StateTimelineItem'

components:
  securitySchemes:
    BearerAuth:
      type: http
      scheme: bearer
      bearerFormat: JWT

  parameters:
    Limit:
      name: limit
      in: query
      schema:
        type: integer
        minimum: 0
      description: Number of results to return per page (default configured on server)
    Offset:
      name: offset
      in: query
      schema:
        type: integer
        minimum: 0
      description: Offset into the result set for pagination
    StateId:
      name: id
      in: path
      required: true
      schema:
        type: integer
      description: State ID
    ProcessId:
      name: id
      in: path
      required: true
      schema:
        type: integer
      description: Process ID
    BusinessObjectId:
      name: id
      in: path
      required: true
      schema:
        type: integer
      description: Business object ID

  schemas:
    DateTime:
      type: string
      format: date-time

    StateParameter:
      type: object
      properties:
        id:
          type: integer
        key:
          type: string
        value:
          type: string
        description:
          type: string
          nullable: true
      required: [id, key, value]

    StateListItem:
      type: object
      properties:
        id:
          type: integer
        name:
          type: string
        description:
          type: string
          nullable: true
        created_at:
          $ref: '#/components/schemas/DateTime'
        updated_at:
          $ref: '#/components/schemas/DateTime'
      required: [id, name, created_at, updated_at]

    StateDetail:
      allOf:
        - $ref: '#/components/schemas/StateListItem'
        - type: object
          properties:
            parameters:
              type: array
              items:
                $ref: '#/components/schemas/StateParameter'

    StateCreateRequest:
      type: object
      properties:
        name:
          type: string
        description:
          type: string
          nullable: true
        parameters:
          type: array
          items:
            type: object
            properties:
              key:
                type: string
              value:
                type: string
              description:
                type: string
                nullable: true
            required: [key, value]
      required: [name]

    StatePartialRequest:
      type: object
      properties:
        name:
          type: string
        description:
          type: string
          nullable: true
        parameters:
          type: array
          nullable: true
          items:
            type: object
            properties:
              key:
                type: string
              value:
                type: string
              description:
                type: string
                nullable: true
            required: [key, value]

    ProcessNode:
      type: object
      properties:
        id:
          type: integer
        state_id:
          type: integer
        state_name:
          type: string
        order:
          type: integer
      required: [id, state_id, state_name, order]

    ProcessListItem:
      type: object
      properties:
        id:
          type: integer
        name:
          type: string
        description:
          type: string
          nullable: true
        node_count:
          type: integer
        created_at:
          $ref: '#/components/schemas/DateTime'
        updated_at:
          $ref: '#/components/schemas/DateTime'
      required: [id, name, node_count, created_at, updated_at]

    ProcessDetail:
      allOf:
        - $ref: '#/components/schemas/ProcessListItem'
        - type: object
          properties:
            nodes:
              type: array
              items:
                $ref: '#/components/schemas/ProcessNode'

    ProcessCreateRequest:
      type: object
      properties:
        name:
          type: string
        description:
          type: string
          nullable: true
        nodes:
          type: array
          items:
            type: object
            properties:
              state_id:
                type: integer
              order:
                type: integer
            required: [state_id, order]
      required: [name]

    ProcessPartialRequest:
      type: object
      properties:
        name:
          type: string
        description:
          type: string
          nullable: true
        nodes:
          type: array
          nullable: true
          items:
            type: object
            properties:
              state_id:
                type: integer
              order:
                type: integer
            required: [state_id, order]

    StateFlowRecord:
      type: object
      properties:
        id:
          type: integer
        state:
          type: integer
        state_name:
          type: string
        completed_at:
          $ref: '#/components/schemas/DateTime'
          nullable: true
        completed_by:
          type: integer
          nullable: true
        completed_by_username:
          type: string
          nullable: true
        is_cancelled:
          type: boolean
        cancelled_at:
          $ref: '#/components/schemas/DateTime'
          nullable: true
      required: [id, state, state_name, is_cancelled]

    StateTimelineItem:
      type: object
      properties:
        state:
          $ref: '#/components/schemas/StateListItem'
        status:
          type: string
          enum: [not_started, in_progress, completed, cancelled]
        order:
          type: integer
        completed_at:
          $ref: '#/components/schemas/DateTime'
          nullable: true
        completed_by:
          type: string
          nullable: true
        cancelled_at:
          $ref: '#/components/schemas/DateTime'
          nullable: true
        is_cancelled:
          type: boolean
      required: [state, status, order, is_cancelled]

    BusinessObjectListItem:
      type: object
      properties:
        id:
          type: integer
        name:
          type: string
        process:
          type: integer
        process_name:
          type: string
        current_state_name:
          type: string
          nullable: true
        overall_status:
          type: string
          enum: [not_started, in_progress, completed]
        progress_percentage:
          type: number
          format: float
        content_type:
          type: integer
          nullable: true
        object_id:
          type: integer
          nullable: true
        content_type_name:
          type: string
          nullable: true
        description:
          type: string
          nullable: true
        created_at:
          $ref: '#/components/schemas/DateTime'
        updated_at:
          $ref: '#/components/schemas/DateTime'
      required: [id, name, process, process_name, overall_status, progress_percentage, created_at, updated_at]

    BusinessObjectDetail:
      allOf:
        - $ref: '#/components/schemas/BusinessObjectListItem'
        - type: object
          properties:
            process_detail:
              $ref: '#/components/schemas/ProcessDetail'
            current_state:
              $ref: '#/components/schemas/StateDetail'
              nullable: true
            timeline:
              type: array
              items:
                $ref: '#/components/schemas/StateTimelineItem'
            state_logs:
              type: array
              items:
                $ref: '#/components/schemas/StateFlowRecord'

    BusinessObjectCreateRequest:
      type: object
      properties:
        name:
          type: string
        process:
          type: integer
        description:
          type: string
          nullable: true
        content_type:
          type: integer
          nullable: true
        object_id:
          type: integer
          nullable: true
        content_type_str:
          type: string
          nullable: true
          description: Alternative to content_type; format app_label.model
      required: [name, process]

    BusinessObjectPartialRequest:
      type: object
      properties:
        name:
          type: string
        process:
          type: integer
        description:
          type: string
          nullable: true
        content_type:
          type: integer
          nullable: true
        object_id:
          type: integer
          nullable: true
        content_type_str:
          type: string
          nullable: true

    BusinessObjectAdvanceResponse:
      type: object
      properties:
        success:
          type: boolean
        message:
          type: string
        business_object:
          $ref: '#/components/schemas/BusinessObjectDetail'
          nullable: true
      required: [success, message]

    BusinessObjectResetResponse:
      type: object
      properties:
        success:
          type: boolean
        message:
          type: string
        business_object:
          $ref: '#/components/schemas/BusinessObjectDetail'
      required: [success, message, business_object]

    PaginatedStateList:
      type: object
      properties:
        count:
          type: integer
        next:
          type: string
          nullable: true
        previous:
          type: string
          nullable: true
        results:
          type: array
          items:
            $ref: '#/components/schemas/StateListItem'
      required: [count, results]

    PaginatedProcessList:
      type: object
      properties:
        count:
          type: integer
        next:
          type: string
          nullable: true
        previous:
          type: string
          nullable: true
        results:
          type: array
          items:
            $ref: '#/components/schemas/ProcessListItem'
      required: [count, results]

    PaginatedBusinessObjectList:
      type: object
      properties:
        count:
          type: integer
        next:
          type: string
          nullable: true
        previous:
          type: string
          nullable: true
        results:
          type: array
          items:
            $ref: '#/components/schemas/BusinessObjectListItem'
      required: [count, results]