asyncapi: '3.0.0'
info:
  title: MSPlatform トークルーム WebSocket API
  version: '1.0.0'
  description: |
    MSPlatform マッチングサービス基盤のリアルタイムトークルーム機能
    
    ## 🎯 主要機能
    - **リアルタイムメッセージング**: 1対1・グループチャット対応
    - **既読管理**: 個別ユーザー単位の精密な既読状態管理
    - **入力中通知**: リアルタイム入力状態の共有
    - **認証**: JWT認証によるセキュアな接続
    
    ## 🔐 認証
    WebSocket接続時にJWT認証が必要です。
    フロントエンドでSockJS/STOMPクライアントを使用してください。
    
    ## 📝 使用例
    ```javascript
    const client = new StompJs.Client({
      brokerURL: 'ws://localhost:8080/ws/talk',
      connectHeaders: {
        Authorization: 'Bearer YOUR_JWT_TOKEN'
      }
    });
    ```
  
  contact:
    name: MSPlatform Development Team
    email: dev@msplatform.example.com
  
  license:
    name: Private License
    url: https://msplatform.example.com/license

servers:
  development:
    host: 'localhost:8080'
    protocol: ws
    description: 開発環境WebSocketサーバー
    security:
      - $ref: '#/components/securitySchemes/jwtAuth'
    
  production:
    host: 'api.msplatform.example.com'
    protocol: wss
    description: 本番環境WebSocketサーバー（SSL対応）
    security:
      - $ref: '#/components/securitySchemes/jwtAuth'

defaultContentType: application/json

channels:
  # WebSocket接続エンドポイント
  'ws/talk':
    address: '/ws/talk'
    messages:
      connectionEstablished:
        $ref: '#/components/messages/connectionEstablished'
    description: |
      WebSocket接続エンドポイント（SockJS対応）
      
      **接続URL**: `ws://localhost:8080/ws/talk`
      **プロトコル**: STOMP over SockJS
      
      ### 接続手順
      1. SockJS/STOMPクライアント初期化
      2. JWT認証ヘッダー設定
      3. WebSocket接続確立
      4. 各チャンネルに購読

  # メッセージ送信（クライアント→サーバー）
  'app/talkroom/{roomCode}/send':
    address: '/app/talkroom/{roomCode}/send'
    messages:
      sendMessage:
        $ref: '#/components/messages/sendMessage'
    parameters:
      roomCode:
        description: 'トークルームの外部コード（16文字）'
        schema:
          type: string
          pattern: '^[A-Z0-9]{16}$'
          example: 'ABC123DEF456GHI7'
    description: |
      メッセージ送信チャンネル
      
      クライアントがこのチャンネルにメッセージを送信すると、
      同じトークルームの全参加者に配信されます。

  # メッセージ受信購読（サーバー→クライアント）  
  'topic/talkroom/{roomCode}':
    address: '/topic/talkroom/{roomCode}'
    messages:
      messageReceived:
        $ref: '#/components/messages/messageReceived'
    parameters:
      roomCode:
        description: 'トークルームの外部コード（16文字）'
        schema:
          type: string
          pattern: '^[A-Z0-9]{16}$'
          example: 'ABC123DEF456GHI7'
    description: |
      メッセージ受信購読チャンネル
      
      このチャンネルを購読することで、
      トークルーム内の全メッセージをリアルタイム受信できます。

  # 入力中状態送信
  'app/talkroom/{roomCode}/typing':
    address: '/app/talkroom/{roomCode}/typing'
    messages:
      sendTyping:
        $ref: '#/components/messages/sendTyping'
    parameters:
      roomCode:
        description: 'トークルームの外部コード（16文字）'
        schema:
          type: string
          pattern: '^[A-Z0-9]{16}$'
          example: 'ABC123DEF456GHI7'
    description: |
      入力中状態通知チャンネル
      
      ユーザーがメッセージを入力中であることを
      他の参加者に通知します。

  # 入力中状態受信購読
  'topic/talkroom/{roomCode}/typing':
    address: '/topic/talkroom/{roomCode}/typing'
    messages:
      typingNotification:
        $ref: '#/components/messages/typingNotification'
    parameters:
      roomCode:
        description: 'トークルームの外部コード（16文字）'
        schema:
          type: string
          pattern: '^[A-Z0-9]{16}$'
          example: 'ABC123DEF456GHI7'
    description: |
      入力中状態受信購読チャンネル
      
      他のユーザーの入力中状態を
      リアルタイムで受信できます。

operations:
  # 接続確立
  connectToTalkRoom:
    action: receive
    channel:
      $ref: '#/channels/ws~1talk'
    summary: WebSocket接続確立
    description: |
      WebSocket接続を確立します。
      JWT認証が必要です。

  # メッセージ送信
  sendMessageToRoom:
    action: send
    channel:
      $ref: '#/channels/app~1talkroom~1{roomCode}~1send'
    summary: トークルームにメッセージ送信
    description: |
      指定したトークルームにメッセージを送信します。
      送信者は該当トークルームの参加者である必要があります。

  # メッセージ受信購読
  subscribeToRoomMessages:
    action: receive
    channel:
      $ref: '#/channels/topic~1talkroom~1{roomCode}'
    summary: トークルームメッセージ受信購読
    description: |
      指定したトークルームのメッセージを購読します。
      リアルタイムでメッセージを受信できます。

  # 入力中状態送信
  sendTypingNotification:
    action: send
    channel:
      $ref: '#/channels/app~1talkroom~1{roomCode}~1typing'
    summary: 入力中状態通知送信
    description: |
      ユーザーがメッセージを入力中であることを通知します。

  # 入力中状態受信購読
  subscribeToTypingNotifications:
    action: receive
    channel:
      $ref: '#/channels/topic~1talkroom~1{roomCode}~1typing'
    summary: 入力中状態受信購読
    description: |
      他のユーザーの入力中状態をリアルタイムで受信します。

