/**
 * 会议室相关类型定义
 * 提供会议功能所需的接口和类型
 *
 * 设计原则：
 * 1. 优先使用响应式状态（ref/reactive）而非回调函数
 * 2. 类型定义清晰完整，包含详细注释
 * 3. 分离关注点：基础类型、消息类型、Hook 返回类型
 */
import type { MeetingToken } from '@/api/meeting';
import type { Socket as IOSocket } from 'socket.io-client';
import type { IAgoraRTCClient, IAgoraRTCRemoteUser, ICameraVideoTrack, IMicrophoneAudioTrack } from 'agora-rtc-sdk-ng';
// ============================================================================
// 基础数据类型
// ============================================================================

/**
 * 本地用户对象类型
 * 用于统一本地用户与远程用户的展示结构
 */
export interface LocalUser {
  /** 用户唯一标识符 */
  uid: number | string;
  /** 是否为本地用户 */
  isLocal: boolean;
  /** 本地摄像头视频轨道 */
  videoTrack: ICameraVideoTrack | null;
  /** 本地麦克风音频轨道 */
  audioTrack: IMicrophoneAudioTrack | null;
  /** 用户显示名称 */
  userName: string;
}

/**
 * 展示用户通用接口（本地用户或远程用户共同属性）
 * 用于 displayUsers 列表中统一处理模板访问
 */
export interface DisplayUser {
  /** 用户唯一标识符 */
  uid: number | string;
  /** 是否为本地用户，远程用户不存在此字段 */
  isLocal?: boolean;
  /** 用户显示名称，远程用户不存在此字段 */
  userName?: string;
}

/**
 * 网络质量等级
 */
export type NetworkQualityLevel = 'fair' | 'good' | 'poor';

/**
 * 双流模式类型
 * 0 = 高流（高清视频）
 * 1 = 低流（低分辨率视频，节省流量）
 */
export type StreamType = 0 | 1;

/**
 * 课堂状态
 */
export type ClassStatus = 'finished' | 'in_class' | 'not_started';

/**
 * 用户角色
 */
export type UserRole = 'student' | 'teacher';

/**
 * 加入方式
 */
export type JoinMode = 'classroom' | 'monitor' | 'student';

// ============================================================================
// 会议状态（响应式状态替代回调）
// ============================================================================

/**
 * 会议状态聚合
 * 使用响应式状态替代回调函数，方便组件直接使用
 */
export interface MeetingState {
  /** 是否已加入频道 */
  isJoined: boolean;
  /** 是否静音 */
  isMuted: boolean;
  /** 是否关闭视频 */
  isVideoOff: boolean;
  /** 静音操作加载状态 */
  muteLoading: boolean;
  /** 视频操作加载状态 */
  videoLoading: boolean;
  /** 离开操作加载状态 */
  leaveLoading: boolean;
  /** 网络质量等级 */
  networkQuality: NetworkQualityLevel;
  /** 远程用户列表 */
  remoteUsers: IAgoraRTCRemoteUser[];
  /** 本地用户 */
  localUser: LocalUser;
  /** 当前选中的主视频用户 ID */
  selectedUserUid: number | string | null;
  /** 声网 RTC 客户端 */
  client: IAgoraRTCClient | null;
}

/**
 * 权限状态聚合
 * 使用响应式状态管理用户权限
 */
export interface PermissionsState {
  /** 用户权限映射 */
  userPermissions: Map<number | string, UserPermission>;
  /** 是否正在发送控制消息 */
  isSending: boolean;
}

/**
 * 用户权限
 */
export interface UserPermission {
  /** 用户 ID */
  uid: number | string;
  /** 是否被禁麦 */
  isAudioMuted: boolean;
  /** 是否被禁视频 */
  isVideoMuted: boolean;
  /** 是否被踢出 */
  isKicked: boolean;
}

/**
 * 双流状态聚合
 */
