openapi: 3.0.3
info:
  title: Shoehorn Catalog API
  description: Search, statistics, manifest management, and documentation.
  version: 1.0.0

servers:
  - url: https://shoehorn.example.com/api/v1
    description: Production

paths:
  # --- Search ---
  /search:
    get:
      summary: Search entities
      description: Full-text search across all catalog entities using Meilisearch.
      tags: [Search]
      parameters:
        - name: q
          in: query
          required: true
          schema: { type: string }
          description: Search query (supports fuzzy matching)
        - name: type
          in: query
          schema: { type: string }
          description: Filter by entity type
        - name: lifecycle
          in: query
          schema: { type: string }
        - name: owner
          in: query
          schema: { type: string }
        - name: limit
          in: query
          schema: { type: integer, default: 20 }
      responses:
        '200':
          description: Search results
          content:
            application/json:
              schema:
                type: object
                properties:
                  results:
                    type: array
                    items: { $ref: '#/components/schemas/SearchResult' }
                  total: { type: integer }
                  query: { type: string }
                  processing_time_ms: { type: integer }

  # --- Statistics ---
  /stats:
    get:
      summary: Get catalog statistics
      tags: [Statistics]
      responses:
        '200':
          description: Aggregate catalog metrics
          content:
            application/json:
              schema:
                type: object
                properties:
                  total_entities: { type: integer }
                  by_type: { type: object, additionalProperties: { type: integer } }
                  by_lifecycle: { type: object, additionalProperties: { type: integer } }
                  by_tier: { type: object, additionalProperties: { type: integer } }

  /stats/entity-types:
    get:
      summary: Get entity type breakdown
      tags: [Statistics]
      responses:
        '200':
          description: Count by entity type

  /stats/languages:
    get:
      summary: Get programming language distribution
      tags: [Statistics]
      responses:
        '200':
          description: Language statistics

  /stats/lifecycle:
    get:
      summary: Get lifecycle stage distribution
      tags: [Statistics]
      responses:
        '200':
          description: Count by lifecycle stage

  /stats/teams:
    get:
      summary: Get team ownership statistics
      tags: [Statistics]
      responses:
        '200':
          description: Entities per team

  /stats/unowned:
    get:
      summary: Get unowned entities
      tags: [Statistics]
      responses:
        '200':
          description: Entities without an owner

  # --- Metrics ---
  /metrics/dora:
    get:
      summary: Get DORA metrics
      tags: [Metrics]
      parameters:
        - name: team
          in: query
          schema: { type: string }
        - name: period
          in: query
          schema: { type: string, enum: [7d, 30d, 90d] }
      responses:
        '200':
          description: DORA metrics (deployment frequency, lead time, MTTR, change failure rate)

  /metrics/bus-factor:
    get:
      summary: Get bus factor analysis
      tags: [Metrics]
      parameters:
        - name: entity_id
          in: query
          schema: { type: string }
      responses:
        '200':
          description: Bus factor scores

  # --- Manifests ---
  /manifests:
    get:
      summary: List manifests
      tags: [Manifests]
      responses:
        '200':
          description: All manifests

    post:
      summary: Create manifest
      tags: [Manifests]
      requestBody:
        required: true
        content:
          application/json:
            schema: { $ref: '#/components/schemas/ManifestInput' }
      responses:
        '201':
          description: Manifest created

  /manifests/{id}:
    get:
      summary: Get manifest
      tags: [Manifests]
      parameters:
        - name: id
          in: path
          required: true
          schema: { type: string }
      responses:
        '200':
          description: Manifest details

    put:
      summary: Update manifest
      tags: [Manifests]
      parameters:
        - name: id
          in: path
          required: true
          schema: { type: string }
      responses:
        '200':
          description: Manifest updated

    delete:
      summary: Delete manifest
      tags: [Manifests]
      parameters:
        - name: id
          in: path
          required: true
          schema: { type: string }
      responses:
        '204':
          description: Manifest deleted

  /manifests/validate:
    post:
      summary: Validate manifest
      description: Validates a manifest YAML against the schema without creating it.
      tags: [Manifests]
      requestBody:
        required: true
        content:
          application/json:
            schema: { $ref: '#/components/schemas/ManifestInput' }
      responses:
        '200':
          description: Validation results
          content:
            application/json:
              schema:
                type: object
                properties:
                  valid: { type: boolean }
                  errors:
                    type: array
                    items:
                      type: object
                      properties:
                        field: { type: string }
                        message: { type: string }

  /manifests/analyze:
    post:
      summary: Analyze manifest quality
      description: Returns quality score and improvement suggestions.
      tags: [Manifests]
      requestBody:
        required: true
        content:
          application/json:
            schema: { $ref: '#/components/schemas/ManifestInput' }
      responses:
        '200':
          description: Quality analysis

  /manifests/convert:
    post:
      summary: Convert Backstage catalog-info.yaml
      description: Converts a Backstage catalog-info.yaml to Shoehorn manifest format.
      tags: [Manifests]
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              properties:
                content: { type: string, description: Raw YAML content }
      responses:
        '200':
          description: Converted manifest

  # --- Documentation ---
  /docs:
    get:
      summary: List documentation entries
      tags: [Documentation]
      responses:
        '200':
          description: Documentation entries discovered from repositories

  /docs/{id}:
    get:
      summary: Get documentation content
      tags: [Documentation]
      parameters:
        - name: id
          in: path
          required: true
          schema: { type: string }
      responses:
        '200':
          description: Documentation content

  # --- Analytics ---
  /analytics/search:
    get:
      summary: Get search analytics
      tags: [Analytics]
      responses:
        '200':
          description: Search usage analytics

  /analytics/search/{period}:
    get:
      summary: Get search analytics by period
      tags: [Analytics]
      parameters:
        - name: period
          in: path
          required: true
          schema: { type: string, enum: [7d, 30d, 90d] }
      responses:
        '200':
          description: Search analytics for period

  # --- Indexing ---
  /indexing/status:
    get:
      summary: Get search indexing status
      tags: [Indexing]
      responses:
        '200':
          description: Current indexing status and queue size

components:
  schemas:
    SearchResult:
      type: object
      properties:
        id: { type: string }
        service_id: { type: string }
        name: { type: string }
        type: { type: string }
        description: { type: string }
        owner: { type: string }
        lifecycle: { type: string }
        score: { type: number, description: Relevance score }

    ManifestInput:
      type: object
      required: [content]
      properties:
        content: { type: string, description: YAML manifest content }
        format: { type: string, enum: [shoehorn, backstage], default: shoehorn }
