syntax = "proto3";

package hyapp.user.v1;

import "proto/user/v1/user.proto";

option go_package = "hyapp.local/api/proto/user/v1;userv1";

// HostProfile 是用户长期主播身份，不等同于 room-service 的房间 host_user_id。
message HostProfile {
  int64 user_id = 1;
  string status = 2;
  int64 region_id = 3;
  int64 current_agency_id = 4;
  int64 current_membership_id = 5;
  string source = 6;
  int64 first_became_host_at_ms = 7;
  int64 created_at_ms = 8;
  int64 updated_at_ms = 9;
  // current_agency_owner_user_id 是当前 Agency 的收款用户快照，wallet-service 入账时固化该值，避免月底按新归属错发代理工资。
  int64 current_agency_owner_user_id = 10;
}

// Agency 是主播组织，owner 自动拥有 host 身份和 owner membership。
message Agency {
  int64 agency_id = 1;
  int64 owner_user_id = 2;
  int64 region_id = 3;
  int64 parent_bd_user_id = 4;
  string name = 5;
  string status = 6;
  bool join_enabled = 7;
  // Deprecated: Agency 不再限制主播数量，该字段仅为历史兼容保留。
  int32 max_hosts = 8;
  int64 created_by_user_id = 9;
  int64 created_at_ms = 10;
  int64 updated_at_ms = 11;
  string avatar = 12;
  int32 host_count = 13;
}

// BDProfile 表达 BD 或 BD Leader 拓展角色。BD 默认不是 host。
message BDProfile {
  int64 user_id = 1;
  string role = 2;
  int64 region_id = 3;
  int64 parent_leader_user_id = 4;
  string status = 5;
  int64 created_by_user_id = 6;
  int64 created_at_ms = 7;
  int64 updated_at_ms = 8;
  // parent_owner_user_id 是外管团队直接 owner；历史 App BD 仍保留 parent_leader_user_id。
  int64 parent_owner_user_id = 9;
}

// CoinSellerProfile 表达币商身份；余额在 wallet-service，不在 user-service。
message CoinSellerProfile {
  int64 user_id = 1;
  string status = 2;
  string merchant_asset_type = 3;
  int64 created_by_user_id = 4;
  int64 created_at_ms = 5;
  int64 updated_at_ms = 6;
  bool can_manage_sub_coin_sellers = 7;
}

// CoinSellerListItem 是 App 充值页展示的同区域启用币商投影。
message CoinSellerListItem {
  int64 user_id = 1;
  string display_user_id = 2;
  string username = 3;
  string avatar = 4;
  int64 country_id = 5;
  string country_code = 6;
  string country_name = 7;
  string country_display_name = 8;
  int64 region_id = 9;
  string region_code = 10;
  string region_name = 11;
  string status = 12;
  string merchant_asset_type = 13;
  int64 updated_at_ms = 14;
  string contact_info = 15;
  bool can_manage_sub_coin_sellers = 16;
}

// CoinSellerSubRelation 是币商中心的直属子币商关系事实。
message CoinSellerSubRelation {
  int64 relation_id = 1;
  int64 parent_user_id = 2;
  int64 child_user_id = 3;
  string status = 4;
  int64 created_by_user_id = 5;
  int64 created_at_ms = 6;
  int64 updated_at_ms = 7;
}

// CoinSellerSubApplication 是父币商邀请子币商后的后台审核事实。
message CoinSellerSubApplication {
  int64 application_id = 1;
  string command_id = 2;
  int64 parent_user_id = 3;
  int64 target_user_id = 4;
  string status = 5;
  int64 relation_id = 6;
  int64 reviewed_by_admin_id = 7;
  string review_reason = 8;
  int64 reviewed_at_ms = 9;
  int64 created_at_ms = 10;
  int64 updated_at_ms = 11;
}

// UserRoleSummary 是 App 我的页和入口显隐使用的轻量角色摘要。
// 它把 host、Agency、manager、BD 和币商身份收敛到一次 user-service RPC，避免 gateway 随角色扩张继续 fanout。
message UserRoleSummary {
  int64 user_id = 1;
  bool is_host = 2;
  bool is_agency = 3;
  bool is_bd = 4;
  bool is_bd_leader = 5;
  bool is_coin_seller = 6;
  string host_status = 7;
  int64 agency_id = 8;
  int64 bd_id = 9;
  string bd_status = 10;
  string coin_seller_status = 11;
  int64 pending_role_invitations = 12;
  bool is_manager = 13;
  // roles 给后台等需要多身份并列展示的调用方提供稳定字符串集合；原布尔字段继续兼容 App 入口显隐。
  repeated string roles = 14;
}

