syntax = "proto3";

package chatto.api.v1;

import "buf/validate/validate.proto";
import "chatto/api/v1/pagination.proto";
import "chatto/api/v1/users.proto";
import "google/protobuf/timestamp.proto";

// Public user/member row used by user directory, room membership, and mention
// surfaces.
message DirectoryMember {
  // Public user fields.
  User user = 1;
  // Explicit roles assigned to the user. Member listings include the virtual
  // `everyone` role for parity with Chatto's permission model.
  repeated string roles = 2;
  // Account creation time when known.
  google.protobuf.Timestamp created_at = 3;
}

// Request for users visible to the authenticated user.
message ListUsersRequest {
  reserved 2, 3;
  reserved "limit", "offset";

  // Optional case-insensitive search against login and display name.
  string search = 1 [(buf.validate.field).string.max_len = 100];
  // Page request. Defaults to 20 results when absent or limit is zero.
  PageRequest page = 4;
}

// User directory page.
message ListUsersResponse {
  reserved 2, 3;
  reserved "total_count", "has_more";

  // Users in the requested page.
  repeated DirectoryMember users = 1;
  // Page metadata.
  PageInfo page = 4;
}

// Request one visible user by stable user ID or login.
message GetUserRequest {
  oneof target {
    // Target stable user ID.
    string user_id = 1 [(buf.validate.field).string.min_len = 1];
    // Target login identifier.
    string login = 2 [(buf.validate.field).string.min_len = 1];
  }
}

// User directory response.
message GetUserResponse {
  // Requested user.
  DirectoryMember user = 1;
}

// Request user directory rows for a set of stable user IDs.
message BatchGetUsersRequest {
  // Required target user IDs. Unknown IDs are omitted from the response.
  repeated string user_ids = 1 [(buf.validate.field).repeated = {
    min_items: 1
    max_items: 100
    items: {
      string: {min_len: 1}
    }
  }];
}

// Batch user directory response.
message BatchGetUsersResponse {
  // Found users. The server preserves first-seen request order and
  // de-duplicates repeated IDs.
  repeated DirectoryMember users = 1;
}

// Request for members of one room.
message ListRoomMembersRequest {
  reserved 3, 4;
  reserved "limit", "offset";

  // Required. Room whose explicit members should be listed.
  string room_id = 1 [(buf.validate.field).string.min_len = 1];
  // Optional case-insensitive search against login and display name.
  string search = 2 [(buf.validate.field).string.max_len = 100];
  // Page request. Defaults to 250 results when absent or limit is zero.
  PageRequest page = 5;
}

// Room member page.
message ListRoomMembersResponse {
  reserved 2, 3;
  reserved "total_count", "has_more";

  // Members in the requested page.
  repeated DirectoryMember members = 1;
  // Page metadata.
  PageInfo page = 4;
}

// Request one member of one room by stable user ID.
message GetRoomMemberRequest {
  // Required room ID.
  string room_id = 1 [(buf.validate.field).string.min_len = 1];
  // Required target user ID.
  string user_id = 2 [(buf.validate.field).string.min_len = 1];
}

// Room member response.
message GetRoomMemberResponse {
  // Requested room member.
  DirectoryMember member = 1;
}

// Request room member rows for a set of stable user IDs.
message BatchGetRoomMembersRequest {
  // Required room ID.
  string room_id = 1 [(buf.validate.field).string.min_len = 1];
  // Required target user IDs. Unknown IDs and users that are not members of the
  // room are omitted from the response.
  repeated string user_ids = 2 [(buf.validate.field).repeated = {
    min_items: 1
    max_items: 100
    items: {
      string: {min_len: 1}
    }
  }];
}

// Batch room member response.
message BatchGetRoomMembersResponse {
  // Found members. The server preserves first-seen request order and
  // de-duplicates repeated IDs.
  repeated DirectoryMember members = 1;
}

// Reads the authenticated server-wide user directory.
service UserService {
  // Lists users visible to the authenticated user. Admin-sensitive account
  // fields stay out of this public row shape.
  rpc ListUsers(ListUsersRequest) returns (ListUsersResponse);
  // Gets one visible user by user ID or login. Returns NOT_FOUND when the
  // target is unknown.
  rpc GetUser(GetUserRequest) returns (GetUserResponse);
  // Gets visible user rows for multiple stable user IDs. Unknown IDs are
  // omitted from the response.
  rpc BatchGetUsers(BatchGetUsersRequest) returns (BatchGetUsersResponse);
}
