openapi: 3.0.3
info:
  title: Account Management API
  description: RBAC 账号管理接口 - 支持账号的创建、查询、更新、删除和角色分配
  version: 1.0.0

servers:
  - url: http://localhost:8080/api/v1
    description: Development server

tags:
  - name: accounts
    description: 账号管理
  - name: account-roles
    description: 账号-角色关联

paths:
  /accounts:
    post:
      summary: 创建账号
      description: 创建新账号，非 root 账号必须提供 parent_id，密码使用 bcrypt 哈希
      tags:
        - accounts
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/CreateAccountRequest'
      responses:
        '200':
          description: 创建成功
          content:
            application/json:
              schema:
                allOf:
                  - $ref: '#/components/schemas/ApiResponse'
                  - type: object
                    properties:
                      data:
                        $ref: '#/components/schemas/AccountResponse'
        '400':
          description: 请求参数错误
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ApiResponse'
        '500':
          description: 服务器错误
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ApiResponse'

    get:
      summary: 查询账号列表
      description: 分页查询账号列表，自动应用数据权限过滤（只返回自己和下级创建的账号）
      tags:
        - accounts
      parameters:
        - name: page
          in: query
          description: 页码（从 1 开始）
          schema:
            type: integer
            default: 1
            minimum: 1
        - name: page_size
          in: query
          description: 每页大小
          schema:
            type: integer
            default: 20
            minimum: 1
            maximum: 100
        - name: username
          in: query
          description: 用户名模糊查询
          schema:
            type: string
        - name: user_type
          in: query
          description: 用户类型过滤（1=root, 2=平台, 3=代理, 4=企业）
          schema:
            type: integer
            enum: [1, 2, 3, 4]
        - name: status
          in: query
          description: 状态过滤（0=禁用, 1=启用）
          schema:
            type: integer
            enum: [0, 1]
      responses:
        '200':
          description: 查询成功
          content:
            application/json:
              schema:
                allOf:
                  - $ref: '#/components/schemas/ApiResponse'
                  - type: object
                    properties:
                      data:
                        $ref: '#/components/schemas/ListAccountsResponse'
        '400':
          description: 请求参数错误
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ApiResponse'
        '500':
          description: 服务器错误
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ApiResponse'

  /accounts/{id}:
    get:
      summary: 查询账号详情
      description: 根据 ID 查询账号详情，自动应用数据权限过滤
      tags:
        - accounts
      parameters:
        - name: id
          in: path
          required: true
          description: 账号 ID
          schema:
            type: integer
      responses:
        '200':
          description: 查询成功
          content:
            application/json:
              schema:
                allOf:
                  - $ref: '#/components/schemas/ApiResponse'
                  - type: object
                    properties:
                      data:
                        $ref: '#/components/schemas/AccountResponse'
        '404':
          description: 账号不存在或无权访问
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ApiResponse'
        '500':
          description: 服务器错误
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ApiResponse'

    put:
      summary: 更新账号
      description: 更新账号信息，禁止修改 parent_id 和 user_type
      tags:
        - accounts
      parameters:
        - name: id
          in: path
          required: true
          description: 账号 ID
          schema:
            type: integer
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/UpdateAccountRequest'
      responses:
        '200':
          description: 更新成功
          content:
            application/json:
              schema:
                allOf:
                  - $ref: '#/components/schemas/ApiResponse'
                  - type: object
                    properties:
                      data:
                        $ref: '#/components/schemas/AccountResponse'
        '400':
          description: 请求参数错误
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ApiResponse'
        '404':
          description: 账号不存在或无权访问
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ApiResponse'
        '500':
          description: 服务器错误
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ApiResponse'

    delete:
      summary: 删除账号
      description: 软删除账号，设置 deleted_at 字段，并清除该账号及所有上级的下级 ID 缓存
      tags:
        - accounts
      parameters:
        - name: id
          in: path
          required: true
          description: 账号 ID
          schema:
            type: integer
      responses:
        '200':
          description: 删除成功
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ApiResponse'
        '404':
          description: 账号不存在或无权访问
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ApiResponse'
        '500':
          description: 服务器错误
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ApiResponse'

  /accounts/{id}/roles:
    post:
      summary: 为账号分配角色
      description: 批量为账号分配角色，已存在的关联会被忽略
      tags:
        - account-roles
      parameters:
        - name: id
          in: path
          required: true
          description: 账号 ID
          schema:
            type: integer
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/AssignRolesToAccountRequest'
      responses:
        '200':
          description: 分配成功
          content:
            application/json:
              schema:
                allOf:
                  - $ref: '#/components/schemas/ApiResponse'
                  - type: object
                    properties:
                      data:
                        type: array
                        items:
                          $ref: '#/components/schemas/AccountRoleResponse'
        '400':
          description: 请求参数错误
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ApiResponse'
        '404':
          description: 账号或角色不存在
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ApiResponse'
        '500':
          description: 服务器错误
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ApiResponse'

    get:
      summary: 查询账号的所有角色
      description: 查询指定账号已分配的所有角色
      tags:
        - account-roles
      parameters:
        - name: id
          in: path
          required: true
          description: 账号 ID
          schema:
            type: integer
      responses:
        '200':
          description: 查询成功
          content:
            application/json:
              schema:
                allOf:
                  - $ref: '#/components/schemas/ApiResponse'
                  - type: object
                    properties:
                      data:
                        type: array
                        items:
                          $ref: '#/components/schemas/RoleResponse'
        '404':
          description: 账号不存在或无权访问
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ApiResponse'
        '500':
          description: 服务器错误
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ApiResponse'

  /accounts/{account_id}/roles/{role_id}:
    delete:
      summary: 移除账号的角色
      description: 软删除账号-角色关联
      tags:
        - account-roles
      parameters:
        - name: account_id
          in: path
          required: true
          description: 账号 ID
          schema:
            type: integer
        - name: role_id
          in: path
          required: true
          description: 角色 ID
          schema:
            type: integer
      responses:
        '200':
          description: 移除成功
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ApiResponse'
        '404':
          description: 账号或角色不存在
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ApiResponse'
        '500':
          description: 服务器错误
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ApiResponse'