// AgencyMembership 是 host 与 Agency 的有时效关系事实。
message AgencyMembership {
  int64 membership_id = 1;
  int64 agency_id = 2;
  int64 host_user_id = 3;
  int64 region_id = 4;
  string membership_type = 5;
  string status = 6;
  int64 joined_at_ms = 7;
  int64 ended_at_ms = 8;
  int64 ended_by_user_id = 9;
  string ended_reason = 10;
  int64 created_at_ms = 11;
  int64 updated_at_ms = 12;
}

// AgencyApplication 是用户主动申请加入 Agency 的 App 事实。
message AgencyApplication {
  int64 application_id = 1;
  string command_id = 2;
  int64 applicant_user_id = 3;
  int64 agency_id = 4;
  int64 region_id = 5;
  string status = 6;
  int64 reviewed_by_user_id = 7;
  string review_reason = 8;
  int64 reviewed_at_ms = 9;
  int64 created_at_ms = 10;
  int64 updated_at_ms = 11;
}

// RoleInvitation 是 BD/BD Leader 邀请用户成为 Agency 或 BD 的 App 事实。
message RoleInvitation {
  int64 invitation_id = 1;
  string command_id = 2;
  string invitation_type = 3;
  string status = 4;
  int64 inviter_user_id = 5;
  int64 inviter_bd_user_id = 6;
  int64 target_user_id = 7;
  int64 region_id = 8;
  string agency_name = 9;
  int64 parent_bd_user_id = 10;
  int64 parent_leader_user_id = 11;
  int64 processed_by_user_id = 12;
  string process_reason = 13;
  int64 processed_at_ms = 14;
  int64 created_at_ms = 15;
  int64 updated_at_ms = 16;
  // external_operator_user_id 非 0 表示邀请由外管专用入口创建。
  int64 external_operator_user_id = 17;
  // parent_owner_user_id 固化所选 BD 的外管团队 owner，接受时用于检测归属漂移。
  int64 parent_owner_user_id = 18;
  // parent_agency_id 固化 Host 邀请所选 Agency，不能在接受时改绑到操作者的其他 Agency。
  int64 parent_agency_id = 19;
}

// ExternalTeamUser 是外管团队列表的 user-service 权威投影。
// roles 只可能包含 bd/agency/host；外管 Local、国家外管经理和外管SuperAdmin 不属于 App 业务角色。
message ExternalTeamUser {
  int64 user_id = 1;
  string default_display_user_id = 2;
  string current_display_user_id = 3;
  string username = 4;
  string avatar = 5;
  string status = 6;
  int64 region_id = 7;
  repeated string roles = 8;
  int64 parent_owner_user_id = 9;
  int64 parent_bd_user_id = 10;
  int64 agency_id = 11;
}

message ExternalInviteBDRequest {
  RequestMeta meta = 1;
  string command_id = 2;
  int64 operator_user_id = 3;
  int64 target_user_id = 4;
  int64 expected_region_id = 5;
}

message ExternalInviteBDResponse {
  RoleInvitation invitation = 1;
}

message ExternalInviteAgencyRequest {
  RequestMeta meta = 1;
  string command_id = 2;
  int64 operator_user_id = 3;
  int64 parent_bd_user_id = 4;
  int64 target_user_id = 5;
  string agency_name = 6;
  repeated int64 scope_owner_user_ids = 7;
  int64 expected_region_id = 8;
}

message ExternalInviteAgencyResponse {
  RoleInvitation invitation = 1;
}

message ExternalInviteHostRequest {
  RequestMeta meta = 1;
  string command_id = 2;
  int64 operator_user_id = 3;
  int64 agency_id = 4;
  int64 target_user_id = 5;
  repeated int64 scope_owner_user_ids = 6;
  int64 expected_region_id = 7;
}

message ExternalInviteHostResponse {
  RoleInvitation invitation = 1;
}

message ListExternalTeamUsersRequest {
  RequestMeta meta = 1;
  repeated int64 scope_owner_user_ids = 2;
  int64 region_id = 3;
  // role 为空返回全部团队用户，否则只接受 bd/agency/host。
  string role = 4;
  string status = 5;
  string keyword = 6;
  int32 page = 7;
  int32 page_size = 8;
}

