openapi: 3.0.3
info:
  title: Unify Admin API
  description: |
    Comprehensive admin API for managing the Unify fintech platform's configurable services system.
    
    ## Features
    - **Service Provider Management** - Add, configure, and monitor VTU/Bills providers
    - **Service Plan Management** - Manage data plans, pricing, and availability
    - **System Configuration** - Control system-wide settings and parameters
    - **Health Monitoring** - Real-time provider health checks and statistics
    - **Security** - Role-based access control and encrypted sensitive data
    
    ## Authentication
    All admin endpoints require:
    1. **JWT Authentication** - Valid JWT token in Authorization header
    2. **Admin Role** - User must have 'admin' role
    
    ## Base URL
    ```
    https://your-domain.com/api/v1/admin
    ```
  version: 1.0.0
  contact:
    name: Unify API Support
    email: admin@unify.com
  license:
    name: MIT
    url: https://opensource.org/licenses/MIT

servers:
  - url: http://localhost:3000/api/v1/admin
    description: Development server
  - url: https://api.unify.com/v1/admin
    description: Production server

security:
  - BearerAuth: []

paths:
  # Service Provider Endpoints
  /services/providers:
    get:
      tags:
        - Service Providers
      summary: Get all service providers
      description: Retrieve all service providers with optional filtering and pagination
      parameters:
        - name: serviceType
          in: query
          description: Filter by service type
          schema:
            type: string
            enum: [vtu, bills, verification, payment]
        - name: status
          in: query
          description: Filter by provider status
          schema:
            type: string
            enum: [active, inactive, maintenance]
        - name: isHealthy
          in: query
          description: Filter by health status
          schema:
            type: boolean
        - name: sandboxMode
          in: query
          description: Filter by sandbox mode
          schema:
            type: boolean
        - name: search
          in: query
          description: Search providers by name, slug, or supported services
          schema:
            type: string
        - name: page
          in: query
          description: Page number for pagination
          schema:
            type: integer
            minimum: 1
            default: 1
        - name: limit
          in: query
          description: Number of items per page
          schema:
            type: integer
            minimum: 1
            maximum: 100
            default: 20
      responses:
        '200':
          description: Successfully retrieved service providers
          content:
            application/json:
              schema:
                type: object
                properties:
                  success:
                    type: boolean
                    example: true
                  data:
                    type: object
                    properties:
                      providers:
                        type: array
                        items:
                          $ref: '#/components/schemas/ServiceProvider'
                      pagination:
                        $ref: '#/components/schemas/Pagination'
                      stats:
                        $ref: '#/components/schemas/ProviderStats'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '403':
          $ref: '#/components/responses/Forbidden'
        '500':
          $ref: '#/components/responses/InternalServerError'

    post:
      tags:
        - Service Providers
      summary: Create a new service provider
      description: Add a new service provider to the system
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/CreateServiceProviderRequest'
            examples:
              asbdata:
                summary: ASB Data Provider
                value:
                  name: "ASB Data"
                  slug: "asbdata"
                  displayName: "ASB Data"
                  serviceType: "vtu"
                  baseUrl: "https://asbdata.com/api"
                  apiKey: "your-asbdata-api-key"
                  secretKey: "your-asbdata-secret-key"
                  priority: 1
                  defaultMarkup: 2.5
                  supportedServices: ["airtime", "data", "electricity", "cable"]
                  supportedNetworks: ["mtn", "airtel", "glo", "9mobile"]
              bilalsada:
                summary: Bilal Sada Sub Provider
                value:
                  name: "Bilal Sada Sub"
                  slug: "bilal-sada-sub"
                  displayName: "Bilal Sada Sub"
                  serviceType: "vtu"
                  baseUrl: "https://bilalsadasub.com/api"
                  apiKey: "your-bilalsada-api-key"
                  priority: 2
                  defaultMarkup: 3.0
                  supportedServices: ["airtime", "data"]
                  supportedNetworks: ["mtn", "airtel", "glo", "9mobile"]
      responses:
        '201':
          description: Service provider created successfully
          content:
            application/json:
              schema:
                type: object
                properties:
                  success:
                    type: boolean
                    example: true
                  message:
                    type: string
                    example: "Service provider created successfully"
                  data:
                    $ref: '#/components/schemas/ServiceProvider'
        '400':
          $ref: '#/components/responses/BadRequest'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '403':
          $ref: '#/components/responses/Forbidden'
        '409':
          description: Provider with slug already exists
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '500':
          $ref: '#/components/responses/InternalServerError'

  /services/providers/{id}:
    get:
      tags:
        - Service Providers
      summary: Get service provider by ID
      description: Retrieve a specific service provider by its ID
      parameters:
        - name: id
          in: path
          required: true
          description: Service provider ID
          schema:
            type: string
            pattern: '^[0-9a-fA-F]{24}$'
      responses:
        '200':
          description: Service provider retrieved successfully
          content:
            application/json:
              schema:
                type: object
                properties:
                  success:
                    type: boolean
                    example: true
                  data:
                    $ref: '#/components/schemas/ServiceProvider'
        '404':
          $ref: '#/components/responses/NotFound'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '403':
          $ref: '#/components/responses/Forbidden'

    put:
      tags:
        - Service Providers
      summary: Update service provider
      description: Update an existing service provider
      parameters:
        - name: id
          in: path
          required: true
          description: Service provider ID
          schema:
            type: string
            pattern: '^[0-9a-fA-F]{24}$'
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/UpdateServiceProviderRequest'
      responses:
        '200':
          description: Service provider updated successfully
          content:
            application/json:
              schema:
                type: object
                properties:
                  success:
                    type: boolean
                    example: true
                  message:
                    type: string
                    example: "Service provider updated successfully"
                  data:
                    $ref: '#/components/schemas/ServiceProvider'
        '400':
          $ref: '#/components/responses/BadRequest'
        '404':
          $ref: '#/components/responses/NotFound'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '403':
          $ref: '#/components/responses/Forbidden'

    delete:
      tags:
        - Service Providers
      summary: Delete service provider
      description: Soft delete a service provider (sets isDeleted flag)
      parameters:
        - name: id
          in: path
          required: true
          description: Service provider ID
          schema:
            type: string
            pattern: '^[0-9a-fA-F]{24}$'
      responses:
        '200':
          description: Service provider deleted successfully
          content:
            application/json:
              schema:
                type: object
                properties:
                  success:
                    type: boolean
                    example: true
                  message:
                    type: string
                    example: "Service provider deleted successfully"
        '404':
          $ref: '#/components/responses/NotFound'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '403':
          $ref: '#/components/responses/Forbidden'

  /services/providers/{id}/health-check:
    post:
      tags:
        - Service Providers
      summary: Test provider health
      description: Perform a health check on a specific service provider
      parameters:
        - name: id
          in: path
          required: true
          description: Service provider ID
          schema:
            type: string
            pattern: '^[0-9a-fA-F]{24}$'
      responses:
        '200':
          description: Health check completed
          content:
            application/json:
              schema:
                type: object
                properties:
                  success:
                    type: boolean
                    example: true
                  data:
                    type: object
                    properties:
                      isHealthy:
                        type: boolean
                        example: true
                      responseTime:
                        type: number
                        example: 245.5
                      lastCheck:
                        type: string
                        format: date-time
                      message:
                        type: string
                        example: "Health check successful"
        '404':
          $ref: '#/components/responses/NotFound'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '403':
          $ref: '#/components/responses/Forbidden'

  /services/providers/{id}/toggle-status:
    patch:
      tags:
        - Service Providers
      summary: Toggle provider status
      description: Toggle provider status between active and inactive
      parameters:
        - name: id
          in: path
          required: true
          description: Service provider ID
          schema:
            type: string
            pattern: '^[0-9a-fA-F]{24}$'
      responses:
        '200':
          description: Provider status toggled successfully
          content:
            application/json:
              schema:
                type: object
                properties:
                  success:
                    type: boolean
                    example: true
                  message:
                    type: string
                    example: "Provider activated successfully"
                  data:
                    $ref: '#/components/schemas/ServiceProvider'

  /services/providers/service-type/{serviceType}:
    get:
      tags:
        - Service Providers
      summary: Get providers by service type
      description: Retrieve all providers for a specific service type
      parameters:
        - name: serviceType
          in: path
          required: true
          description: Service type
          schema:
            type: string
            enum: [vtu, bills, verification, payment]
      responses:
        '200':
          description: Providers retrieved successfully
          content:
            application/json:
              schema:
                type: object
                properties:
                  success:
                    type: boolean
                    example: true
                  data:
                    type: array
                    items:
                      $ref: '#/components/schemas/ServiceProvider'

  # Service Plan Endpoints
  /services/plans:
    get:
      tags:
        - Service Plans
      summary: Get all service plans
      description: Retrieve all service plans with optional filtering and pagination
      parameters:
        - name: type
          in: query
          description: Filter by plan type
          schema:
            type: string
            enum: [data, airtime, electricity, cable, education, exam-pin]
        - name: network
          in: query
          description: Filter by network (for VTU plans)
          schema:
            type: string
            enum: [mtn, airtel, glo, 9mobile]
        - name: status
          in: query
          description: Filter by plan status
          schema:
            type: string
            enum: [active, inactive, out-of-stock]
        - name: isVisible
          in: query
          description: Filter by visibility
          schema:
            type: boolean
        - name: providerId
          in: query
          description: Filter by provider ID
          schema:
            type: string
            pattern: '^[0-9a-fA-F]{24}$'
        - name: minPrice
          in: query
          description: Minimum price filter
          schema:
            type: number
        - name: maxPrice
          in: query
          description: Maximum price filter
          schema:
            type: number
        - name: category
          in: query
          description: Filter by category
          schema:
            type: string
        - name: search
          in: query
          description: Search plans by name, description, or metadata
          schema:
            type: string
        - name: page
          in: query
          description: Page number for pagination
          schema:
            type: integer
            minimum: 1
            default: 1
        - name: limit
          in: query
          description: Number of items per page
          schema:
            type: integer
            minimum: 1
            maximum: 100
            default: 20
      responses:
        '200':
          description: Successfully retrieved service plans
          content:
            application/json:
              schema:
                type: object
                properties:
                  success:
                    type: boolean
                    example: true
                  data:
                    type: object
                    properties:
                      plans:
                        type: array
                        items:
                          $ref: '#/components/schemas/ServicePlan'
                      pagination:
                        $ref: '#/components/schemas/Pagination'
                      stats:
                        $ref: '#/components/schemas/PlanStats'

    post:
      tags:
        - Service Plans
      summary: Create a new service plan
      description: Add a new service plan to the system
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/CreateServicePlanRequest'
            examples:
              mtn_data:
                summary: MTN Data Plan
                value:
                  providerId: "507f1f77bcf86cd799439011"
                  planId: "mtn-sme-1gb"
                  name: "MTN SME 1GB"
                  type: "data"
                  network: "mtn"
                  dataPlanType: "sme"
                  size: "1GB"
                  validity: "30 days"
                  amount: 250
                  sellingPrice: 260
                  status: "active"
                  isVisible: true
              electricity:
                summary: Electricity Plan
                value:
                  providerId: "507f1f77bcf86cd799439011"
                  planId: "kedco-prepaid"
                  name: "KEDCO Prepaid"
                  type: "electricity"
                  amount: 0
                  sellingPrice: 0
                  metadata:
                    discoId: "kedco"
                    discoName: "Kaduna Electric Distribution Company"
                    meterType: "prepaid"
      responses:
        '201':
          description: Service plan created successfully
          content:
            application/json:
              schema:
                type: object
                properties:
                  success:
                    type: boolean
                    example: true
                  message:
                    type: string
                    example: "Service plan created successfully"
                  data:
                    $ref: '#/components/schemas/ServicePlan'

  /services/plans/{id}:
    get:
      tags:
        - Service Plans
      summary: Get service plan by ID
      description: Retrieve a specific service plan by its ID
      parameters:
        - name: id
          in: path
          required: true
          description: Service plan ID
          schema:
            type: string
            pattern: '^[0-9a-fA-F]{24}$'
      responses:
        '200':
          description: Service plan retrieved successfully
          content:
            application/json:
              schema:
                type: object
                properties:
                  success:
                    type: boolean
                    example: true
                  data:
                    $ref: '#/components/schemas/ServicePlan'

    put:
      tags:
        - Service Plans
      summary: Update service plan
      description: Update an existing service plan
      parameters:
        - name: id
          in: path
          required: true
          description: Service plan ID
          schema:
            type: string
            pattern: '^[0-9a-fA-F]{24}$'
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/UpdateServicePlanRequest'
      responses:
        '200':
          description: Service plan updated successfully
          content:
            application/json:
              schema:
                type: object
                properties:
                  success:
                    type: boolean
                    example: true
                  message:
                    type: string
                    example: "Service plan updated successfully"
                  data:
                    $ref: '#/components/schemas/ServicePlan'

    delete:
      tags:
        - Service Plans
      summary: Delete service plan
      description: Soft delete a service plan
      parameters:
        - name: id
          in: path
          required: true
          description: Service plan ID
          schema:
            type: string
            pattern: '^[0-9a-fA-F]{24}$'
      responses:
        '200':
          description: Service plan deleted successfully
          content:
            application/json:
              schema:
                type: object
                properties:
                  success:
                    type: boolean
                    example: true
                  message:
                    type: string
                    example: "Service plan deleted successfully"

  /services/plans/bulk-update-prices:
    post:
      tags:
        - Service Plans
      summary: Bulk update plan prices
      description: Update prices for all plans of a provider with a markup percentage
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              required:
                - providerId
                - markupPercentage
              properties:
                providerId:
                  type: string
                  pattern: '^[0-9a-fA-F]{24}$'
                  description: Provider ID
                markupPercentage:
                  type: number
                  minimum: 0
                  maximum: 100
                  description: Markup percentage to apply
              example:
                providerId: "507f1f77bcf86cd799439011"
                markupPercentage: 5
      responses:
        '200':
          description: Prices updated successfully
          content:
            application/json:
              schema:
                type: object
                properties:
                  success:
                    type: boolean
                    example: true
                  message:
                    type: string
                    example: "Updated prices for 25 plans"
                  data:
                    type: object
                    properties:
                      modifiedCount:
                        type: integer
                        example: 25

  /services/plans/{id}/toggle-visibility:
    patch:
      tags:
        - Service Plans
      summary: Toggle plan visibility
      description: Toggle plan visibility (show/hide from users)
      parameters:
        - name: id
          in: path
          required: true
          description: Service plan ID
          schema:
            type: string
            pattern: '^[0-9a-fA-F]{24}$'
      responses:
        '200':
          description: Plan visibility toggled successfully
          content:
            application/json:
              schema:
                type: object
                properties:
                  success:
                    type: boolean
                    example: true
                  message:
                    type: string
                    example: "Plan shown successfully"
                  data:
                    $ref: '#/components/schemas/ServicePlan'

  /services/plans/{id}/toggle-status:
    patch:
      tags:
        - Service Plans
      summary: Toggle plan status
      description: Toggle plan status between active and inactive
      parameters:
        - name: id
          in: path
          required: true
          description: Service plan ID
          schema:
            type: string
            pattern: '^[0-9a-fA-F]{24}$'
      responses:
        '200':
          description: Plan status toggled successfully
          content:
            application/json:
              schema:
                type: object
                properties:
                  success:
                    type: boolean
                    example: true
                  message:
                    type: string
                    example: "Plan activated successfully"
                  data:
                    $ref: '#/components/schemas/ServicePlan'

  # Specialized Plan Endpoints
  /services/plans/type/{type}:
    get:
      tags:
        - Service Plans
      summary: Get plans by type
      description: Retrieve all plans of a specific type
      parameters:
        - name: type
          in: path
          required: true
          description: Plan type
          schema:
            type: string
            enum: [data, airtime, electricity, cable, education, exam-pin]
      responses:
        '200':
          description: Plans retrieved successfully
          content:
            application/json:
              schema:
                type: object
                properties:
                  success:
                    type: boolean
                    example: true
                  data:
                    type: array
                    items:
                      $ref: '#/components/schemas/ServicePlan'

  /services/plans/data/{network}:
    get:
      tags:
        - Service Plans
      summary: Get data plans by network
      description: Retrieve all data plans for a specific network
      parameters:
        - name: network
          in: path
          required: true
          description: Network name
          schema:
            type: string
            enum: [mtn, airtel, glo, 9mobile]
        - name: dataPlanType
          in: query
          description: Filter by data plan type
          schema:
            type: string
            enum: [sme, sme2, corporate, awoof, gifting]
      responses:
        '200':
          description: Data plans retrieved successfully
          content:
            application/json:
              schema:
                type: object
                properties:
                  success:
                    type: boolean
                    example: true
                  data:
                    type: array
                    items:
                      $ref: '#/components/schemas/ServicePlan'

  /services/plans/electricity:
    get:
      tags:
        - Service Plans
      summary: Get electricity plans
      description: Retrieve all electricity plans
      parameters:
        - name: discoName
          in: query
          description: Filter by distribution company name
          schema:
            type: string
      responses:
        '200':
          description: Electricity plans retrieved successfully
          content:
            application/json:
              schema:
                type: object
                properties:
                  success:
                    type: boolean
                    example: true
                  data:
                    type: array
                    items:
                      $ref: '#/components/schemas/ServicePlan'

  /services/plans/cable:
    get:
      tags:
        - Service Plans
      summary: Get cable plans
      description: Retrieve all cable TV plans
      parameters:
        - name: cableProvider
          in: query
          description: Filter by cable provider name
          schema:
            type: string
      responses:
        '200':
          description: Cable plans retrieved successfully
          content:
            application/json:
              schema:
                type: object
                properties:
                  success:
                    type: boolean
                    example: true
                  data:
                    type: array
                    items:
                      $ref: '#/components/schemas/ServicePlan'

