openapi: 3.1.0
info:
  title: AI-DaaS API
  version: 0.1.0
  description: 统一数据查询、指标查询与视图查询接口规范。
servers:
  - url: http://localhost:8080
components:
  securitySchemes:
    bearerAuth:
      type: http
      scheme: bearer
  parameters:
    TenantId:
      name: X-Tenant-Id
      in: header
      required: true
      schema:
        type: string
      description: 目标租户标识
  schemas:
    SelectItem:
      type: object
      properties:
        field:
          type: string
        agg:
          type: string
          description: 聚合函数，如 SUM、COUNT、AVG
        alias:
          type: string
      required:
        - field
    FilterSimple:
      type: object
      properties:
        field:
          type: string
        op:
          type: string
          enum:
            - EQ
            - NE
            - GT
            - GTE
            - LT
            - LTE
            - IN
            - NOT_IN
            - LIKE
            - BETWEEN
            - IS_NULL
            - NOT_NULL
        value:
          description: 条件值；当 op 为 IS_NULL/NOT_NULL 时可省略
      required:
        - op
    FilterComposite:
      type: object
      properties:
        op:
          type: string
          enum:
            - AND
            - OR
        conditions:
          type: array
          items:
            $ref: '#/components/schemas/Filter'
      required:
        - op
        - conditions
    Filter:
      oneOf:
        - $ref: '#/components/schemas/FilterSimple'
        - $ref: '#/components/schemas/FilterComposite'
    TimeRangeAbsolute:
      type: object
      properties:
        from:
          type: string
          example: '2024-09-01'
        to:
          type: string
          example: '2024-09-30'
      required:
        - from
        - to
    TimeRangeRelative:
      type: object
      properties:
        last:
          type: string
          example: 7d
      required:
        - last
    TimeConfig:
      type: object
      properties:
        granularity:
          type: string
          enum:
            - HOUR
            - DAY
            - WEEK
            - MONTH
        range:
          oneOf:
            - $ref: '#/components/schemas/TimeRangeAbsolute'
            - $ref: '#/components/schemas/TimeRangeRelative'
    QueryRequest:
      type: object
      properties:
        entity:
          type: string
          description: 查询目标实体或视图名
        select:
          type: array
          items:
            $ref: '#/components/schemas/SelectItem'
        filter:
          $ref: '#/components/schemas/Filter'
        time:
          $ref: '#/components/schemas/TimeConfig'
        limit:
          type: integer
          default: 100
        offset:
          type: integer
          default: 0
      required:
        - entity
        - select
    MetricQueryParams:
      type: object
      properties:
        dimensions:
          type: array
          items:
            type: string
        filter:
          $ref: '#/components/schemas/Filter'
        time:
          $ref: '#/components/schemas/TimeConfig'
        limit:
          type: integer
        offset:
          type: integer
    ViewQueryRequest:
      type: object
      properties:
        params:
          type: object
          additionalProperties: true
        time:
          $ref: '#/components/schemas/TimeConfig'
        limit:
          type: integer
        offset:
          type: integer