message ListExternalTeamUsersResponse {
  repeated ExternalTeamUser users = 1;
  int64 total = 2;
  int32 page = 3;
  int32 page_size = 4;
}

message SearchExternalInvitationCandidateRequest {
  RequestMeta meta = 1;
  int64 operator_user_id = 2;
  int64 expected_region_id = 3;
  // invitation_type 用于排除已经拥有对应有效身份或归属的目标。
  string invitation_type = 4;
  // keyword 必须精确命中内部长 ID、默认短号或当前短号/靓号。
  string keyword = 5;
}

message SearchExternalInvitationCandidateResponse {
  ExternalTeamUser user = 1;
}

message SearchAgenciesRequest {
  RequestMeta meta = 1;
  int64 user_id = 2;
  string keyword = 3;
  int32 page_size = 4;
}

message SearchAgenciesResponse {
  repeated Agency agencies = 1;
}

message ApplyToAgencyRequest {
  RequestMeta meta = 1;
  string command_id = 2;
  int64 user_id = 3;
  int64 agency_id = 4;
}

message ApplyToAgencyResponse {
  AgencyApplication application = 1;
}

message ReviewAgencyApplicationRequest {
  RequestMeta meta = 1;
  string command_id = 2;
  int64 reviewer_user_id = 3;
  int64 application_id = 4;
  string decision = 5;
  string reason = 6;
}

message ReviewAgencyApplicationResponse {
  AgencyApplication application = 1;
  HostProfile host_profile = 2;
  AgencyMembership membership = 3;
}

message KickAgencyHostRequest {
  RequestMeta meta = 1;
  string command_id = 2;
  int64 operator_user_id = 3;
  int64 agency_id = 4;
  int64 host_user_id = 5;
  string reason = 6;
}

message KickAgencyHostResponse {
  AgencyMembership membership = 1;
  HostProfile host_profile = 2;
}

message InviteAgencyRequest {
  RequestMeta meta = 1;
  string command_id = 2;
  int64 inviter_user_id = 3;
  int64 target_user_id = 4;
  string agency_name = 5;
}

message InviteAgencyResponse {
  RoleInvitation invitation = 1;
}

message InviteBDRequest {
  RequestMeta meta = 1;
  string command_id = 2;
  int64 inviter_user_id = 3;
  int64 target_user_id = 4;
}

message InviteBDResponse {
  RoleInvitation invitation = 1;
}

message InviteHostRequest {
  RequestMeta meta = 1;
  string command_id = 2;
  int64 inviter_user_id = 3;
  int64 target_user_id = 4;
}

message InviteHostResponse {
  RoleInvitation invitation = 1;
}

message ListBDLeaderBDsRequest {
  RequestMeta meta = 1;
  int64 leader_user_id = 2;
  string status = 3;
  int32 page_size = 4;
}

message ListBDLeaderBDsResponse {
  repeated BDProfile bd_profiles = 1;
}

message ListBDLeaderAgenciesRequest {
  RequestMeta meta = 1;
  int64 leader_user_id = 2;
  string status = 3;
  int32 page_size = 4;
}

message ListBDLeaderAgenciesResponse {
  repeated Agency agencies = 1;
}

message ListManagerTeamAgenciesRequest {
  RequestMeta meta = 1;
  int64 manager_user_id = 2;
  // page_size 是防御性截断上限；正常经理团队规模远小于该值，超限时 truncated=true 提示统计口径不完整。
  int32 page_size = 3;
}

// ManagerTeamAgency 是团队统计专用的轻量投影，只承诺归属关系字段；
// 不复用 Agency 消息，避免调用方误以为能拿到名称/头衔/成员数等完整资料。
message ManagerTeamAgency {
  int64 agency_id = 1;
  int64 owner_user_id = 2;
  int64 parent_bd_user_id = 3;
}

message ListManagerTeamAgenciesResponse {
  // agencies 覆盖经理整棵团队树：经理创建的 BD Leader 直挂 Agency + 这些 Leader 下属 BD 拓展的 Agency。
  repeated ManagerTeamAgency agencies = 1;
  int32 total_bd_leaders = 2;
  int32 total_bds = 3;
  bool truncated = 4;
}

message ListBDAgenciesRequest {
  RequestMeta meta = 1;
  int64 bd_user_id = 2;
  string status = 3;
  int32 page_size = 4;
}