export interface StreamTypeState {
  /** 主视频用户 ID */
  mainVideoUid: number | string | null;
  /** 用户流类型映射 */
  userStreamTypes: Map<number | string, StreamType>;
}

// ============================================================================
// WebSocket 消息基础类型
// ============================================================================

/**
 * 通用 WebSocket 消息包结构
 */
export interface WebSocketPacket<T extends string, D = unknown> {
  type: T;
  data: D;
}

// ============================================================================
// WebSocket 上行消息（客户端 -> 后端）
// ============================================================================

/**
 * 加入房间请求的数据结构
 */
export interface SendJoinRoomData {
  /** 课程房间 ID（前端传入） */
  courseRoomId: string;
  /** 用户显示名称 */
  userName: string;
  /** 作业 ID */
  homeworkId: number;
  /** 加入方式（课程/监控/学生） */
  joinMode: JoinMode;
  /** 房间结束时间（毫秒时间戳），仅老师端首次进入时会写入 */
  endTimestamp?: number;
}

/**
 * 离开房间请求的数据结构
 */
// 调整为允许可选的 courseRoomId，兼容现有调用
export interface SendLeaveRoomData {
  /** 课程房间 ID（可选，后端主要依赖 socket.data.roomId） */
  courseRoomId?: string;
}

/**
 * 踢人请求的数据结构
 */
export interface SendKickUserData {
  /** 目标用户 ID */
  targetUid: number | string;
  /** 房间 ID */
  roomId: string;
}

/**
 * 禁麦/禁视频请求的数据结构
 */
export interface SendMuteUserData {
  /** 目标用户 ID */
  targetUid: number | string;
  /** 房间 ID */
  roomId: string;
}

/**
 * WebSocket 消息包 - 客户端发送：设置主屏请求
 */
export type SendSetMainVideoPacket = WebSocketPacket<'client_set_main_video', SendMuteUserData>;

/**
 * WebSocket 消息包 - 客户端发送：加入房间请求
 */
export type SendJoinRoomPacket = WebSocketPacket<'client_join_room', SendJoinRoomData>;

/**
 * WebSocket 消息包 - 客户端发送：离开房间请求
 */
export type SendLeaveRoomPacket = WebSocketPacket<'client_leave_room', SendLeaveRoomData>;

/**
 * WebSocket 消息包 - 客户端发送：踢人请求
 */
export type SendKickUserPacket = WebSocketPacket<'client_kick_user', SendKickUserData>;

/**
 * WebSocket 消息包 - 客户端发送：禁麦请求
 */
export type SendMuteAudioPacket = WebSocketPacket<'client_mute_audio', SendMuteUserData>;

/**
 * WebSocket 消息包 - 客户端发送：禁视频请求
 */
export type SendMuteVideoPacket = WebSocketPacket<'client_mute_video', SendMuteUserData>;

/**
 * WebSocket 消息包 - 客户端发送：解除禁麦请求
 */
export type SendUnmuteAudioPacket = WebSocketPacket<'client_unmute_audio', SendMuteUserData>;

/**
 * WebSocket 消息包 - 客户端发送：解除禁视频请求
 */
export type SendUnmuteVideoPacket = WebSocketPacket<'client_unmute_video', SendMuteUserData>;

// ============================================================================
// WebSocket 下行消息（后端 -> 客户端）
// ============================================================================

/**
 * 加入房间成功响应的数据结构
 */
export interface OnJoinRoomData {
  /** 房间 ID（课程房间的真实 ID） */
  roomId: string;
  /** 会议专用的短用户 ID（用于声网 RTC 通信） */
  shortUid: number;
  /** 是否被禁麦*/
  isAudioMuted: boolean;
  /** 是否被禁视频 */
  isVideoMuted: boolean;
  /** 声网 RTC Token 信息 */
  tokenInfo: MeetingToken;
  /** 课堂状态 */
  classStatus?: ClassStatus;
  /** 投屏状态：正在投屏的用户短 UID，undefined 表示无人投屏 */
  screenShareUid?: number;
  screenShareOwnerUid?: number;
  /** 主讲人短 UID（默认等于 teacherUid） */
  speakerUid: number;
  /** 老师短 UID */
  teacherUid: number;
  /** 房间结束时间（毫秒时间戳） */
  endTimestamp?: number;
}

