export const CommandType = {
  SaveMessage: 'save-message',
  DeleteMessage: 'delete-message',
  UpdateMessage: 'update-message',
  ClearRoomMessages: 'clear-room-messages',
  SaveReaction: 'save-reaction',
  RemoveReaction: 'remove-reaction',
  SaveUser: 'save-user',
  SetCurrentUserId: 'set-current-user-id',
  UpdateUser: 'update-user',
  SaveRoom: 'save-room',
  DeleteRoom: 'delete-room',
  UpdateRoom: 'update-room',
  SaveBan: 'save-ban',
  RemoveBan: 'remove-ban',
  SaveAttachment: 'save-attachment',
  DeleteAttachmentsForMessage: 'delete-attachments-for-message',
  SavePluginData: 'save-plugin-data',
  DeletePluginData: 'delete-plugin-data',
  SaveMeta: 'save-meta',
  ClearAllData: 'clear-all-data'
} as const;

export type CommandTypeKey = typeof CommandType[keyof typeof CommandType];

export const QueryType = {
  GetMessages: 'get-messages',
  GetMessagesSince: 'get-messages-since',
  GetMessageById: 'get-message-by-id',
  GetReactionsForMessage: 'get-reactions-for-message',
  GetUser: 'get-user',
  GetCurrentUser: 'get-current-user',
  GetCurrentUserId: 'get-current-user-id',
  GetUsersByRoom: 'get-users-by-room',
  GetRoom: 'get-room',
  GetAllRooms: 'get-all-rooms',
  GetBansForRoom: 'get-bans-for-room',
  IsUserBanned: 'is-user-banned',
  GetAttachmentsForMessage: 'get-attachments-for-message',
  GetAllAttachments: 'get-all-attachments',
  GetPluginData: 'get-plugin-data',
  GetMeta: 'get-meta'
} as const;

export type QueryTypeKey = typeof QueryType[keyof typeof QueryType];

export interface MessagePayload {
  id: string;
  roomId: string;
  channelId?: string;
  senderId: string;
  senderName: string;
  content: string;
  timestamp: number;
  editedAt?: number;
  reactions?: ReactionPayload[];
  isDeleted?: boolean;
  replyToId?: string;
  linkMetadata?: { url: string; title?: string; description?: string; imageUrl?: string; siteName?: string; failed?: boolean }[];
}

export interface ReactionPayload {
  id: string;
  messageId: string;
  oderId: string;
  userId: string;
  emoji: string;
  timestamp: number;
}

export type PermissionStatePayload = 'allow' | 'deny' | 'inherit';

export type RoomPermissionKeyPayload =
  | 'manageServer'
  | 'manageRoles'
  | 'manageChannels'
  | 'manageIcon'
  | 'kickMembers'
  | 'banMembers'
  | 'manageBans'
  | 'deleteMessages'
  | 'joinVoice'
  | 'shareScreen'
  | 'uploadFiles';

export interface AccessRolePayload {
  id: string;
  name: string;
  color?: string;
  position: number;
  isSystem?: boolean;
  permissions?: Partial<Record<RoomPermissionKeyPayload, PermissionStatePayload>>;
}

export interface RoleAssignmentPayload {
  userId: string;
  oderId?: string;
  roleIds: string[];
}

export interface ChannelPermissionPayload {
  channelId: string;
  targetType: 'role' | 'user';
  targetId: string;
  permission: RoomPermissionKeyPayload;
  value: PermissionStatePayload;
}

export interface UserPayload {
  id: string;
  oderId?: string;
  username?: string;
  displayName?: string;
  description?: string;
  profileUpdatedAt?: number;
  avatarUrl?: string;
  avatarHash?: string;
  avatarMime?: string;
  avatarUpdatedAt?: number;
  status?: string;
  role?: string;
  joinedAt?: number;
  peerId?: string;
  isOnline?: boolean;
  isAdmin?: boolean;
  isRoomOwner?: boolean;
  voiceState?: unknown;
  screenShareState?: unknown;
}

export interface RoomPayload {
  id: string;
  name: string;
  description?: string;
  topic?: string;
  hostId: string;
  password?: string;
  hasPassword?: boolean;
  isPrivate?: boolean;
  createdAt: number;
  userCount?: number;
  maxUsers?: number;
  icon?: string;
  iconUpdatedAt?: number;
  slowModeInterval?: number;
  permissions?: unknown;
  channels?: unknown[];
  members?: unknown[];
  roles?: AccessRolePayload[];
  roleAssignments?: RoleAssignmentPayload[];
  channelPermissions?: ChannelPermissionPayload[];
  sourceId?: string;
  sourceName?: string;
  sourceUrl?: string;
}

export interface BanPayload {
  oderId: string;
  roomId: string;
  userId?: string;
  bannedBy: string;
  displayName?: string;
  reason?: string;
  expiresAt?: number;
  timestamp: number;
}

export interface AttachmentPayload {
  id: string;
  messageId: string;
  filename: string;
  size: number;
  mime: string;
  isImage?: boolean;
  uploaderPeerId?: string;
  filePath?: string;
  savedPath?: string;
}

export type PluginDataScopePayload = 'local' | 'server';

export interface PluginDataPayload {
  key: string;
  pluginId: string;
  scope: PluginDataScopePayload;
  serverId?: string;
  value: unknown;
}