message ListBDAgenciesResponse {
  repeated Agency agencies = 1;
}

message ListRoleInvitationsRequest {
  RequestMeta meta = 1;
  int64 target_user_id = 2;
  string status = 3;
  int32 page_size = 4;
}

message ListRoleInvitationsResponse {
  repeated RoleInvitation invitations = 1;
}

message GetRoleInvitationRequest {
  RequestMeta meta = 1;
  int64 actor_user_id = 2;
  int64 invitation_id = 3;
}

message GetRoleInvitationResponse {
  RoleInvitation invitation = 1;
}

message ProcessRoleInvitationRequest {
  RequestMeta meta = 1;
  string command_id = 2;
  int64 actor_user_id = 3;
  int64 invitation_id = 4;
  string action = 5;
  string reason = 6;
}

message ProcessRoleInvitationResponse {
  RoleInvitation invitation = 1;
  HostProfile host_profile = 2;
  Agency agency = 3;
  AgencyMembership membership = 4;
  BDProfile bd_profile = 5;
}

message GetHostProfileRequest {
  RequestMeta meta = 1;
  int64 user_id = 2;
}

message GetHostProfileResponse {
  HostProfile host_profile = 1;
}

message BatchGetHostProfilesRequest {
  RequestMeta meta = 1;
  repeated int64 user_ids = 2;
}

message BatchGetHostProfilesResponse {
  map<int64, HostProfile> host_profiles = 1;
}

message GetBDProfileRequest {
  RequestMeta meta = 1;
  int64 user_id = 2;
  string role = 3;
}

message GetBDProfileResponse {
  BDProfile bd_profile = 1;
}

message GetCoinSellerProfileRequest {
  RequestMeta meta = 1;
  int64 user_id = 2;
}

message GetCoinSellerProfileResponse {
  CoinSellerProfile coin_seller_profile = 1;
}

message ListActiveCoinSellersInMyRegionRequest {
  RequestMeta meta = 1;
  int64 user_id = 2;
}

message ListActiveCoinSellersInMyRegionResponse {
  repeated CoinSellerListItem coin_sellers = 1;
}

message CreateSubCoinSellerRequest {
  RequestMeta meta = 1;
  string command_id = 2;
  int64 parent_user_id = 3;
  int64 child_user_id = 4;
}

message CreateSubCoinSellerResponse {
  CoinSellerSubRelation relation = 1;
  CoinSellerListItem child = 2;
}

message SubmitSubCoinSellerApplicationRequest {
  RequestMeta meta = 1;
  string command_id = 2;
  int64 parent_user_id = 3;
  int64 target_user_id = 4;
}

message SubmitSubCoinSellerApplicationResponse {
  CoinSellerSubApplication application = 1;
}

message ListSubCoinSellersRequest {
  RequestMeta meta = 1;
  int64 parent_user_id = 2;
  int32 page = 3;
  int32 page_size = 4;
}

message ListSubCoinSellersResponse {
  repeated CoinSellerListItem children = 1;
  int64 total = 2;
  int32 page = 3;
  int32 page_size = 4;
}

message CheckCoinSellerSubRelationRequest {
  RequestMeta meta = 1;
  int64 parent_user_id = 2;
  int64 child_user_id = 3;
}

message CheckCoinSellerSubRelationResponse {
  bool allowed = 1;
  string reason = 2;
  CoinSellerListItem child = 3;
}

message GetUserRoleSummaryRequest {
  RequestMeta meta = 1;
  int64 user_id = 2;
}

message GetUserRoleSummaryResponse {
  UserRoleSummary summary = 1;
}

message GetAgencyRequest {
  RequestMeta meta = 1;
  int64 agency_id = 2;
}

message GetAgencyResponse {
  Agency agency = 1;
}

message CheckBusinessCapabilityRequest {
  RequestMeta meta = 1;
  int64 actor_user_id = 2;
  string capability = 3;
}

message CheckBusinessCapabilityResponse {
  bool allowed = 1;
  string reason = 2;
}

// RoleScopePolicy 是 App 级角色拓展边界；调用方只消费 scope，不直接判断具体 app_code。
message RoleScopePolicy {
  string scene = 1;
  string base_scope = 2;
  bool region_expansion_configurable = 3;
  // expanded_scope 是经理通用范围开关开启后的范围；调用方不能自行假设一定是 region。
  string expanded_scope = 4;
  int64 updated_at_ms = 5;
}

