openapi: 3.1.0
info:
  title: El Captain Sports Management — Mobile API
  version: '1.0'
  description: |
    RESTful API for the El Captain mobile app (Flutter).
    Serves guardians/parents to track children's progress, pay invoices, receive notifications.

    ## Authentication
    All protected endpoints require a Bearer token obtained via OTP verification.
    Header: `Authorization: Bearer {token}`

    ## Money
    All monetary values are integers representing **piasters** (1 EGP = 100 piasters).
    Display-formatted values are provided alongside as `*_display` fields.

    ## Language
    Arabic is the primary language. All `name_ar` fields are required; `name` (English) is optional.

    ## Rate Limits
    - General: 60 requests/minute
    - Auth: 10 requests/minute
    - OTP: 3 requests/minute
    - Payments: 5 requests/minute
  contact:
    name: El Captain Dev Team
    email: dev@al-arcade.com

servers:
  - url: https://el-captain.caprover.al-arcade.com/api/v1
    description: Production
  - url: http://localhost:8000/api/v1
    description: Local development

tags:
  - name: Health
    description: System health and configuration
  - name: Auth
    description: OTP-based authentication
  - name: Academy
    description: Public academy content (no auth required)
  - name: Dashboard
    description: Single-call home screen
  - name: Profile
    description: User profile management
  - name: Participants
    description: Child data (schedule, attendance, invoices, enrollments)
  - name: Notifications
    description: In-app notifications and preferences
  - name: Shop
    description: Products and orders
  - name: Payments
    description: Online payment via Paymob
  - name: Events
    description: Academy events and registration
  - name: ServiceRequests
    description: Freeze/transfer/cancellation approval workflow
  - name: Push
    description: Push notification analytics and broadcast
  - name: Devices
    description: FCM device token management
  - name: Messages
    description: Guardian-academy messaging

security:
  - BearerAuth: []

components:
  securitySchemes:
    BearerAuth:
      type: http
      scheme: bearer
      bearerFormat: Sanctum Token

  schemas:
    Error:
      type: object
      properties:
        error:
          type: string
          description: Machine-readable error code
        message:
          type: string
          description: Human-readable Arabic message
      required: [error, message]

    ValidationError:
      type: object
      properties:
        message:
          type: string
        errors:
          type: object
          additionalProperties:
            type: array
            items:
              type: string

    PaginationMeta:
      type: object
      properties:
        current_page:
          type: integer
        last_page:
          type: integer
        per_page:
          type: integer
        total:
          type: integer

    User:
      type: object
      properties:
        id:
          type: integer
        name_ar:
          type: string
        name:
          type: string
          nullable: true
        email:
          type: string
          nullable: true
        phone:
          type: string
        academy_id:
          type: integer
        status:
          type: string
          enum: [active, inactive, suspended, pending]

    Participant:
      type: object
      properties:
        uuid:
          type: string
          format: uuid
        name_ar:
          type: string
        name:
          type: string
          nullable: true
        photo_url:
          type: string
          nullable: true
        status:
          type: string
          enum: [registered, active, frozen, suspended, inactive, graduated, transferred, withdrawn, blacklisted]
        gender:
          type: string
          enum: [male, female]
        date_of_birth:
          type: string
          format: date
          nullable: true
        active_enrollments:
          type: array
          items:
            $ref: '#/components/schemas/Enrollment'

    Session:
      type: object
      properties:
        id:
          type: integer
        session_date:
          type: string
          format: date
        start_time:
          type: string
        end_time:
          type: string
        status:
          type: string
          enum: [scheduled, in_progress, completed, cancelled, rescheduled]
        group_name:
          type: string
        program_name:
          type: string
          nullable: true
        facility_name:
          type: string
          nullable: true

    Attendance:
      type: object
      properties:
        id:
          type: integer
        date:
          type: string
          format: date
        status:
          type: string
          enum: [expected, present, late, excused, absent, no_show, left_early, partial, cancelled, exempt]
        check_in_time:
          type: string
          nullable: true
        late_minutes:
          type: integer
          nullable: true
        session:
          $ref: '#/components/schemas/Session'

    Invoice:
      type: object
      properties:
        uuid:
          type: string
          format: uuid
        number:
          type: string
        status:
          type: string
          enum: [draft, pending, sent, paid, partially_paid, overdue, cancelled, refunded]
        total_amount:
          type: integer
          description: Total in piasters
        due_amount:
          type: integer
          description: Remaining balance in piasters
        due_date:
          type: string
          format: date
          nullable: true
        items:
          type: array
          items:
            type: object
            properties:
              description:
                type: string
              quantity:
                type: integer
              unit_price:
                type: integer
              line_total:
                type: integer
        created_at:
          type: string
          format: date-time

    Enrollment:
      type: object
      properties:
        id:
          type: integer
        status:
          type: string
          enum: [pending, active, completed, cancelled, expired, waitlisted]
        enrolled_at:
          type: string
          format: date
        group:
          type: object
          properties:
            id:
              type: integer
            name_ar:
              type: string
            program:
              type: object
              properties:
                name_ar:
                  type: string
                activity:
                  type: object
                  properties:
                    name_ar:
                      type: string

    Notification:
      type: object
      properties:
        id:
          type: integer
        event_type:
          type: string
        title:
          type: string
        body:
          type: string
        is_read:
          type: boolean
        read_at:
          type: string
          format: date-time
          nullable: true
        sent_at:
          type: string
          format: date-time
          nullable: true
        created_at:
          type: string
          format: date-time
        metadata:
          type: object

    Announcement:
      type: object
      properties:
        uuid:
          type: string
          format: uuid
        title:
          type: string
        body:
          type: string
        target_type:
          type: string
          enum: [all, group, branch, program]
        status:
          type: string
          enum: [pending, scheduled, sending, sent, failed]
        sent_count:
          type: integer
        failed_count:
          type: integer
        scheduled_at:
          type: string
          format: date-time
          nullable: true
        sent_at:
          type: string
          format: date-time
          nullable: true
        created_at:
          type: string
          format: date-time

  responses:
    Unauthorized:
      description: Missing or invalid authentication token
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/Error'
          example:
            error: unauthenticated
            message: غير مصرح

    Forbidden:
      description: Authenticated but not authorized for this resource
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/Error'
          example:
            error: forbidden
            message: غير مصرح لك بالوصول لهذا المشترك

    NotFound:
      description: Resource not found
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/Error'

    ValidationFailed:
      description: Validation error
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/ValidationError'

    TooManyRequests:
      description: Rate limit exceeded
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/Error'
          example:
            error: too_many_attempts
            message: يرجى الانتظار قبل المحاولة مرة أخرى