paths:
  /health:
    get:
      summary: 健康检查
      responses:
        '200':
          description: 服务器运行正常
          content:
            application/json:
              schema:
                type: object
                properties:
                  status:
                    type: string
                    example: OK
  /api/v1/query:
    post:
      summary: 执行查询（QueryController）
      security:
        - bearerAuth: []
      parameters:
        - $ref: '#/components/parameters/TenantId'
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/QueryRequest'
            examples:
              example:
                value:
                  entity: orders
                  select:
                    - field: date
                      alias: date
                    - field: amount
                      agg: SUM
                      alias: revenue
                  filter:
                    op: AND
                    conditions:
                      - field: status
                        op: EQ
                        value: PAID
                      - field: country
                        op: IN
                        value:
                          - US
                          - CA
                  time:
                    granularity: DAY
                    range:
                      from: '2024-09-01'
                      to: '2024-09-30'
                  limit: 100
                  offset: 0
      responses:
        '200':
          description: 成功
          content:
            application/json:
              schema:
                type: object
                properties:
                  success:
                    type: boolean
                  data:
                    type: object
                    properties:
                      columns:
                        type: array
                        items:
                          type: string
                      rows:
                        type: array
                        items:
                          type: array
                          items:
                            oneOf:
                              - type: string
                              - type: number
                              - type: boolean
                              - type: 'null'
              examples:
                example:
                  value:
                    success: true
                    data:
                      columns:
                        - date
                        - revenue
                      rows:
                        - - '2024-09-01'
                          - 1200.5
  /api/v1/query/validate:
    post:
      summary: 验证查询 DSL
      security:
        - bearerAuth: []
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/QueryRequest'
            examples:
              example:
                value:
                  entity: orders
                  select:
                    - field: amount
                      agg: SUM
      responses:
        '200':
          description: 成功
          content:
            application/json:
              schema:
                type: object
                properties:
                  success:
                    type: boolean
                  data:
                    type: boolean
              examples:
                ok:
                  value:
                    success: true
                    data: true
  /api/v1/query/explain:
    post:
      summary: 解释计划
      security:
        - bearerAuth: []
      parameters:
        - $ref: '#/components/parameters/TenantId'
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/QueryRequest'
      responses:
        '200':
          description: 成功
          content:
            application/json:
              schema:
                type: object
                properties:
                  success:
                    type: boolean
                  data:
                    type: string
              examples:
                example:
                  value:
                    success: true
                    data: Seq Scan on orders...
  /api/v1/metric/{metricName}/query:
    post:
      summary: 单指标查询（MetricQueryController）
      security:
        - bearerAuth: []
      parameters:
        - name: metricName
          in: path
          required: true
          schema:
            type: string
        - $ref: '#/components/parameters/TenantId'
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/MetricQueryParams'
            examples:
              example:
                value:
                  dimensions:
                    - channel
                  filter:
                    op: AND
                    conditions:
                      - field: country
                        op: EQ
                        value: US
                      - field: status
                        op: EQ
                        value: PAID
                  time:
                    granularity: DAY
                    range:
                      from: '2024-09-01'
                      to: '2024-09-30'
                  limit: 50
      responses:
        '200':
          description: 成功
          content:
            application/json:
              schema:
                type: object
                properties:
                  success:
                    type: boolean
                  data:
                    type: object
                    properties:
                      columns:
                        type: array
                        items:
                          type: string
                      rows:
                        type: array
                        items:
                          type: array
                          items:
                            oneOf:
                              - type: string
                              - type: number
              examples:
                example:
                  value:
                    success: true
                    data:
                      columns:
                        - channel
                        - revenue
                      rows:
                        - - web
                          - 5000
                        - - store
                          - 3000
  /api/v1/metric/query/batch:
    post:
      summary: 批量指标查询
      security:
        - bearerAuth: []
      parameters:
        - $ref: '#/components/parameters/TenantId'
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              properties:
                metrics:
                  type: array
                  items:
                    type: string
                params:
                  $ref: '#/components/schemas/MetricQueryParams'
              required:
                - metrics
            examples:
              example:
                value:
                  metrics:
                    - revenue
                    - orders_count
                  params:
                    dimensions:
                      - channel
                    limit: 10
      responses:
        '200':
          description: 成功
          content:
            application/json:
              schema:
                type: object
                properties:
                  success:
                    type: boolean
                  data:
                    type: object
              examples:
                example:
                  value:
                    success: true
                    data:
                      revenue:
                        columns:
                          - channel
                          - revenue
                        rows:
                          - - web
                            - 5000
                      orders_count:
                        columns:
                          - channel
                          - orders_count
                        rows:
                          - - web
                            - 120
  /api/v1/views/{viewName}/query:
    post:
      summary: 根据视图名称执行查询（ViewController）
      security:
        - bearerAuth: []
      parameters:
        - name: viewName
          in: path
          required: true
          schema:
            type: string
        - $ref: '#/components/parameters/TenantId'
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/ViewQueryRequest'
            examples:
              example:
                value:
                  params:
                    country: US
                    channel: web
                  time:
                    granularity: DAY
                    range:
                      from: '2024-09-01'
                      to: '2024-09-30'
                  limit: 100
      responses:
        '200':
          description: 成功
          content:
            application/json:
              schema:
                type: object
                properties:
                  success:
                    type: boolean
                  data:
                    type: object
                    properties:
                      columns:
                        type: array
                        items:
                          type: string
                      rows:
                        type: array
                        items:
                          type: array
                          items:
                            oneOf:
                              - type: string
                              - type: number
              examples:
                example:
                  value:
                    success: true
                    data:
                      columns:
                        - date
                        - revenue
                      rows:
                        - - '2024-09-01'
                          - 1200.5
        '400':
          description: 视图参数缺失或视图不存在
          content:
            application/json:
              examples:
                missingParam:
                  value:
                    success: false
                    error:
                      code: VIEW_PARAM_MISSING
                      message: Param 'country' is required
                notFound:
                  value:
                    success: false
                    error:
                      code: VIEW_NOT_FOUND
                      message: View 'sales_overviewx' not found