message GetRoleScopePolicyRequest {
  RequestMeta meta = 1;
  string scene = 2;
}

message GetRoleScopePolicyResponse {
  RoleScopePolicy policy = 1;
}

message UpdateRoleScopePoliciesRequest {
  RequestMeta meta = 1;
  // 两个 scene 必须一起提交，user-service 在同一事务内保存完整 App 快照。
  repeated RoleScopePolicy policies = 2;
}

message UpdateRoleScopePoliciesResponse {
  repeated RoleScopePolicy policies = 1;
}

message GetAgencyMembersRequest {
  RequestMeta meta = 1;
  int64 agency_id = 2;
  string status = 3;
}

message GetAgencyMembersResponse {
  repeated AgencyMembership memberships = 1;
}

message GetAgencyApplicationsRequest {
  RequestMeta meta = 1;
  int64 agency_id = 2;
  string status = 3;
}

message GetAgencyApplicationsResponse {
  repeated AgencyApplication applications = 1;
}

message CreateBDLeaderRequest {
  RequestMeta meta = 1;
  string command_id = 2;
  int64 admin_user_id = 3;
  int64 target_user_id = 4;
  string reason = 5;
}

message CreateBDLeaderResponse {
  BDProfile bd_profile = 1;
}

message CreateBDRequest {
  RequestMeta meta = 1;
  string command_id = 2;
  int64 admin_user_id = 3;
  int64 target_user_id = 4;
  int64 parent_leader_user_id = 5;
  string reason = 6;
}

message CreateBDResponse {
  BDProfile bd_profile = 1;
}

message SetBDStatusRequest {
  RequestMeta meta = 1;
  string command_id = 2;
  int64 admin_user_id = 3;
  int64 target_user_id = 4;
  string status = 5;
  string reason = 6;
  string role = 7;
}

message SetBDStatusResponse {
  BDProfile bd_profile = 1;
}

message CreateCoinSellerRequest {
  RequestMeta meta = 1;
  string command_id = 2;
  int64 admin_user_id = 3;
  int64 target_user_id = 4;
  string reason = 5;
  optional bool can_manage_sub_coin_sellers = 6;
}

message CreateCoinSellerResponse {
  CoinSellerProfile coin_seller_profile = 1;
}

message SetCoinSellerStatusRequest {
  RequestMeta meta = 1;
  string command_id = 2;
  int64 admin_user_id = 3;
  int64 target_user_id = 4;
  string status = 5;
  string reason = 6;
  optional bool can_manage_sub_coin_sellers = 7;
}

message SetCoinSellerStatusResponse {
  CoinSellerProfile coin_seller_profile = 1;
}

message ReviewSubCoinSellerApplicationRequest {
  RequestMeta meta = 1;
  string command_id = 2;
  int64 admin_user_id = 3;
  int64 application_id = 4;
  string decision = 5;
  string reason = 6;
}

message ReviewSubCoinSellerApplicationResponse {
  CoinSellerSubApplication application = 1;
  CoinSellerSubRelation relation = 2;
  CoinSellerListItem child = 3;
}

message CreateAgencyRequest {
  RequestMeta meta = 1;
  string command_id = 2;
  int64 admin_user_id = 3;
  int64 owner_user_id = 4;
  int64 parent_bd_user_id = 5;
  string name = 6;
  bool join_enabled = 7;
  // Deprecated: Agency 不再限制主播数量，服务端会忽略该字段。
  int32 max_hosts = 8;
  string reason = 9;
}

message CreateAgencyResponse {
  Agency agency = 1;
  HostProfile host_profile = 2;
  AgencyMembership membership = 3;
}

message AdminAddAgencyHostRequest {
  RequestMeta meta = 1;
  string command_id = 2;
  int64 admin_user_id = 3;
  int64 agency_id = 4;
  int64 target_user_id = 5;
  string reason = 6;
}

message AdminAddAgencyHostResponse {
  Agency agency = 1;
  HostProfile host_profile = 2;
  AgencyMembership membership = 3;
}

message CloseAgencyRequest {
  RequestMeta meta = 1;
  string command_id = 2;
  int64 admin_user_id = 3;
  int64 agency_id = 4;
  string reason = 5;
}

message CloseAgencyResponse {
  Agency agency = 1;
}

message DeleteAgencyRequest {
  RequestMeta meta = 1;
  string command_id = 2;
  int64 admin_user_id = 3;
  int64 agency_id = 4;
  string reason = 5;
}