paths:
  /health:
    get:
      tags: [Health]
      summary: Health check
      security: []
      responses:
        '200':
          description: API is healthy
          content:
            application/json:
              schema:
                type: object
                properties:
                  status:
                    type: string
                    example: ok
                  version:
                    type: string
                    example: '1.0'
                  timestamp:
                    type: string
                    format: date-time

  /app/config:
    get:
      tags: [Health]
      summary: App configuration (theme, features, maintenance)
      security: []
      responses:
        '200':
          description: Configuration for the mobile app
          content:
            application/json:
              schema:
                type: object
                properties:
                  academy:
                    type: object
                    properties:
                      name:
                        type: string
                      name_ar:
                        type: string
                      logo_url:
                        type: string
                        nullable: true
                      phone:
                        type: string
                      email:
                        type: string
                  theme:
                    type: object
                    properties:
                      primary_color:
                        type: string
                        example: '#1e40af'
                      accent_color:
                        type: string
                        example: '#f59e0b'
                  features:
                    type: object
                    properties:
                      shop:
                        type: boolean
                      events:
                        type: boolean
                      chat:
                        type: boolean
                      online_payment:
                        type: boolean
                  app:
                    type: object
                    properties:
                      min_version:
                        type: string
                        example: '1.0.0'
                      maintenance_mode:
                        type: boolean
                      maintenance_message:
                        type: string
        '404':
          $ref: '#/components/responses/NotFound'

  /branches:
    get:
      tags: [Academy]
      summary: List academy branches (for branch locator)
      security: []
      responses:
        '200':
          description: Active branches
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                        uuid:
                          type: string
                        name_ar:
                          type: string
                        name:
                          type: string
                          nullable: true
                        address:
                          type: string
                          nullable: true
                        phone:
                          type: string
                          nullable: true
                        latitude:
                          type: number
                          nullable: true
                        longitude:
                          type: number
                          nullable: true
                        operating_hours:
                          type: object
                          nullable: true

  /auth/otp/request:
    post:
      tags: [Auth]
      summary: Request OTP code via SMS
      security: []
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              required: [phone]
              properties:
                phone:
                  type: string
                  description: Egyptian phone number
                  example: '+201012345678'
      responses:
        '200':
          description: OTP sent successfully
          content:
            application/json:
              schema:
                type: object
                properties:
                  sent:
                    type: boolean
                  mode:
                    type: string
                    enum: [demo, sms]
                  expires_in:
                    type: integer
                    description: Seconds until OTP expires
                    example: 300
        '404':
          description: Phone not registered
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
              example:
                error: phone_not_found
                message: هذا الرقم غير مسجل في النظام
        '422':
          $ref: '#/components/responses/ValidationFailed'
        '429':
          $ref: '#/components/responses/TooManyRequests'

  /auth/otp/verify:
    post:
      tags: [Auth]
      summary: Verify OTP and get auth token
      security: []
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              required: [phone, otp]
              properties:
                phone:
                  type: string
                  example: '+201012345678'
                otp:
                  type: string
                  minLength: 6
                  maxLength: 6
                  example: '123456'
      responses:
        '200':
          description: Authentication successful
          content:
            application/json:
              schema:
                type: object
                properties:
                  token:
                    type: string
                    description: Bearer token for subsequent requests
                  user:
                    $ref: '#/components/schemas/User'
                  participants:
                    type: array
                    items:
                      $ref: '#/components/schemas/Participant'
        '401':
          description: Invalid OTP
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
              example:
                error: invalid_otp
                message: رمز التحقق غير صحيح
        '404':
          $ref: '#/components/responses/NotFound'

  /auth/logout:
    post:
      tags: [Auth]
      summary: Logout and revoke token
      responses:
        '200':
          description: Logged out
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                    example: تم تسجيل الخروج بنجاح

  /auth/me:
    get:
      tags: [Auth]
      summary: Get current user and linked participants
      responses:
        '200':
          description: Current user data
          content:
            application/json:
              schema:
                type: object
                properties:
                  user:
                    $ref: '#/components/schemas/User'
                  participants:
                    type: array
                    items:
                      $ref: '#/components/schemas/Participant'

  /academy/news:
    get:
      tags: [Academy]
      summary: Published news articles
      security: []
      responses:
        '200':
          description: Paginated news
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                        uuid:
                          type: string
                        title:
                          type: string
                        excerpt:
                          type: string
                          nullable: true
                        category:
                          type: string
                          nullable: true
                        image_url:
                          type: string
                          nullable: true
                        published_at:
                          type: string
                          format: date-time
                        is_featured:
                          type: boolean
                  meta:
                    $ref: '#/components/schemas/PaginationMeta'

  /academy/news/{uuid}:
    get:
      tags: [Academy]
      summary: Single news article
      security: []
      parameters:
        - name: uuid
          in: path
          required: true
          schema:
            type: string
      responses:
        '200':
          description: Full article
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      uuid:
                        type: string
                      title:
                        type: string
                      body:
                        type: string
                      category:
                        type: string
                      image_url:
                        type: string
                        nullable: true
                      published_at:
                        type: string
                        format: date-time
        '404':
          $ref: '#/components/responses/NotFound'

  /academy/programs:
    get:
      tags: [Academy]
      summary: Active training programs
      security: []
      responses:
        '200':
          description: Program list
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                        uuid:
                          type: string
                        name_ar:
                          type: string
                        name:
                          type: string
                          nullable: true
                        description_ar:
                          type: string
                          nullable: true
                        activity:
                          type: object
                          properties:
                            id:
                              type: integer
                            name_ar:
                              type: string
                            category:
                              type: string
                        age_min:
                          type: integer
                          nullable: true
                        age_max:
                          type: integer
                          nullable: true
                        gender:
                          type: string
                          nullable: true
                          enum: [male, female, null]

  /academy/events:
    get:
      tags: [Academy]
      summary: Upcoming published events
      security: []
      responses:
        '200':
          description: Paginated events
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                        uuid:
                          type: string
                        title:
                          type: string
                        description:
                          type: string
                          nullable: true
                        type:
                          type: string
                        starts_at:
                          type: string
                          format: date-time
                        ends_at:
                          type: string
                          format: date-time
                          nullable: true
                        location_name:
                          type: string
                          nullable: true
                        cover_url:
                          type: string
                          nullable: true
                        max_capacity:
                          type: integer
                          nullable: true
                        registrations_count:
                          type: integer
                        is_registration_open:
                          type: boolean
                        spots_remaining:
                          type: integer
                          nullable: true
                  meta:
                    $ref: '#/components/schemas/PaginationMeta'

  /academy/events/{uuid}:
    get:
      tags: [Academy]
      summary: Event detail
      security: []
      parameters:
        - name: uuid
          in: path
          required: true
          schema:
            type: string
      responses:
        '200':
          description: Full event detail
        '404':
          $ref: '#/components/responses/NotFound'

  /dashboard:
    get:
      tags: [Dashboard]
      summary: Single-call home screen data
      description: Returns all children summaries, today's sessions, totals, and announcements in one call.
      responses:
        '200':
          description: Dashboard data
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      children:
                        type: array
                        items:
                          type: object
                          properties:
                            uuid:
                              type: string
                            name_ar:
                              type: string
                            photo_url:
                              type: string
                              nullable: true
                            status:
                              type: string
                            outstanding_balance:
                              type: integer
                            outstanding_display:
                              type: string
                            next_session:
                              type: object
                              nullable: true
                              properties:
                                date:
                                  type: string
                                  format: date
                                start_time:
                                  type: string
                                group_name:
                                  type: string
                      totals:
                        type: object
                        properties:
                          outstanding_balance:
                            type: integer
                          outstanding_display:
                            type: string
                          children_count:
                            type: integer
                          today_sessions:
                            type: integer
                          unread_messages:
                            type: integer
                          unread_notifications:
                            type: integer
                          recent_evaluations:
                            type: integer
                      today_sessions:
                        type: array
                        items:
                          $ref: '#/components/schemas/Session'
                      announcement:
                        type: object
                        nullable: true
                        properties:
                          text:
                            type: string
                          link:
                            type: string
                            nullable: true
                          type:
                            type: string

  /profile:
    get:
      tags: [Profile]
      summary: Get user profile
      responses:
        '200':
          description: Profile data
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      name_ar:
                        type: string
                      name:
                        type: string
                        nullable: true
                      email:
                        type: string
                        nullable: true
                      phone:
                        type: string
                      phone_secondary:
                        type: string
                        nullable: true
                      address:
                        type: string
                        nullable: true
                      city:
                        type: string
                        nullable: true
                      emergency_contact_name:
                        type: string
                        nullable: true
                      emergency_contact_phone:
                        type: string
                        nullable: true
                      medical_notes:
                        type: string
                        nullable: true
                      photo_url:
                        type: string
                        nullable: true
    patch:
      tags: [Profile]
      summary: Update profile fields
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              properties:
                phone_secondary:
                  type: string
                address:
                  type: string
                city:
                  type: string
                emergency_contact_name:
                  type: string
                emergency_contact_phone:
                  type: string
                medical_notes:
                  type: string
      responses:
        '200':
          description: Updated
          content:
            application/json:
              schema:
                type: object
                properties:
                  success:
                    type: boolean
                  data:
                    type: object
        '422':
          $ref: '#/components/responses/ValidationFailed'

  /profile/photo:
    post:
      tags: [Profile]
      summary: Upload profile or participant photo
      requestBody:
        required: true
        content:
          multipart/form-data:
            schema:
              type: object
              required: [photo]
              properties:
                photo:
                  type: string
                  format: binary
                  description: JPEG or PNG, max 5MB
                type:
                  type: string
                  enum: [profile, participant]
                  default: profile
                participant_uuid:
                  type: string
                  description: Required when type=participant
      responses:
        '200':
          description: Photo uploaded
          content:
            application/json:
              schema:
                type: object
                properties:
                  success:
                    type: boolean
                  photo_url:
                    type: string
        '422':
          $ref: '#/components/responses/ValidationFailed'

  /devices/register:
    post:
      tags: [Devices]
      summary: Register FCM device token
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              required: [token, platform]
              properties:
                token:
                  type: string
                  description: FCM device token
                platform:
                  type: string
                  enum: [android, ios]
                device_name:
                  type: string
                app_version:
                  type: string
      responses:
        '200':
          description: Registered
          content:
            application/json:
              schema:
                type: object
                properties:
                  registered:
                    type: boolean

  /devices/refresh:
    patch:
      tags: [Devices]
      summary: Refresh expired FCM token
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              required: [old_token, new_token]
              properties:
                old_token:
                  type: string
                new_token:
                  type: string
      responses:
        '200':
          description: Refreshed
          content:
            application/json:
              schema:
                type: object
                properties:
                  refreshed:
                    type: boolean
        '404':
          $ref: '#/components/responses/NotFound'

  /devices/{token}:
    delete:
      tags: [Devices]
      summary: Unregister device token (on logout)
      parameters:
        - name: token
          in: path
          required: true
          schema:
            type: string
      responses:
        '200':
          description: Deleted
          content:
            application/json:
              schema:
                type: object
                properties:
                  deleted:
                    type: boolean

  /guardian/children:
    get:
      tags: [Participants]
      summary: List all linked participants (children)
      responses:
        '200':
          description: Participant list
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      $ref: '#/components/schemas/Participant'

  /participants/{uuid}:
    get:
      tags: [Participants]
      summary: Participant full profile
      parameters:
        - name: uuid
          in: path
          required: true
          schema:
            type: string
      responses:
        '200':
          description: Participant data
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    $ref: '#/components/schemas/Participant'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/NotFound'

  /participants/{uuid}/summary:
    get:
      tags: [Participants]
      summary: Quick stats summary
      parameters:
        - name: uuid
          in: path
          required: true
          schema:
            type: string
      responses:
        '200':
          description: Summary stats
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      participant_uuid:
                        type: string
                      name_ar:
                        type: string
                      photo_url:
                        type: string
                        nullable: true
                      status:
                        type: string
                      active_enrollments:
                        type: integer
                      attendance_rate:
                        type: number
                        format: float
                      outstanding_balance:
                        type: integer
                      next_session:
                        $ref: '#/components/schemas/Session'

  /participants/{uuid}/schedule:
    get:
      tags: [Participants]
      summary: Upcoming sessions (next 7 days)
      parameters:
        - name: uuid
          in: path
          required: true
          schema:
            type: string
      responses:
        '200':
          description: Session list
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      $ref: '#/components/schemas/Session'

  /participants/{uuid}/attendance:
    get:
      tags: [Participants]
      summary: Attendance history with rate
      parameters:
        - name: uuid
          in: path
          required: true
          schema:
            type: string
      responses:
        '200':
          description: Attendance records
          content:
            application/json:
              schema:
                type: object
                properties:
                  rate:
                    type: number
                    format: float
                    description: Attendance rate percentage
                  data:
                    type: array
                    items:
                      $ref: '#/components/schemas/Attendance'
                  meta:
                    $ref: '#/components/schemas/PaginationMeta'

  /participants/{uuid}/invoices:
    get:
      tags: [Participants]
      summary: Invoice history
      parameters:
        - name: uuid
          in: path
          required: true
          schema:
            type: string
      responses:
        '200':
          description: Paginated invoices
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      $ref: '#/components/schemas/Invoice'
                  meta:
                    $ref: '#/components/schemas/PaginationMeta'

  /participants/{uuid}/enrollments:
    get:
      tags: [Participants]
      summary: Active enrollments with group/program details
      parameters:
        - name: uuid
          in: path
          required: true
          schema:
            type: string
      responses:
        '200':
          description: Enrollment list
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      $ref: '#/components/schemas/Enrollment'

  /participants/{uuid}/documents:
    get:
      tags: [Participants]
      summary: Documents with expiry summary
      parameters:
        - name: uuid
          in: path
          required: true
          schema:
            type: string
      responses:
        '200':
          description: Documents
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                        title:
                          type: string
                        type:
                          type: string
                        file_url:
                          type: string
                        expires_at:
                          type: string
                          format: date
                          nullable: true
                        status:
                          type: string
                          enum: [valid, expiring_soon, expired]
                  expiry_summary:
                    type: object
                    properties:
                      expired:
                        type: integer
                      expiring_soon:
                        type: integer
                      valid:
                        type: integer

  /participants/{uuid}/wallet:
    get:
      tags: [Participants]
      summary: Wallet balance
      parameters:
        - name: uuid
          in: path
          required: true
          schema:
            type: string
      responses:
        '200':
          description: Wallet data
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      balance:
                        type: integer
                      available_balance:
                        type: integer
                      frozen_amount:
                        type: integer
                      status:
                        type: string
                      display:
                        type: string

  /participants/{uuid}/wallet/transactions:
    get:
      tags: [Participants]
      summary: Wallet transaction history
      parameters:
        - name: uuid
          in: path
          required: true
          schema:
            type: string
      responses:
        '200':
          description: Paginated transactions
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                        type:
                          type: string
                        amount:
                          type: integer
                        description:
                          type: string
                        created_at:
                          type: string
                          format: date-time
                  meta:
                    $ref: '#/components/schemas/PaginationMeta'

  /participants/{uuid}/installments:
    get:
      tags: [Participants]
      summary: Payment plans and installments
      parameters:
        - name: uuid
          in: path
          required: true
          schema:
            type: string
      responses:
        '200':
          description: Plans with installment breakdown
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        plan_id:
                          type: integer
                        total_amount:
                          type: integer
                        paid_amount:
                          type: integer
                        remaining:
                          type: integer
                        installments:
                          type: array
                          items:
                            type: object
                            properties:
                              id:
                                type: integer
                              amount:
                                type: integer
                              due_date:
                                type: string
                                format: date
                              status:
                                type: string
                              paid_at:
                                type: string
                                format: date-time
                                nullable: true

  /participants/{uuid}/evaluations:
    get:
      tags: [Participants]
      summary: Shared evaluations list
      parameters:
        - name: uuid
          in: path
          required: true
          schema:
            type: string
      responses:
        '200':
          description: Evaluation list
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                        uuid:
                          type: string
                        title:
                          type: string
                        type:
                          type: string
                        shared_at:
                          type: string
                          format: date-time
                        overall_score:
                          type: number

  /participants/{uuid}/evaluations/{evaluationUuid}:
    get:
      tags: [Participants]
      summary: Full evaluation with criteria scores
      parameters:
        - name: uuid
          in: path
          required: true
          schema:
            type: string
        - name: evaluationUuid
          in: path
          required: true
          schema:
            type: string
      responses:
        '200':
          description: Evaluation detail
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      uuid:
                        type: string
                      title:
                        type: string
                      type:
                        type: string
                      period:
                        type: string
                        nullable: true
                      shared_at:
                        type: string
                        format: date-time
                      overall_score:
                        type: number
                      criteria:
                        type: array
                        items:
                          type: object
                          properties:
                            name:
                              type: string
                            score:
                              type: number
                            max_score:
                              type: number
                            percentage:
                              type: number
                            notes:
                              type: string
                              nullable: true
                      notes:
                        type: string
                        nullable: true
                      recommendations:
                        type: string
                        nullable: true

  /notifications:
    get:
      tags: [Notifications]
      summary: Notification inbox
      responses:
        '200':
          description: Paginated notifications with unread count
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      $ref: '#/components/schemas/Notification'
                  unread_count:
                    type: integer
                  meta:
                    $ref: '#/components/schemas/PaginationMeta'

  /notifications/{id}/read:
    patch:
      tags: [Notifications]
      summary: Mark single notification as read
      parameters:
        - name: id
          in: path
          required: true
          schema:
            type: integer
      responses:
        '200':
          description: Marked
          content:
            application/json:
              schema:
                type: object
                properties:
                  success:
                    type: boolean

  /notifications/read-all:
    post:
      tags: [Notifications]
      summary: Mark all notifications as read
      responses:
        '200':
          description: All marked
          content:
            application/json:
              schema:
                type: object
                properties:
                  success:
                    type: boolean

  /notifications/preferences:
    get:
      tags: [Notifications]
      summary: Get notification channel preferences
      responses:
        '200':
          description: Preferences
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        event_type:
                          type: string
                        channel_email:
                          type: boolean
                        channel_sms:
                          type: boolean
                        channel_push:
                          type: boolean
                        digest_mode:
                          type: boolean
    post:
      tags: [Notifications]
      summary: Update notification preferences
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              required: [preferences]
              properties:
                preferences:
                  type: array
                  items:
                    type: object
                    required: [event_type]
                    properties:
                      event_type:
                        type: string
                      channel_push:
                        type: boolean
                      channel_email:
                        type: boolean
                      channel_sms:
                        type: boolean
      responses:
        '200':
          description: Updated
          content:
            application/json:
              schema:
                type: object
                properties:
                  success:
                    type: boolean

  /products:
    get:
      tags: [Shop]
      summary: Available products
      responses:
        '200':
          description: Product list
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                        uuid:
                          type: string
                        name_ar:
                          type: string
                        name:
                          type: string
                          nullable: true
                        description_ar:
                          type: string
                          nullable: true
                        price:
                          type: integer
                          description: Price in piasters
                        image_url:
                          type: string
                          nullable: true
                        in_stock:
                          type: boolean
                        category:
                          type: string
                          nullable: true

  /orders/create:
    post:
      tags: [Shop]
      summary: Purchase a product
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              required: [participant_uuid, product_id, payment_method]
              properties:
                participant_uuid:
                  type: string
                product_id:
                  type: integer
                quantity:
                  type: integer
                  default: 1
                payment_method:
                  type: string
                  enum: [wallet, online]
                notes:
                  type: string
      responses:
        '200':
          description: Order created
          content:
            application/json:
              schema:
                type: object
                properties:
                  success:
                    type: boolean
                  order:
                    type: object
                  payment_url:
                    type: string
                    nullable: true
                    description: Present when payment_method=online
        '422':
          $ref: '#/components/responses/ValidationFailed'

  /orders:
    get:
      tags: [Shop]
      summary: Order history
      responses:
        '200':
          description: Paginated orders
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                        uuid:
                          type: string
                        product:
                          type: object
                        quantity:
                          type: integer
                        total:
                          type: integer
                        status:
                          type: string
                        created_at:
                          type: string
                          format: date-time
                  meta:
                    $ref: '#/components/schemas/PaginationMeta'

  /payments/initiate:
    post:
      tags: [Payments]
      summary: Initiate online payment for invoice
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              required: [invoice_uuid]
              properties:
                invoice_uuid:
                  type: string
                  format: uuid
      responses:
        '200':
          description: Payment initiated
          content:
            application/json:
              schema:
                type: object
                properties:
                  success:
                    type: boolean
                  payment_url:
                    type: string
                    description: Paymob iframe URL
                  payment_uuid:
                    type: string
        '404':
          $ref: '#/components/responses/NotFound'
        '422':
          $ref: '#/components/responses/ValidationFailed'
        '503':
          description: Payment gateway not configured
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'

  /payments/callback:
    post:
      tags: [Payments]
      summary: Paymob webhook callback
      description: Server-to-server callback from Paymob. Do not call from mobile app.
      security: []
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
      responses:
        '200':
          description: Processed
          content:
            application/json:
              schema:
                type: object
                properties:
                  processed:
                    type: boolean

  /invoices/{uuid}:
    get:
      tags: [Payments]
      summary: Invoice detail with items and payments
      parameters:
        - name: uuid
          in: path
          required: true
          schema:
            type: string
      responses:
        '200':
          description: Full invoice
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    $ref: '#/components/schemas/Invoice'
        '404':
          $ref: '#/components/responses/NotFound'

  /payments/{uuid}/receipt:
    get:
      tags: [Payments]
      summary: Payment receipt
      parameters:
        - name: uuid
          in: path
          required: true
          schema:
            type: string
      responses:
        '200':
          description: Receipt data
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      payment_uuid:
                        type: string
                      amount:
                        type: integer
                      method:
                        type: string
                      reference:
                        type: string
                        nullable: true
                      paid_at:
                        type: string
                        format: date-time
                      invoice:
                        $ref: '#/components/schemas/Invoice'

  /events/{uuid}/register:
    post:
      tags: [Events]
      summary: Register for an event
      parameters:
        - name: uuid
          in: path
          required: true
          schema:
            type: string
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              required: [participant_uuid]
              properties:
                participant_uuid:
                  type: string
                notes:
                  type: string
      responses:
        '200':
          description: Registered
          content:
            application/json:
              schema:
                type: object
                properties:
                  success:
                    type: boolean
                  registration:
                    type: object
        '422':
          $ref: '#/components/responses/ValidationFailed'

  /events/my-registrations:
    get:
      tags: [Events]
      summary: My event registrations
      responses:
        '200':
          description: Registration list
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        event:
                          type: object
                        participant:
                          type: object
                        status:
                          type: string
                        registered_at:
                          type: string
                          format: date-time

  /service-requests:
    post:
      tags: [ServiceRequests]
      summary: Submit a service request (freeze, transfer, etc.)
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              required: [participant_uuid, type, reason]
              properties:
                participant_uuid:
                  type: string
                type:
                  type: string
                  enum: [freeze, unfreeze, transfer, cancellation, other]
                reason:
                  type: string
                  minLength: 10
                metadata:
                  type: object
                  description: Extra details (e.g. transfer destination)
      responses:
        '201':
          description: Request submitted
          content:
            application/json:
              schema:
                type: object
                properties:
                  success:
                    type: boolean
                  request:
                    type: object
                    properties:
                      uuid:
                        type: string
                      status:
                        type: string
                      type:
                        type: string
        '409':
          description: Duplicate pending request
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
        '422':
          $ref: '#/components/responses/ValidationFailed'
    get:
      tags: [ServiceRequests]
      summary: List my service requests
      responses:
        '200':
          description: Request list
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        uuid:
                          type: string
                        type:
                          type: string
                        status:
                          type: string
                          enum: [pending, approved, rejected, cancelled]
                        reason:
                          type: string
                        admin_notes:
                          type: string
                          nullable: true
                        created_at:
                          type: string
                          format: date-time
                        handled_at:
                          type: string
                          format: date-time
                          nullable: true

  /service-requests/{uuid}/cancel:
    post:
      tags: [ServiceRequests]
      summary: Cancel a pending service request
      parameters:
        - name: uuid
          in: path
          required: true
          schema:
            type: string
      responses:
        '200':
          description: Cancelled
          content:
            application/json:
              schema:
                type: object
                properties:
                  success:
                    type: boolean
        '422':
          description: Cannot cancel (not pending)
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'

  /absences/report:
    post:
      tags: [Participants]
      summary: Pre-report upcoming absence
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              required: [participant_uuid, session_id, reason]
              properties:
                participant_uuid:
                  type: string
                session_id:
                  type: integer
                reason:
                  type: string
      responses:
        '200':
          description: Reported
          content:
            application/json:
              schema:
                type: object
                properties:
                  success:
                    type: boolean
        '422':
          $ref: '#/components/responses/ValidationFailed'

  /messages/send:
    post:
      tags: [Messages]
      summary: Send message to academy
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              required: [subject, body]
              properties:
                subject:
                  type: string
                body:
                  type: string
                category:
                  type: string
      responses:
        '201':
          description: Sent
          content:
            application/json:
              schema:
                type: object
                properties:
                  success:
                    type: boolean
                  message:
                    type: object
                    properties:
                      id:
                        type: integer
        '422':
          $ref: '#/components/responses/ValidationFailed'

  /messages:
    get:
      tags: [Messages]
      summary: Message history
      responses:
        '200':
          description: Paginated messages
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                        subject:
                          type: string
                        body:
                          type: string
                        reply:
                          type: string
                          nullable: true
                        is_read:
                          type: boolean
                        created_at:
                          type: string
                          format: date-time
                  meta:
                    $ref: '#/components/schemas/PaginationMeta'

  /push/track:
    post:
      tags: [Push]
      summary: Track push notification delivery/interaction
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              required: [events]
              properties:
                events:
                  type: array
                  minItems: 1
                  maxItems: 50
                  items:
                    type: object
                    required: [event_type, action]
                    properties:
                      notification_id:
                        type: string
                      event_type:
                        type: string
                      action:
                        type: string
                        enum: [delivered, opened, dismissed, action_clicked]
                      metadata:
                        type: object
      responses:
        '200':
          description: Tracked
          content:
            application/json:
              schema:
                type: object
                properties:
                  tracked:
                    type: integer

  /push/badge:
    get:
      tags: [Push]
      summary: Get unread notification badge count
      responses:
        '200':
          description: Badge count
          content:
            application/json:
              schema:
                type: object
                properties:
                  badge_count:
                    type: integer

  /push/heartbeat:
    post:
      tags: [Push]
      summary: Report device activity (keeps token fresh)
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              required: [token]
              properties:
                token:
                  type: string
                  description: FCM device token
      responses:
        '200':
          description: OK
          content:
            application/json:
              schema:
                type: object
                properties:
                  ok:
                    type: boolean

  /broadcast/send:
    post:
      tags: [Push]
      summary: Send push announcement (admin only)
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              required: [title, body, target_type]
              properties:
                title:
                  type: string
                  maxLength: 200
                body:
                  type: string
                  maxLength: 1000
                target_type:
                  type: string
                  enum: [all, group, branch, program]
                target_ids:
                  type: array
                  items:
                    type: integer
                  description: Required unless target_type=all
                push_data:
                  type: object
                scheduled_at:
                  type: string
                  format: date-time
                  description: Schedule for future delivery
      responses:
        '200':
          description: Sent immediately
          content:
            application/json:
              schema:
                type: object
                properties:
                  success:
                    type: boolean
                  message:
                    type: string
                  announcement:
                    $ref: '#/components/schemas/Announcement'
        '201':
          description: Scheduled
          content:
            application/json:
              schema:
                type: object
                properties:
                  success:
                    type: boolean
                  message:
                    type: string
                  announcement:
                    $ref: '#/components/schemas/Announcement'
        '422':
          $ref: '#/components/responses/ValidationFailed'

  /broadcast/history:
    get:
      tags: [Push]
      summary: Broadcast announcement history
      responses:
        '200':
          description: Paginated announcements
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      $ref: '#/components/schemas/Announcement'
                  meta:
                    $ref: '#/components/schemas/PaginationMeta'

  /deeplinks/routes:
    get:
      tags: [Push]
      summary: Deep-link routing map for push notifications
      description: |
        Returns route templates used by the mobile app to navigate to the correct screen
        when a push notification is tapped. Template variables (e.g. `{participant_uuid}`)
        are replaced with values from the push payload `data` object.
      responses:
        '200':
          description: Route map
          content:
            application/json:
              schema:
                type: object
                properties:
                  routes:
                    type: object
                    additionalProperties:
                      type: string
                    example:
                      enrollment: /participants/{participant_uuid}/enrollments
                      invoice: /participants/{participant_uuid}/invoices/{invoice_uuid}
                      attendance: /participants/{participant_uuid}/attendance
                      session_cancelled: /participants/{participant_uuid}/schedule
                      service_request_resolved: /service-requests
                      announcement: /notifications