components:
  schemas:
    ApiResponse:
      type: object
      required:
        - code
        - message
        - timestamp
      properties:
        code:
          type: integer
          description: 错误码（0 表示成功，1xxx 表示客户端错误，2xxx 表示服务端错误）
          example: 0
        message:
          type: string
          description: 响应消息
          example: success
        data:
          type: object
          description: 响应数据
        timestamp:
          type: string
          format: date-time
          description: 响应时间戳（ISO 8601 格式）
          example: "2025-11-18T15:30:00Z"

    CreateAccountRequest:
      type: object
      required:
        - username
        - phone
        - password
        - user_type
      properties:
        username:
          type: string
          minLength: 3
          maxLength: 20
          pattern: '^[a-zA-Z0-9_]+$'
          description: 用户名（3-20 个字符，字母、数字、下划线）
          example: admin001
        phone:
          type: string
          pattern: '^1[3-9]\d{9}$'
          description: 手机号（11 位中国大陆手机号）
          example: "13812345678"
        password:
          type: string
          minLength: 8
          description: 密码（最少 8 位，包含字母和数字）
          example: "Password123"
        user_type:
          type: integer
          enum: [1, 2, 3, 4]
          description: 用户类型（1=root, 2=平台, 3=代理, 4=企业）
          example: 2
        shop_id:
          type: integer
          nullable: true
          description: 所属店铺 ID（可选）
          example: 10
        parent_id:
          type: integer
          nullable: true
          description: 上级账号 ID（非 root 用户必须提供）
          example: 1
        status:
          type: integer
          enum: [0, 1]
          default: 1
          description: 状态（0=禁用, 1=启用）
          example: 1

    UpdateAccountRequest:
      type: object
      properties:
        username:
          type: string
          minLength: 3
          maxLength: 20
          pattern: '^[a-zA-Z0-9_]+$'
          description: 用户名（可选更新）
          example: admin002
        phone:
          type: string
          pattern: '^1[3-9]\d{9}$'
          description: 手机号（可选更新）
          example: "13812345679"
        password:
          type: string
          minLength: 8
          description: 密码（可选更新）
          example: "NewPassword123"
        status:
          type: integer
          enum: [0, 1]
          description: 状态（可选更新）
          example: 0

    AccountResponse:
      type: object
      properties:
        id:
          type: integer
          description: 账号 ID
          example: 1
        username:
          type: string
          description: 用户名
          example: admin001
        phone:
          type: string
          description: 手机号
          example: "13812345678"
        user_type:
          type: integer
          description: 用户类型（1=root, 2=平台, 3=代理, 4=企业）
          example: 2
        shop_id:
          type: integer
          nullable: true
          description: 所属店铺 ID
          example: 10
        parent_id:
          type: integer
          nullable: true
          description: 上级账号 ID
          example: 1
        status:
          type: integer
          description: 状态（0=禁用, 1=启用）
          example: 1
        creator:
          type: integer
          description: 创建人 ID
          example: 1
        updater:
          type: integer
          description: 更新人 ID
          example: 1
        created_at:
          type: string
          format: date-time
          description: 创建时间
          example: "2025-11-18T10:00:00Z"
        updated_at:
          type: string
          format: date-time
          description: 更新时间
          example: "2025-11-18T10:00:00Z"

    ListAccountsResponse:
      type: object
      properties:
        items:
          type: array
          items:
            $ref: '#/components/schemas/AccountResponse'
        total:
          type: integer
          description: 总记录数
          example: 100
        page:
          type: integer
          description: 当前页码
          example: 1
        page_size:
          type: integer
          description: 每页大小
          example: 20

    AssignRolesToAccountRequest:
      type: object
      required:
        - role_ids
      properties:
        role_ids:
          type: array
          items:
            type: integer
          minItems: 1
          description: 角色 ID 列表
          example: [1, 2, 3]

    AccountRoleResponse:
      type: object
      properties:
        id:
          type: integer
          description: 关联 ID
          example: 1
        account_id:
          type: integer
          description: 账号 ID
          example: 1
        role_id:
          type: integer
          description: 角色 ID
          example: 1
        status:
          type: integer
          description: 状态（0=禁用, 1=启用）
          example: 1
        creator:
          type: integer
          description: 创建人 ID
          example: 1
        created_at:
          type: string
          format: date-time
          description: 创建时间
          example: "2025-11-18T10:00:00Z"

    RoleResponse:
      type: object
      properties:
        id:
          type: integer
          description: 角色 ID
          example: 1
        role_name:
          type: string
          description: 角色名称
          example: 平台管理员
        role_desc:
          type: string
          description: 角色描述
          example: 平台系统管理员角色
        role_type:
          type: integer
          description: 角色类型（1=超级, 2=代理, 3=企业）
          example: 1
        status:
          type: integer
          description: 状态（0=禁用, 1=启用）
          example: 1
        created_at:
          type: string
          format: date-time
          description: 创建时间
          example: "2025-11-18T10:00:00Z"

  securitySchemes:
    BearerAuth:
      type: http
      scheme: bearer
      bearerFormat: JWT

security:
  - BearerAuth: []