message DeleteAgencyResponse {
  Agency agency = 1;
}

message SetAgencyStatusRequest {
  RequestMeta meta = 1;
  string command_id = 2;
  int64 admin_user_id = 3;
  int64 agency_id = 4;
  string status = 5;
  string reason = 6;
}

message SetAgencyStatusResponse {
  Agency agency = 1;
}

message SetAgencyJoinEnabledRequest {
  RequestMeta meta = 1;
  string command_id = 2;
  int64 admin_user_id = 3;
  int64 agency_id = 4;
  bool join_enabled = 5;
  string reason = 6;
}

message SetAgencyJoinEnabledResponse {
  Agency agency = 1;
}

message UpdateAgencyProfileRequest {
  RequestMeta meta = 1;
  string command_id = 2;
  int64 operator_user_id = 3;
  int64 agency_id = 4;
  optional string name = 5;
  optional string avatar = 6;
}

message UpdateAgencyProfileResponse {
  Agency agency = 1;
}

// HostEngagementStats 是 Fami 等公会中心使用的用户侧统计聚合；金额/礼物流水由 wallet-service 单独拥有。
message HostEngagementStats {
  int64 online_duration_ms = 1;
  int64 valid_mic_duration_ms = 2;
  int64 valid_mic_days = 3;
  int64 private_message_senders = 4;
  int64 new_followers = 5;
}

message GetHostEngagementStatsRequest {
  RequestMeta meta = 1;
  int64 host_user_id = 2;
  int64 start_at_ms = 3;
  int64 end_at_ms = 4;
}

message GetHostEngagementStatsResponse {
  HostEngagementStats stats = 1;
}

// RecordPrivateMessageEvent 由经过腾讯回调鉴权的 gateway 写入私信事实；重复 event_id 必须幂等。
message RecordPrivateMessageEventRequest {
  RequestMeta meta = 1;
  string event_id = 2;
  int64 sender_user_id = 3;
  int64 target_user_id = 4;
  int64 occurred_at_ms = 5;
}

message RecordPrivateMessageEventResponse {
  bool created = 1;
}

// UserHostService 是 user-service 内部 host domain 的 gRPC 面，不是独立微服务。
service UserHostService {
  rpc SearchAgencies(SearchAgenciesRequest) returns (SearchAgenciesResponse);
  rpc ApplyToAgency(ApplyToAgencyRequest) returns (ApplyToAgencyResponse);
  rpc ReviewAgencyApplication(ReviewAgencyApplicationRequest) returns (ReviewAgencyApplicationResponse);
  rpc KickAgencyHost(KickAgencyHostRequest) returns (KickAgencyHostResponse);
  rpc InviteAgency(InviteAgencyRequest) returns (InviteAgencyResponse);
  rpc InviteBD(InviteBDRequest) returns (InviteBDResponse);
  rpc InviteHost(InviteHostRequest) returns (InviteHostResponse);
  rpc ListBDLeaderBDs(ListBDLeaderBDsRequest) returns (ListBDLeaderBDsResponse);
  rpc ListBDLeaderAgencies(ListBDLeaderAgenciesRequest) returns (ListBDLeaderAgenciesResponse);
  rpc ListBDAgencies(ListBDAgenciesRequest) returns (ListBDAgenciesResponse);
  // ListManagerTeamAgencies 返回经理团队树内全部有效 Agency；经理中心团队工资统计据此圈定主播归属范围。
  rpc ListManagerTeamAgencies(ListManagerTeamAgenciesRequest) returns (ListManagerTeamAgenciesResponse);
  rpc ListRoleInvitations(ListRoleInvitationsRequest) returns (ListRoleInvitationsResponse);
  rpc GetRoleInvitation(GetRoleInvitationRequest) returns (GetRoleInvitationResponse);
  rpc ProcessRoleInvitation(ProcessRoleInvitationRequest) returns (ProcessRoleInvitationResponse);
  rpc GetHostProfile(GetHostProfileRequest) returns (GetHostProfileResponse);
  rpc BatchGetHostProfiles(BatchGetHostProfilesRequest) returns (BatchGetHostProfilesResponse);
  rpc GetBDProfile(GetBDProfileRequest) returns (GetBDProfileResponse);
  rpc GetCoinSellerProfile(GetCoinSellerProfileRequest) returns (GetCoinSellerProfileResponse);
  rpc ListActiveCoinSellersInMyRegion(ListActiveCoinSellersInMyRegionRequest) returns (ListActiveCoinSellersInMyRegionResponse);
  rpc CreateSubCoinSeller(CreateSubCoinSellerRequest) returns (CreateSubCoinSellerResponse);
  rpc SubmitSubCoinSellerApplication(SubmitSubCoinSellerApplicationRequest) returns (SubmitSubCoinSellerApplicationResponse);
  rpc ListSubCoinSellers(ListSubCoinSellersRequest) returns (ListSubCoinSellersResponse);
  rpc CheckCoinSellerSubRelation(CheckCoinSellerSubRelationRequest) returns (CheckCoinSellerSubRelationResponse);
  rpc GetUserRoleSummary(GetUserRoleSummaryRequest) returns (GetUserRoleSummaryResponse);
  rpc GetAgency(GetAgencyRequest) returns (GetAgencyResponse);
  rpc CheckBusinessCapability(CheckBusinessCapabilityRequest) returns (CheckBusinessCapabilityResponse);
  rpc GetRoleScopePolicy(GetRoleScopePolicyRequest) returns (GetRoleScopePolicyResponse);
  rpc GetAgencyMembers(GetAgencyMembersRequest) returns (GetAgencyMembersResponse);
  rpc GetAgencyApplications(GetAgencyApplicationsRequest) returns (GetAgencyApplicationsResponse);
  rpc UpdateAgencyProfile(UpdateAgencyProfileRequest) returns (UpdateAgencyProfileResponse);
  rpc GetHostEngagementStats(GetHostEngagementStatsRequest) returns (GetHostEngagementStatsResponse);
  rpc RecordPrivateMessageEvent(RecordPrivateMessageEventRequest) returns (RecordPrivateMessageEventResponse);
}