export interface SaveMessageCommand { type: typeof CommandType.SaveMessage; payload: { message: MessagePayload } }
export interface DeleteMessageCommand { type: typeof CommandType.DeleteMessage; payload: { messageId: string } }
export interface UpdateMessageCommand { type: typeof CommandType.UpdateMessage; payload: { messageId: string; updates: Partial<MessagePayload> } }
export interface ClearRoomMessagesCommand { type: typeof CommandType.ClearRoomMessages; payload: { roomId: string } }
export interface SaveReactionCommand { type: typeof CommandType.SaveReaction; payload: { reaction: ReactionPayload } }
export interface RemoveReactionCommand { type: typeof CommandType.RemoveReaction; payload: { messageId: string; userId: string; emoji: string } }
export interface SaveUserCommand { type: typeof CommandType.SaveUser; payload: { user: UserPayload } }
export interface SetCurrentUserIdCommand { type: typeof CommandType.SetCurrentUserId; payload: { userId: string } }
export interface UpdateUserCommand { type: typeof CommandType.UpdateUser; payload: { userId: string; updates: Partial<UserPayload> } }
export interface SaveRoomCommand { type: typeof CommandType.SaveRoom; payload: { room: RoomPayload } }
export interface DeleteRoomCommand { type: typeof CommandType.DeleteRoom; payload: { roomId: string } }
export interface UpdateRoomCommand { type: typeof CommandType.UpdateRoom; payload: { roomId: string; updates: Partial<RoomPayload> } }
export interface SaveBanCommand { type: typeof CommandType.SaveBan; payload: { ban: BanPayload } }
export interface RemoveBanCommand { type: typeof CommandType.RemoveBan; payload: { oderId: string } }
export interface SaveAttachmentCommand { type: typeof CommandType.SaveAttachment; payload: { attachment: AttachmentPayload } }
export interface DeleteAttachmentsForMessageCommand { type: typeof CommandType.DeleteAttachmentsForMessage; payload: { messageId: string } }
export interface SavePluginDataCommand { type: typeof CommandType.SavePluginData; payload: PluginDataPayload }
export interface DeletePluginDataCommand { type: typeof CommandType.DeletePluginData; payload: Omit<PluginDataPayload, 'value'> }
export interface SaveMetaCommand { type: typeof CommandType.SaveMeta; payload: { key: string; value: string | null } }
export interface ClearAllDataCommand { type: typeof CommandType.ClearAllData; payload: Record<string, never> }

export type Command =
  | SaveMessageCommand
  | DeleteMessageCommand
  | UpdateMessageCommand
  | ClearRoomMessagesCommand
  | SaveReactionCommand
  | RemoveReactionCommand
  | SaveUserCommand
  | SetCurrentUserIdCommand
  | UpdateUserCommand
  | SaveRoomCommand
  | DeleteRoomCommand
  | UpdateRoomCommand
  | SaveBanCommand
  | RemoveBanCommand
  | SaveAttachmentCommand
  | DeleteAttachmentsForMessageCommand
  | SavePluginDataCommand
  | DeletePluginDataCommand
  | SaveMetaCommand
  | ClearAllDataCommand;

export interface GetMessagesQuery {
  type: typeof QueryType.GetMessages;
  payload: {
    roomId: string;
    limit?: number;
    offset?: number;
    channelId?: string;
    beforeTimestamp?: number;
  };
}
export interface GetMessagesSinceQuery { type: typeof QueryType.GetMessagesSince; payload: { roomId: string; sinceTimestamp: number } }
export interface GetMessageByIdQuery { type: typeof QueryType.GetMessageById; payload: { messageId: string } }
export interface GetReactionsForMessageQuery { type: typeof QueryType.GetReactionsForMessage; payload: { messageId: string } }
export interface GetUserQuery { type: typeof QueryType.GetUser; payload: { userId: string } }
export interface GetCurrentUserQuery { type: typeof QueryType.GetCurrentUser; payload: Record<string, never> }
export interface GetCurrentUserIdQuery { type: typeof QueryType.GetCurrentUserId; payload: Record<string, never> }
export interface GetUsersByRoomQuery { type: typeof QueryType.GetUsersByRoom; payload: { roomId: string } }
export interface GetRoomQuery { type: typeof QueryType.GetRoom; payload: { roomId: string } }
export interface GetAllRoomsQuery { type: typeof QueryType.GetAllRooms; payload: Record<string, never> }
export interface GetBansForRoomQuery { type: typeof QueryType.GetBansForRoom; payload: { roomId: string } }
export interface IsUserBannedQuery { type: typeof QueryType.IsUserBanned; payload: { userId: string; roomId: string } }
export interface GetAttachmentsForMessageQuery { type: typeof QueryType.GetAttachmentsForMessage; payload: { messageId: string } }
export interface GetAllAttachmentsQuery { type: typeof QueryType.GetAllAttachments; payload: Record<string, never> }
export interface GetPluginDataQuery { type: typeof QueryType.GetPluginData; payload: Omit<PluginDataPayload, 'value'> }
export interface GetMetaQuery { type: typeof QueryType.GetMeta; payload: { key: string } }

export type Query =
  | GetMessagesQuery
  | GetMessagesSinceQuery
  | GetMessageByIdQuery
  | GetReactionsForMessageQuery
  | GetUserQuery
  | GetCurrentUserQuery
  | GetCurrentUserIdQuery
  | GetUsersByRoomQuery
  | GetRoomQuery
  | GetAllRoomsQuery
  | GetBansForRoomQuery
  | IsUserBannedQuery
  | GetAttachmentsForMessageQuery
  | GetAllAttachmentsQuery
  | GetPluginDataQuery
  | GetMetaQuery;