/**
 * 房间即将到期提醒数据
 */
export interface OnRoomWillExpireData {
  /** 来源房间 */
  fromRoomId: string;
  /** 房间结束时间（毫秒时间戳） */
  endTimestamp: number;
  /** 剩余毫秒数 */
  remainingMs: number;
}

/**
 * 房间结束时间更新数据
 */
export interface OnRoomEndTimestampUpdatedData {
  /** 来源房间 */
  fromRoomId: string;
  /** 房间结束时间（毫秒时间戳） */
  endTimestamp: number;
}

/**
 * 被踢出会议的数据结构
 */
export interface OnKickedData {
  /** 来源房间 ID（可选） */
  fromRoomId?: string;
  /** 目标用户 ID（可选） */
  targetUid?: number | string;
  /** 踢出原因（可选） */
  reason?: string;
}

/**
 * 控制消息的数据结构（禁麦/禁视频/踢人）
 */
export interface OnControlMessageData {
  /** 来源房间 ID（后端返回） */
  fromRoomId: string;
  /** 目标用户 ID（部分消息有） */
  targetUid?: number | string;
}

/**
 * 设置主屏的数据结构
 */
export interface OnSetMainVideoData extends OnControlMessageData {
  /** 被设置为主屏的用户 ID（短 UID） */
  targetUid: number;
}

/**
 * WebSocket 消息包 - 客户端接收：加入房间成功响应
 */
export type OnJoinRoomSuccessPacket = WebSocketPacket<'sev_join_room', OnJoinRoomData>;

/**
 * WebSocket 消息包 - 服务端下发：房间即将到期提醒
 */
export type OnRoomWillExpirePacket = WebSocketPacket<'sev_room_will_expire', OnRoomWillExpireData>;

/**
 * WebSocket 消息包 - 服务端下发：房间结束时间更新
 */
export type OnRoomEndTimestampUpdatedPacket = WebSocketPacket<'sev_room_end_timestamp_updated', OnRoomEndTimestampUpdatedData>;

/**
 * WebSocket 消息包 - 客户端接收：被踢出会议
 */
export type OnKickedPacket = WebSocketPacket<'sev_kick_user', OnKickedData>;

/**
 * WebSocket 消息包 - 客户端接收：禁麦通知
 */
export type OnMuteAudioPacket = WebSocketPacket<'sev_mute_audio', OnControlMessageData>;

/**
 * WebSocket 消息包 - 客户端接收：禁视频通知
 */
export type OnMuteVideoPacket = WebSocketPacket<'sev_mute_video', OnControlMessageData>;

/**
 * WebSocket 消息包 - 客户端接收：解除禁麦通知
 */
export type OnUnmuteAudioPacket = WebSocketPacket<'sev_unmute_audio', OnControlMessageData>;

/**
 * WebSocket 消息包 - 客户端接收：解除禁视频通知
 */
export type OnUnmuteVideoPacket = WebSocketPacket<'sev_unmute_video', OnControlMessageData>;

/**
 * WebSocket 消息包 - 客户端接收：设置主屏通知
 */
export type OnSetMainVideoPacket = WebSocketPacket<'sev_set_main_video', OnSetMainVideoData>;

/**
 * WebSocket 消息包 - 客户端接收：上课通知
 */
export type OnClassStartedPacket = WebSocketPacket<'sev_class_started', OnControlMessageData>;

/**
 * WebSocket 消息包 - 客户端接收：下课通知
 */
export type OnClassEndedPacket = WebSocketPacket<'sev_class_ended', OnControlMessageData>;