// UserHostAdminService 是后台关系管理入口；公网 admin 鉴权由 admin-server 承担。
service UserHostAdminService {
  // UpdateRoleScopePolicies 是后台修改角色范围的唯一写入口，配置事实归 user DB 所有。
  rpc UpdateRoleScopePolicies(UpdateRoleScopePoliciesRequest) returns (UpdateRoleScopePoliciesResponse);
  rpc CreateBDLeader(CreateBDLeaderRequest) returns (CreateBDLeaderResponse);
  rpc CreateBD(CreateBDRequest) returns (CreateBDResponse);
  rpc SetBDStatus(SetBDStatusRequest) returns (SetBDStatusResponse);
  rpc CreateCoinSeller(CreateCoinSellerRequest) returns (CreateCoinSellerResponse);
  rpc SetCoinSellerStatus(SetCoinSellerStatusRequest) returns (SetCoinSellerStatusResponse);
  rpc ReviewSubCoinSellerApplication(ReviewSubCoinSellerApplicationRequest) returns (ReviewSubCoinSellerApplicationResponse);
  rpc CreateAgency(CreateAgencyRequest) returns (CreateAgencyResponse);
  rpc AdminAddAgencyHost(AdminAddAgencyHostRequest) returns (AdminAddAgencyHostResponse);
  rpc CloseAgency(CloseAgencyRequest) returns (CloseAgencyResponse);
  rpc DeleteAgency(DeleteAgencyRequest) returns (DeleteAgencyResponse);
  rpc SetAgencyStatus(SetAgencyStatusRequest) returns (SetAgencyStatusResponse);
  rpc SetAgencyJoinEnabled(SetAgencyJoinEnabledRequest) returns (SetAgencyJoinEnabledResponse);
  // ExternalInvite* 是外管平台唯一邀请入口；区域和所选父级在 user-service 事务内重验。
  rpc ExternalInviteBD(ExternalInviteBDRequest) returns (ExternalInviteBDResponse);
  rpc ExternalInviteAgency(ExternalInviteAgencyRequest) returns (ExternalInviteAgencyResponse);
  rpc ExternalInviteHost(ExternalInviteHostRequest) returns (ExternalInviteHostResponse);
  // 团队 scope 为空或 region_id 无效时 fail-closed，不会退化成全 App 列表。
  rpc ListExternalTeamUsers(ListExternalTeamUsersRequest) returns (ListExternalTeamUsersResponse);
  rpc SearchExternalInvitationCandidate(SearchExternalInvitationCandidateRequest) returns (SearchExternalInvitationCandidateResponse);
}
