openapi: "3.1.0"
info:
  title: GreenDial API
  description: |
    REST API for GreenDial — a personal health assistant powered by Doc and
    a team of specialist health agents.

    **Authentication**: Most endpoints require the user_id path parameter.
    Third-party API endpoints use HTTP Basic Auth (username:passphrase).

    **Base URL**: https://greendial.org (or http://localhost:8012 in development)
  version: "2.0.0"
  contact:
    name: GreenDial
    url: https://greendial.org

servers:
  - url: https://greendial.org
    description: Production

paths:
  # ── SYSTEM ──────────────────────────────────────────────────
  /ping:
    get:
      operationId: ping
      summary: Health check
      responses:
        "200":
          description: Service is running
          content:
            application/json:
              schema:
                type: object
                properties:
                  status: {type: string, example: ok}
                  service: {type: string, example: greendial}

  /stats:
    get:
      operationId: getStats
      summary: Public site statistics
      description: Returns total registered user count. No auth required.
      responses:
        "200":
          content:
            application/json:
              schema:
                type: object
                properties:
                  user_count: {type: integer}

  # ── AUTHENTICATION ───────────────────────────────────────────
  /auth:
    post:
      operationId: authenticate
      summary: Sign in or create account
      description: |
        Login: send username + password.
        Signup: also send create_new: true and hipaa_waiver_accepted: true.
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              required: [username, password]
              properties:
                username: {type: string}
                password: {type: string, description: "Passphrase (never transmitted over HTTP in production)"}
                create_new: {type: boolean, default: false}
                hipaa_waiver_accepted: {type: boolean}
                profile: {type: object, additionalProperties: true}
      responses:
        "200":
          description: Authenticated or account created
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/AuthResponse'
        "400": {description: Missing required field or HIPAA waiver not accepted}
        "401": {description: Invalid passphrase}
        "404": {description: User not found}
        "409": {description: Username already taken}

  # ── CHAT ────────────────────────────────────────────────────
  /chat:
    post:
      operationId: postChat
      summary: Send a message to Doc
      description: |
        The primary conversation endpoint. Doc (the coordinator AI) responds,
        optionally dispatching to a specialist agent for expert context.
        Profile updates are extracted and saved automatically.
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              required: [text]
              properties:
                text: {type: string, description: User's message}
                user_id: {type: string, description: "User ID (required for authenticated users)"}
                session_id: {type: string, description: "Session token (generated by server on first request)"}
      responses:
        "200":
          content:
            application/json:
              schema:
                type: object
                properties:
                  response: {type: string, description: "Doc's reply (markdown supported)"}
                  session_id: {type: string}
                  user_id: {type: string}
                  profile_updated: {type: boolean}
                  profile: {type: object, description: "Updated profile if profile_updated is true"}

  # ── USER PROFILE ─────────────────────────────────────────────
  /user/{user_id}:
    get:
      operationId: getUser
      summary: Get full user record (excluding passphrase)
      parameters:
        - {name: user_id, in: path, required: true, schema: {type: string}}
      responses:
        "200":
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/UserRecord'
        "404": {description: User not found}

    put:
      operationId: updateUser
      summary: Update user profile or settings
      description: Allowed fields — username, settings, profile. Nested objects are merged.
      parameters:
        - {name: user_id, in: path, required: true, schema: {type: string}}
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                username: {type: string}
                settings: {type: object}
                profile: {type: object}
      responses:
        "200":
          content:
            application/json:
              schema:
                type: object
                properties:
                  success: {type: boolean}
                  user: {$ref: '#/components/schemas/UserRecord'}

  # ── SETTINGS ────────────────────────────────────────────────
  /settings/{user_id}:
    get:
      operationId: getSettings
      summary: Get user settings
      parameters:
        - {name: user_id, in: path, required: true, schema: {type: string}}
      responses:
        "200":
          content:
            application/json:
              schema:
                type: object
                properties:
                  settings: {$ref: '#/components/schemas/UserSettings'}

    put:
      operationId: updateSettings
      summary: Update user settings (partial update)
      parameters:
        - {name: user_id, in: path, required: true, schema: {type: string}}
      requestBody:
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/UserSettings'
      responses:
        "200":
          content:
            application/json:
              schema:
                type: object
                properties:
                  success: {type: boolean}
                  settings: {$ref: '#/components/schemas/UserSettings'}

  # ── AGENTS ───────────────────────────────────────────────────
  /agents/{user_id}:
    get:
      operationId: getAgentSubscriptions
      summary: Get agent subscription status and available agents
      parameters:
        - {name: user_id, in: path, required: true, schema: {type: string}}
      responses:
        "200":
          content:
            application/json:
              schema:
                type: object
                properties:
                  subscriptions:
                    type: array
                    items: {type: string}
                    example: [diet, sleep, mental_health]
                  agent_prefs:
                    type: object
                    additionalProperties: true
                  available_agents:
                    type: array
                    items:
                      type: object
                      properties:
                        id: {type: string}
                        name: {type: string}
                        emoji: {type: string}
                        subscribed: {type: boolean}

    put:
      operationId: updateAgentSubscriptions
      summary: Update agent subscriptions and preferences
      parameters:
        - {name: user_id, in: path, required: true, schema: {type: string}}
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                subscriptions:
                  type: array
                  description: List of agent IDs to subscribe to
                  items:
                    type: string
                    enum: [diet, exercise, immunity, sleep, disease_prevention, mental_health, relationships, environment, custom]
                  example: [diet, sleep]
                agent_prefs:
                  type: object
                  description: Per-agent preference overrides
                  additionalProperties: true
                  example:
                    diet: {style: plant-based}
                    sleep: {goal_hours: 8}
                custom_agent_prompt:
                  type: string
                  description: System prompt for the Custom agent (max 2000 chars)
                  maxLength: 2000
      responses:
        "200":
          content:
            application/json:
              schema:
                type: object
                properties:
                  success: {type: boolean}
                  subscriptions: {type: array, items: {type: string}}

  # ── NOTIFICATIONS ────────────────────────────────────────────
  /notifications/{user_id}:
    get:
      operationId: getNotifications
      summary: Get user's pending notifications (last 10)
      parameters:
        - {name: user_id, in: path, required: true, schema: {type: string}}
      responses:
        "200":
          content:
            application/json:
              schema:
                type: object
                properties:
                  notifications:
                    type: array
                    items:
                      $ref: '#/components/schemas/Notification'

  /notifications/{user_id}/generate:
    post:
      operationId: generateNotification
      summary: Trigger an on-demand notification for the user
      parameters:
        - {name: user_id, in: path, required: true, schema: {type: string}}
      responses:
        "200":
          content:
            application/json:
              schema:
                type: object
                properties:
                  notification:
                    oneOf:
                      - $ref: '#/components/schemas/Notification'
                      - {type: "null"}

  /notifications/{user_id}/{notification_id}:
    delete:
      operationId: dismissNotification
      summary: Dismiss a notification
      parameters:
        - {name: user_id, in: path, required: true, schema: {type: string}}
        - {name: notification_id, in: path, required: true, schema: {type: string}}
      responses:
        "200":
          content:
            application/json:
              schema:
                type: object
                properties:
                  success: {type: boolean}

  # ── CONVERSATION HISTORY ─────────────────────────────────────
  /conversations/{user_id}:
    get:
      operationId: getConversations
      summary: Get conversation transcript
      parameters:
        - {name: user_id, in: path, required: true, schema: {type: string}}
      responses:
        "200":
          content:
            application/json:
              schema:
                type: object
                properties:
                  transcript: {type: string}
                  conversations: {type: array}

    delete:
      operationId: clearConversations
      summary: Clear all conversation history
      parameters:
        - {name: user_id, in: path, required: true, schema: {type: string}}
      responses:
        "200":
          content:
            application/json:
              schema:
                type: object
                properties:
                  success: {type: boolean}

  # ── THIRD-PARTY API (Basic Auth) ──────────────────────────────
  /api/v1/profile:
    get:
      operationId: apiGetProfile
      summary: Get profile via Basic Auth (third-party integration)
      security:
        - basicAuth: []
      responses:
        "200":
          content:
            application/json:
              schema:
                type: object
                properties:
                  user_id: {type: string}
                  username: {type: string}
                  profile: {type: object}
                  created: {type: string, format: date-time}
                  last_updated: {type: string, format: date-time}
        "401": {description: Invalid credentials}

    put:
      operationId: apiUpdateProfile
      summary: Update profile via Basic Auth (third-party integration)
      security:
        - basicAuth: []
      requestBody:
        content:
          application/json:
            schema:
              type: object
              required: [profile]
              properties:
                profile:
                  type: object
                  description: Fields to merge into the user's health profile
      responses:
        "200":
          content:
            application/json:
              schema:
                type: object
                properties:
                  success: {type: boolean}
                  user_id: {type: string}
                  updated_fields: {type: array, items: {type: string}}

  # ── ADMIN ─────────────────────────────────────────────────────
  /admin/stats:
    get:
      operationId: getAdminStats
      summary: Admin — user statistics (admin only)
      parameters:
        - {name: user_id, in: query, required: true, schema: {type: string}}
      responses:
        "200":
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/AdminStats'
        "403": {description: Unauthorized}

  /admin/balances:
    get:
      operationId: getAdminBalances
      summary: Admin — live crypto donation wallet balances
      parameters:
        - {name: user_id, in: query, required: true, schema: {type: string}}
      responses:
        "200":
          content:
            application/json:
              schema:
                type: object
                properties:
                  btc: {type: number, nullable: true, example: 0.00045}
                  eth: {type: number, nullable: true, example: 0.012}
                  btc_address: {type: string}
                  eth_address: {type: string}
        "403": {description: Unauthorized}

components:
  securitySchemes:
    basicAuth:
      type: http
      scheme: basic
      description: HTTP Basic Auth with username:passphrase

  schemas:
    AuthResponse:
      type: object
      properties:
        user_id: {type: string}
        username: {type: string}
        new_user: {type: boolean}
        settings: {$ref: '#/components/schemas/UserSettings'}
        profile: {type: object}

    UserRecord:
      type: object
      properties:
        user_id: {type: string}
        username: {type: string}
        created: {type: string, format: date-time}
        last_updated: {type: string, format: date-time}
        profile: {type: object, additionalProperties: true}
        settings: {$ref: '#/components/schemas/UserSettings'}
        notifications:
          type: array
          items: {$ref: '#/components/schemas/Notification'}

    UserSettings:
      type: object
      properties:
        doc_style:
          type: string
          enum: [questioning, professional, friendly]
          default: questioning
        theme:
          type: string
          enum: [dark, light]
          default: dark
        notifications_enabled:
          type: boolean
          default: true
        agent_subscriptions:
          type: array
          items:
            type: string
            enum: [diet, exercise, immunity, sleep, disease_prevention, mental_health, relationships, environment, custom]
          description: Agents that will send periodic check-in notifications
        agent_prefs:
          type: object
          description: Per-agent preference overrides
          additionalProperties: true
        custom_agent_prompt:
          type: string
          description: Custom system prompt for the Custom agent
          maxLength: 2000
        notification_schedule:
          type: string
          description: When to receive cron notifications
          enum: [daily_morning, daily_evening, weekly]
          default: daily_morning
        timezone:
          type: string
          description: IANA timezone name
          example: America/New_York

    Notification:
      type: object
      properties:
        id: {type: string, format: uuid}
        type: {type: string, example: diet_checkin}
        agent: {type: string, example: diet}
        message: {type: string, example: "Try adding leafy greens to one meal today!"}
        created: {type: string, format: date-time}
        read: {type: boolean, default: false}

    AdminStats:
      type: object
      properties:
        total_users: {type: integer}
        new_today: {type: integer}
        with_profile: {type: integer}
        users:
          type: array
          items:
            type: object
            properties:
              user_id: {type: string}
              username: {type: string}
              created: {type: string}
              profile_fields: {type: integer}
              doc_style: {type: string}