components:
  messages:
    # 接続確立通知
    connectionEstablished:
      name: ConnectionEstablished
      title: WebSocket接続確立
      summary: WebSocket接続が正常に確立されました
      contentType: application/json
      payload:
        $ref: '#/components/schemas/ConnectionEvent'

    # メッセージ送信
    sendMessage:
      name: SendMessage
      title: メッセージ送信
      summary: トークルームにメッセージを送信
      contentType: application/json
      payload:
        $ref: '#/components/schemas/MessageRequest'
      examples:
        - name: テキストメッセージ
          summary: 通常のテキストメッセージ
          payload:
            message: "こんにちは！元気ですか？"
            messageType: "TEXT"
            replyToMessageId: null
        - name: 返信メッセージ  
          summary: 特定メッセージへの返信
          payload:
            message: "ありがとうございます！"
            messageType: "TEXT"
            replyToMessageId: 12345

    # メッセージ受信
    messageReceived:
      name: MessageReceived
      title: メッセージ受信
      summary: トークルーム内のメッセージを受信
      contentType: application/json
      payload:
        $ref: '#/components/schemas/Message'
      examples:
        - name: 通常メッセージ
          summary: 他ユーザーからのメッセージ
          payload:
            id: 12345
            talkRoomId: 1
            senderProfileId: 67890
            receiverProfileId: null
            message: "おはようございます！"
            messageType: "TEXT"
            deliveredAt: "2024-08-21T08:00:00Z"
            replyToMessageId: null
            createdAt: "2024-08-21T08:00:00Z"
            updatedAt: "2024-08-21T08:00:00Z"

    # 入力中状態送信
    sendTyping:
      name: SendTyping
      title: 入力中状態送信
      summary: 入力中状態を他の参加者に通知
      contentType: application/json
      payload:
        type: object
        properties: {}
        description: 空のオブジェクト（送信者情報はサーバー側で自動設定）

    # 入力中状態通知
    typingNotification:
      name: TypingNotification  
      title: 入力中状態通知
      summary: 他ユーザーの入力中状態を受信
      contentType: application/json
      payload:
        $ref: '#/components/schemas/TypingNotification'

  schemas:
    # 接続イベント
    ConnectionEvent:
      type: object
      properties:
        event:
          type: string
          description: イベント種別
          example: "CONNECTED"
        timestamp:
          type: string
          format: date-time
          description: 接続時刻
        sessionId:
          type: string
          description: WebSocketセッションID
          example: "session-12345-abcde"

    # メッセージ送信リクエスト
    MessageRequest:
      type: object
      required:
        - message
        - messageType
      properties:
        message:
          type: string
          description: メッセージ内容
          maxLength: 1000
          example: "こんにちは！元気ですか？"
        messageType:
          type: string
          enum: [TEXT, IMAGE, FILE, SYSTEM]
          description: メッセージタイプ
          default: TEXT
          example: "TEXT"
        replyToMessageId:
          type: integer
          format: int64
          nullable: true
          description: 返信対象メッセージID（返信の場合のみ）
          example: 12345

    # メッセージ
    Message:
      type: object
      required:
        - id
        - talkRoomId
        - senderProfileId
        - message
        - messageType
        - deliveredAt
        - createdAt
        - updatedAt
      properties:
        id:
          type: integer
          format: int64
          description: メッセージID
          example: 12345
        talkRoomId:
          type: integer
          format: int64
          description: 所属トークルームID
          example: 1
        senderProfileId:
          type: integer
          format: int64
          nullable: true
          description: 送信者プロフィールID（システムメッセージの場合null）
          example: 67890
        receiverProfileId:
          type: integer
          format: int64
          nullable: true
          description: 受信者プロフィールID（1対1トークのみ）
          example: 11111
        message:
          type: string
          description: メッセージ内容
          example: "おはようございます！"
        messageType:
          type: string
          enum: [TEXT, IMAGE, FILE, SYSTEM]
          description: メッセージタイプ
          example: "TEXT"
        deliveredAt:
          type: string
          format: date-time
          description: サーバー受信時刻
          example: "2024-08-21T08:00:00Z"
        replyToMessageId:
          type: integer
          format: int64
          nullable: true
          description: 返信対象メッセージID
          example: 11111
        createdAt:
          type: string
          format: date-time
          description: 作成時刻
          example: "2024-08-21T08:00:00Z"
        updatedAt:
          type: string
          format: date-time
          description: 更新時刻
          example: "2024-08-21T08:00:00Z"

    # 入力中状態通知
    TypingNotification:
      type: object
      required:
        - userId
        - isTyping
      properties:
        userId:
          type: integer
          format: int64
          description: 入力中ユーザーのID
          example: 67890
        isTyping:
          type: boolean
          description: 入力中フラグ
          example: true

  securitySchemes:
    jwtAuth:
      type: httpApiKey
      in: header
      description: |
        JWT認証トークン
        
        **取得方法**: 
        1. `/api/v1/auth/login` エンドポイントでログイン
        2. レスポンスの `token` を使用
        
        **設定例**:
        ```javascript
        connectHeaders: {
          Authorization: 'Bearer YOUR_JWT_TOKEN'
        }
        ```