/**
 * WebSocket 消息包 - 客户端接收：设备冲突通知
 */
export type OnDeviceConflictPacket = WebSocketPacket<'sev_device_conflict', OnControlMessageData>;

// ============================================================================
// WebSocket 消息联合类型
// ============================================================================

/**
 * WebSocket 消息包 - 控制消息（下行：后端 -> 客户端）
 */
export type DownlinkControlMessagePacket =
  | OnClassEndedPacket
  | OnClassStartedPacket
  | OnDeviceConflictPacket
  | OnKickedPacket
  | OnMuteAudioPacket
  | OnMuteVideoPacket
  | OnRoomEndTimestampUpdatedPacket
  | OnRoomWillExpirePacket
  | OnScreenShareStartedPacket
  | OnScreenShareStoppedPacket
  | OnSetMainVideoPacket
  | OnUnmuteAudioPacket
  | OnUnmuteVideoPacket;

/**
 * WebSocket 消息包 - 控制消息（上行：客户端 -> 后端）
 */
export type UplinkControlMessagePacket =
  | SendKickUserPacket
  | SendMuteAudioPacket
  | SendMuteVideoPacket
  | SendSetMainVideoPacket
  | SendUnmuteAudioPacket
  | SendUnmuteVideoPacket;

/**
 * 控制指令类型（上行：客户端 -> 后端）
 */
export type ControlCommandType =
  | 'client_kick_user' // 踢出用户
  | 'client_mute_audio' // 禁麦（关闭用户麦克风）
  | 'client_mute_video' // 禁视频（关闭用户摄像头）
  | 'client_renew_room_end_timestamp' // 续期房间结束时间
  | 'client_set_main_video' // 设置主屏（指定大窗口显示的用户）
  | 'client_start_class' // 开始上课
  | 'client_start_screen_share' // 开始投屏
  | 'client_stop_screen_share' // 停止投屏
  | 'client_unmute_audio' // 解除禁麦
  | 'client_unmute_video'; // 解除禁视频

/**
 * 用户流类型配置
 */
export interface UserStreamConfig {
  /** 用户 ID */
  uid: number | string;
  /** 流类型 */
  streamType: StreamType;
}

// ============================================================================
// 屏幕共享相关类型
// ============================================================================

/**
 * 屏幕共享状态
 */
export interface ScreenShareState {
  /** 是否正在共享屏幕 */
  isScreenSharing: boolean;
  /** 屏幕共享的用户 ID 映射 */
  screenSharers: Map<number | string, ScreenSharerInfo>;
}

/**
 * 屏幕共享者信息
 */
export interface ScreenSharerInfo {
  /** 用户 ID */
  uid: number | string;
  /** 用户名称 */
  userName?: string;
  /** 是否正在共享 */
  isSharing: boolean;
}

/**
 * WebSocket 消息包 - 客户端发送：开始共享屏幕请求
 */
export interface SendStartScreenShareData {
  /** 房间 ID */
  roomId: string;
  /** 短 UID（可选，当前后端不需要） */
  shortUid?: number;
  screenUid: number;
}

/**
 * WebSocket 消息包 - 客户端发送：开始共享屏幕请求
 */
export type SendStartScreenSharePacket = WebSocketPacket<'client_start_screen_share', SendStartScreenShareData>;

/**
 * WebSocket 消息包 - 客户端发送：停止共享屏幕请求
 */
export interface SendStopScreenShareData {
  /** 房间 ID */
  roomId: string;
  screenUid?: number;
}

/**
 * WebSocket 消息包 - 客户端发送：停止共享屏幕请求
 */
export type SendStopScreenSharePacket = WebSocketPacket<'client_stop_screen_share', SendStopScreenShareData>;

/**
 * WebSocket 消息包 - 客户端接收：有人开始共享屏幕通知
 */