components:
  securitySchemes:
    BearerAuth:
      type: http
      scheme: bearer
      bearerFormat: JWT
      description: JWT token obtained from login endpoint

  schemas:
    ServiceProvider:
      type: object
      properties:
        id:
          type: string
          example: "507f1f77bcf86cd799439011"
        name:
          type: string
          example: "ASB Data"
        slug:
          type: string
          example: "asbdata"
        displayName:
          type: string
          example: "ASB Data"
        serviceType:
          type: string
          enum: [vtu, bills, verification, payment]
          example: "vtu"
        status:
          type: string
          enum: [active, inactive, maintenance]
          example: "active"
        baseUrl:
          type: string
          format: uri
          example: "https://asbdata.com/api"
        apiKey:
          type: string
          description: "Encrypted API key"
          example: "enc:..."
        secretKey:
          type: string
          description: "Encrypted secret key"
          example: "enc:..."
        webhookUrl:
          type: string
          format: uri
          example: "https://webhook.asbdata.com"
        timeout:
          type: integer
          example: 30000
        retryAttempts:
          type: integer
          example: 3
        sandboxMode:
          type: boolean
          example: false
        priority:
          type: integer
          minimum: 1
          maximum: 100
          example: 1
        defaultMarkup:
          type: number
          example: 2.5
        supportedServices:
          type: array
          items:
            type: string
          example: ["airtime", "data", "electricity", "cable"]
        supportedNetworks:
          type: array
          items:
            type: string
          example: ["mtn", "airtel", "glo", "9mobile"]
        rateLimitPerMinute:
          type: integer
          example: 60
        rateLimitPerHour:
          type: integer
          example: 1000
        isHealthy:
          type: boolean
          example: true
        lastHealthCheck:
          type: string
          format: date-time
        errorCount:
          type: integer
          example: 0
        successRate:
          type: number
          example: 98.5
        createdAt:
          type: string
          format: date-time
        updatedAt:
          type: string
          format: date-time

    CreateServiceProviderRequest:
      type: object
      required:
        - name
        - slug
        - displayName
        - serviceType
        - baseUrl
        - apiKey
        - supportedServices
      properties:
        name:
          type: string
          minLength: 1
          maxLength: 100
          example: "ASB Data"
        slug:
          type: string
          pattern: '^[a-z0-9-]+$'
          minLength: 1
          maxLength: 50
          example: "asbdata"
        displayName:
          type: string
          minLength: 1
          maxLength: 100
          example: "ASB Data"
        serviceType:
          type: string
          enum: [vtu, bills, verification, payment]
          example: "vtu"
        baseUrl:
          type: string
          format: uri
          example: "https://asbdata.com/api"
        apiKey:
          type: string
          minLength: 1
          example: "your-api-key"
        secretKey:
          type: string
          example: "your-secret-key"
        webhookUrl:
          type: string
          format: uri
          example: "https://webhook.asbdata.com"
        timeout:
          type: integer
          minimum: 1000
          maximum: 120000
          default: 30000
        retryAttempts:
          type: integer
          minimum: 1
          maximum: 10
          default: 3
        sandboxMode:
          type: boolean
          default: false
        priority:
          type: integer
          minimum: 1
          maximum: 100
          default: 1
        defaultMarkup:
          type: number
          minimum: 0
          maximum: 100
          default: 0
        supportedServices:
          type: array
          minItems: 1
          items:
            type: string
          example: ["airtime", "data"]
        supportedNetworks:
          type: array
          items:
            type: string
          example: ["mtn", "airtel", "glo", "9mobile"]
        rateLimitPerMinute:
          type: integer
          minimum: 1
        rateLimitPerHour:
          type: integer
          minimum: 1
        minimumBalance:
          type: number
          minimum: 0

    UpdateServiceProviderRequest:
      type: object
      properties:
        name:
          type: string
          minLength: 1
          maxLength: 100
        displayName:
          type: string
          minLength: 1
          maxLength: 100
        status:
          type: string
          enum: [active, inactive, maintenance]
        baseUrl:
          type: string
          format: uri
        apiKey:
          type: string
          minLength: 1
        secretKey:
          type: string
        webhookUrl:
          type: string
          format: uri
        timeout:
          type: integer
          minimum: 1000
          maximum: 120000
        retryAttempts:
          type: integer
          minimum: 1
          maximum: 10
        sandboxMode:
          type: boolean
        priority:
          type: integer
          minimum: 1
          maximum: 100
        defaultMarkup:
          type: number
          minimum: 0
          maximum: 100
        supportedServices:
          type: array
          items:
            type: string
        supportedNetworks:
          type: array
          items:
            type: string
        rateLimitPerMinute:
          type: integer
          minimum: 1
        rateLimitPerHour:
          type: integer
          minimum: 1
        minimumBalance:
          type: number
          minimum: 0

    ServicePlan:
      type: object
      properties:
        id:
          type: string
          example: "507f1f77bcf86cd799439012"
        providerId:
          type: string
          example: "507f1f77bcf86cd799439011"
        planId:
          type: string
          example: "mtn-sme-1gb"
        vendorPlanId:
          type: string
          example: "mtn_1gb_sme"
        name:
          type: string
          example: "MTN SME 1GB"
        description:
          type: string
          example: "MTN SME data plan with 1GB capacity"
        type:
          type: string
          enum: [data, airtime, electricity, cable, education, exam-pin]
          example: "data"
        category:
          type: string
          example: "sme"
        network:
          type: string
          enum: [mtn, airtel, glo, 9mobile]
          example: "mtn"
        dataPlanType:
          type: string
          enum: [sme, sme2, corporate, awoof, gifting]
          example: "sme"
        size:
          type: string
          example: "1GB"
        validity:
          type: string
          example: "30 days"
        amount:
          type: number
          example: 250
        sellingPrice:
          type: number
          example: 260
        status:
          type: string
          enum: [active, inactive, out-of-stock]
          example: "active"
        isVisible:
          type: boolean
          example: true
        stockQuantity:
          type: integer
          example: 1000
        minPurchase:
          type: number
          example: 1
        maxPurchase:
          type: number
          example: 10
        dailyLimit:
          type: number
          example: 100
        metadata:
          type: object
          additionalProperties: true
          example:
            discoId: "kedco"
            discoName: "Kaduna Electric Distribution Company"
        totalSales:
          type: integer
          example: 150
        successRate:
          type: number
          example: 98.5
        lastSaleDate:
          type: string
          format: date-time
        createdAt:
          type: string
          format: date-time
        updatedAt:
          type: string
          format: date-time

    CreateServicePlanRequest:
      type: object
      required:
        - providerId
        - planId
        - name
        - type
        - amount
        - sellingPrice
      properties:
        providerId:
          type: string
          pattern: '^[0-9a-fA-F]{24}$'
        planId:
          type: string
          minLength: 1
          maxLength: 100
        vendorPlanId:
          type: string
        name:
          type: string
          minLength: 1
          maxLength: 200
        description:
          type: string
        type:
          type: string
          enum: [data, airtime, electricity, cable, education, exam-pin]
        category:
          type: string
        network:
          type: string
          enum: [mtn, airtel, glo, 9mobile]
        dataPlanType:
          type: string
          enum: [sme, sme2, corporate, awoof, gifting]
        size:
          type: string
        validity:
          type: string
        amount:
          type: number
          minimum: 0
        sellingPrice:
          type: number
          minimum: 0
        status:
          type: string
          enum: [active, inactive, out-of-stock]
          default: "active"
        isVisible:
          type: boolean
          default: true
        stockQuantity:
          type: integer
          minimum: 0
        minPurchase:
          type: number
          minimum: 0
        maxPurchase:
          type: number
          minimum: 0
        dailyLimit:
          type: number
          minimum: 0
        metadata:
          type: object
          additionalProperties: true

    UpdateServicePlanRequest:
      type: object
      properties:
        vendorPlanId:
          type: string
        name:
          type: string
          minLength: 1
          maxLength: 200
        description:
          type: string
        category:
          type: string
        size:
          type: string
        validity:
          type: string
        amount:
          type: number
          minimum: 0
        sellingPrice:
          type: number
          minimum: 0
        status:
          type: string
          enum: [active, inactive, out-of-stock]
        isVisible:
          type: boolean
        stockQuantity:
          type: integer
          minimum: 0
        minPurchase:
          type: number
          minimum: 0
        maxPurchase:
          type: number
          minimum: 0
        dailyLimit:
          type: number
          minimum: 0
        metadata:
          type: object
          additionalProperties: true

    Pagination:
      type: object
      properties:
        page:
          type: integer
          example: 1
        limit:
          type: integer
          example: 20
        total:
          type: integer
          example: 150
        pages:
          type: integer
          example: 8

    ProviderStats:
      type: object
      properties:
        total:
          type: integer
          example: 3
        active:
          type: integer
          example: 2
        inactive:
          type: integer
          example: 1
        healthy:
          type: integer
          example: 2
        byServiceType:
          type: object
          additionalProperties:
            type: integer
          example:
            vtu: 2
            bills: 1

    PlanStats:
      type: object
      properties:
        total:
          type: integer
          example: 150
        active:
          type: integer
          example: 145
        inactive:
          type: integer
          example: 5
        visible:
          type: integer
          example: 140
        byType:
          type: object
          additionalProperties:
            type: integer
          example:
            data: 80
            airtime: 4
            electricity: 40
            cable: 26
        byNetwork:
          type: object
          additionalProperties:
            type: integer
          example:
            mtn: 35
            airtel: 30
            glo: 15
        averagePrice:
          type: number
          example: 1250.50

    ErrorResponse:
      type: object
      properties:
        success:
          type: boolean
          example: false
        error:
          type: object
          properties:
            code:
              type: string
              example: "VALIDATION_ERROR"
            message:
              type: string
              example: "Validation failed"
            details:
              type: object
              additionalProperties: true
        requestId:
          type: string
          example: "req_1759392784715_g5xoo9iys"
        timestamp:
          type: string
          format: date-time

  responses:
    BadRequest:
      description: Bad request - validation error
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/ErrorResponse'
          example:
            success: false
            error:
              code: "VALIDATION_ERROR"
              message: "Validation failed"
              details:
                - path: ["name"]
                  message: "Name is required"

    Unauthorized:
      description: Unauthorized - missing or invalid token
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/ErrorResponse'
          example:
            success: false
            error:
              code: "AUTHENTICATION_ERROR"
              message: "Authentication failed"

    Forbidden:
      description: Forbidden - insufficient permissions
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/ErrorResponse'
          example:
            success: false
            error:
              code: "AUTHORIZATION_ERROR"
              message: "Access denied"

    NotFound:
      description: Resource not found
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/ErrorResponse'
          example:
            success: false
            error:
              code: "NOT_FOUND_ERROR"
              message: "Resource not found"

    InternalServerError:
      description: Internal server error
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/ErrorResponse'
          example:
            success: false
            error:
              code: "INTERNAL_SERVER_ERROR"
              message: "Internal server error"

tags:
  - name: Service Providers
    description: |
      Manage service providers for VTU, Bills, and other services.
      
      **Key Features:**
      - Add/remove providers (ASB Data, Bilal Sada Sub, etc.)
      - Configure API credentials and settings
      - Monitor provider health and performance
      - Set priority for automatic failover
      - Control markup and pricing
      
  - name: Service Plans
    description: |
      Manage service plans and pricing across all providers.
      
      **Key Features:**
      - Data plans (MTN, Airtel, Glo, 9mobile)
      - Electricity plans (KEDCO, EKO, etc.)
      - Cable TV plans (DSTV, GOTV, Startimes)
      - Dynamic pricing and markup control
      - Bulk operations and visibility control