export interface OnScreenShareStartedData {
  /** 来源房间 ID */
  fromRoomId: string;
  /** 开始共享的用户 ID */
  targetUid: number;
  screenUid: number;
}

/**
 * WebSocket 消息包 - 客户端接收：有人开始共享屏幕通知
 */
export type OnScreenShareStartedPacket = WebSocketPacket<'sev_start_screen_share', OnScreenShareStartedData>;

/**
 * WebSocket 消息包 - 客户端接收：有人停止共享屏幕通知
 */
export interface OnScreenShareStoppedData {
  /** 来源房间 ID */
  fromRoomId: string;
  /** 停止共享的用户 ID */
  targetUid: number;
  screenUid?: number;
}

/**
 * WebSocket 消息包 - 客户端接收：有人停止共享屏幕通知
 */
export type OnScreenShareStoppedPacket = WebSocketPacket<'sev_stop_screen_share', OnScreenShareStoppedData>;

/**
 * 客户端 -> 服务端（上发事件定义，用于 typed socket）
 */
export interface ClientToServerEvents {
  client_join_room: (data: SendJoinRoomData) => void;
  client_leave_room: (data: SendLeaveRoomData) => void;
  client_kick_user: (data: SendKickUserData) => void;
  client_mute_audio: (data: SendMuteUserData) => void;
  client_unmute_audio: (data: SendMuteUserData) => void;
  client_mute_video: (data: SendMuteUserData) => void;
  client_unmute_video: (data: SendMuteUserData) => void;
  client_set_main_video: (data: SendMuteUserData) => void;
  client_start_class: (data: { roomId: string; meetingDuration?: number }) => void;
  client_end_class: (data: { roomId: string }) => void;
  client_start_screen_share: (data: SendStartScreenShareData) => void;
  client_stop_screen_share: (data: SendStopScreenShareData) => void;
  client_renew_room_end_timestamp: (data: { roomId: string; endTimestamp: number }) => void;
}

/**
 * 服务端 -> 客户端（下发事件定义，用于 typed socket）
 * 约定统一通过 'message' 下发
 */
export interface ServerToClientEvents {
  message: (packet: DownlinkControlMessagePacket | OnJoinRoomSuccessPacket) => void;
}

/**
 * 会议 Socket（socket.io-client）带泛型的类型别名
 */
export type MeetingClientSocket = IOSocket<ServerToClientEvents, ClientToServerEvents>;

// ============================================================================
// 会议事件回调（保留回调接口，因为回调也是合理的设计）
// ============================================================================

/**
 * 会议室事件回调
 * 注意：回调和响应式状态可以共存，根据场景选择合适的方式
 */
export interface MeetingEventCallbacks {
  /** 用户加入回调 */
  onUserJoined?: (user: IAgoraRTCRemoteUser) => void;
  /** 用户离开回调 */
  onUserLeft?: (user: IAgoraRTCRemoteUser) => void;
  /** 用户发布流回调 */
  onUserPublished?: (user: IAgoraRTCRemoteUser, mediaType: 'audio' | 'video') => void;
  /** 用户取消发布流回调 */
  onUserUnpublished?: (user: IAgoraRTCRemoteUser, mediaType: 'audio' | 'video') => void;
  /** 网络质量变化回调 */
  onNetworkQuality?: (quality: NetworkQualityLevel) => void;
  /** 连接状态变化回调 */
  onConnectionStateChange?: (state: string) => void;
  /** 被禁麦回调 */
  onAudioMutedByHost?: () => void;
  /** 被禁视频回调 */
  onVideoMutedByHost?: () => void;
  /** 被踢出回调 */
  onKickedByHost?: () => void;
  /** 错误回调 */
  onError?: (error: Error) => void;
  /** Token 即将过期回调 */
  onTokenWillExpire?: () => void;
  /** Token 已过期回调 */
  onTokenExpired?: () => void;
  /** 离开会议回调 */
  onLeft?: () => void;
  onLocalScreenShareEnded?: () => void;
}
